Émulation d'un joueur - inventaire
-
Bonjour,
J’ai quelque questions pour mon mods visant à implémenter une entité robotisée qui aurait des possibilités similaires à un joueur.
-
J’ai besoin que mon entité détruise des blocs. Pour l’instant j’utilise destroyBlockInWorldPartially() et destroyBlock() mais sans prendre en compte un éventuel outil ni même la force de frappe d’un joueur à mains nues. J’utilise un simple compteur de 0 à 10 pour les dégats qui s’incrémente à chaque tick. Ou puis-je trouver la méthode de calcul à appliquer à chaque tick (en fonction de l’outil) pour que le calcul simule de façon réaliste l’action sur le bloc ?
-
J’ai également besoin d’un inventaire similaire à celui d’un joueur. Je pense reprendre la classe InventoryBasic (net.minecraft.inventory) qui as l’air d’être ce qu’il me faut (sauf si qqun a une meilleur idée). Toutefois j’aimerais également que l’inventaire du robot soit consultable. Par exemple par un clic droit sur l’entité. Je souhaiterais donc savoir si il existe une façon simple de reprendre le code déjà mis en place pour l’affichage du gui inventaire (touche e) et de rappeler les méthodes nécessaire à l’affichage depuis une méthode d’interaction dans le code de l’entité.
accessoirement : 3) Pour l’instant je suis en 1.6.2 (j’ai commencé en aout 2013). Si je passe en 1.7, le risque d’incompatibilité est-il important ? J’aimerai avoir un environnement à jour mais j’ai peur d’y perdre trop de temps.
Je cherche de mon coté en attendant mais si quelqu’un sait m’aiguiller vers un bonne piste ça m’aiderait pas mal, merci.
-
-
-
Regarde du côté des comportements du joueur.
-
Regarde juste le code de l’inventaire.
-
TRES IMPORTANT la mise à jour 1.6->1.7 est très dure mais très importante.
-
-
-
world.getBlock(x, y, z).getBlockHardness(world, x, y, z) donne l’hardness du bloc.
-
Passe par la 1.6.4 d’abord, C’EST TRÈS IMPORTANT et enregistre bien tout tes blocs et tout tes items.
-
-
-
Parmis ce que j’ai trouvé, getCurrentPlayerStrVsBlock() de entityplayer semble calculer un facteur de force qui est à de multiples endroit comme dans updateBlockRemoving() de ItemInWorldManager multiplié par 10 puis utilisé comme valeur de dégat pour destroyBlockInWorldPartially. Si je recalcule ce facteur de force sur base des objets de l’entité est-ce que cela donnerai le même effet que pour un joueur ?
-
Dans quelle classe inventaire plus précisément ? Parce que j’en ai croisé plusieurs mais je n’ai pas vu de code spécifique à une gui.
-
Ok, vu la réaction su ce point je vais pas tarder à update alors ^^
-
-
- Ok, sur ce point à force de bidouiller j’ai fini par réussir à le faire à partir d’un bloc, le passage a une entité devrait pas être trop dur. Par contre j’ai un problème étrange de texture :
Ma texture fait 176x165, dans ma classe qui étend GuiContainer, j’ai tapé ceci :
package PLCmods.robotica.gui; import org.lwjgl.opengl.GL11; import cpw.mods.fml.client.FMLClientHandler; … import net.minecraft.util.ResourceLocation; public class TestGuiContainer extends GuiContainer { public static final ResourceLocation texture = new ResourceLocation(Robotica.SID, "textures/gui/robotinv2.png"); public TestGuiContainer(InventoryPlayer inventory, TestTileEntity te) { super(new TestContainer(inventory, te)); xSize = 176; ySize = 165; } @Override protected void drawGuiContainerBackgroundLayer(float f, int i, int j) { GL11.glColor4f(1F, 1F, 1F, 1F); FMLClientHandler.instance().getClient().renderEngine.func_110577_a(texture); drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); } }
Le problème c’est que la texture prend la place qu’elle doit prendre mais elle est zoomée sur le coin supérieur gauche. Si j’enlève le fichier texture celle par défaut (rose / noire) est chargée à la place mais celle ci est aussi zoomée (la case sup. gauche est complète mais pas les autres). Quelqu’un sait pourquoi ? Vu que la texture par défaut à le même effet ce doit être que je fais une bêtise dans le code …
-
avec ça ?
int x = (this.width - this.xSize) / 2; int y = (this.height - this.ySize) / 2; this.drawTexturedModalRect(x, y, 0, 0, this.xSize, this.ySize);
-
Même résultat, c’est déjà ce positionnement qui est appliqué dans la classe mère apparement.
-
Essaie avec une image de 256*256 mais avec la texture souhaitée sur tes dimensions.
-
Youhou Ca marche \o/.
Merci
Reste à faire fonctionner la partie drag & drop avec l’inventaire du joueur.
Si ça ne dérange pas trop je laisse le post ouvert encore un peu le temps de voir si je m’en sort avant de mettre résolu. -
Ca marche … presque … J’ai des comportements étrange quand je transfert des items :
- Si je fais passer de l’inventaire joueur à l’inventaire custom ça double les quantités.
- Si je prend les items de l’inventaire custom il disparaissent. Si j’utilise maj+clic on voit l’item apparaitre un court instant dans l’inventaire avant de disparaitre.
J’ai l’impression que cela vient de la séparation client / serveur qui est foireuse et que du coup et le client et le serveur transfert l’item et donc double ses quantité.
:::Handler :
public class GuiHandler implements IGuiHandler { /** * Return the requested GUI on server side. * Always null as no server GUI exists. */ @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { switch(id) { case Robotica.GUI.RobotInventory: // NB : j'utilise x comme id car il s'agit d'une entité, pas d'un bloc. Ca semble marcher return getRobotInventoryTileEntity(player, x); default: return null; } } private Object getRobotInventoryTileEntity(EntityPlayer player, int id) { MechaEntity e = MechaEntity.getMecha(id); if(!(e instanceof RobotEntity)) return null; if( new Coords(player).distanceTo((RobotEntity) e) > RobotEntity.GUIRANGE) return null; return new RobotInventoryContainer(player.inventory, ((RobotEntity) e).inventory); } /** * Return the requested GUI on client side. * The corresponding Id's can be found in a subclass of Robotica : {@link PLCmods.robotica.Robotica.GUI}. */ @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { switch(id) { case Robotica.GUI.ControlPanel: return new ControlPanelGUI(); case Robotica.GUI.RobotInfo: return new InfoFrameGUI(); case Robotica.GUI.RobotInventory: return getRobotInventoryGui(player, x); default: return null; } } private Object getRobotInventoryGui(EntityPlayer player, int id) { MechaEntity e = MechaEntity.getMecha(id); if(!(e instanceof RobotEntity)) return null; if( new Coords(player).distanceTo((RobotEntity) e) > RobotEntity.GUIRANGE) return null; return new RobotInventoryGui(player, (RobotEntity) e); } }
GUI :
public class RobotInventoryGui extends GuiContainer { public static final ResourceLocation texture = new ResourceLocation(Robotica.SID, "textures/gui/robotinv.png"); public RobotInventoryGui(EntityPlayer player, RobotEntity robot) { super(new RobotInventoryContainer(player.inventory, robot.inventory)); xSize = 175; ySize = 165; } @Override protected void drawGuiContainerBackgroundLayer(float f, int i, int j) { GL11.glColor4f(1F, 1F, 1F, 1F); FMLClientHandler.instance().getClient().renderEngine.func_110577_a(texture); int x = (this.width - this.xSize) / 2; int y = (this.height - this.ySize) / 2; this.drawTexturedModalRect(x, y, 0, 0, this.xSize, this.ySize); } }
TileEntity :
public class RobotInventory extends TileEntity implements IInventory { public static final int GRAB_RANGE = 3; protected RobotEntity entity; protected ItemStack[] inv; public RobotInventory(RobotEntity robotEntity) { entity = robotEntity; inv = new ItemStack[24]; } @Override public int getSizeInventory() { return inv.length; } @Override public ItemStack getStackInSlot(int i) { return inv*; } @Override public ItemStack decrStackSize(int slotId, int quantity) { if (this.inv[slotId] != null) { ItemStack itemstack; if (this.inv[slotId].stackSize <= quantity) { itemstack = this.inv[slotId]; this.inv[slotId] = null; this.onInventoryChanged(); return itemstack; } else { itemstack = this.inv[slotId].splitStack(quantity); if (this.inv[slotId].stackSize == 0) { this.inv[slotId] = null; } this.onInventoryChanged(); return itemstack; } } else { return null; } } @Override public ItemStack getStackInSlotOnClosing(int slotId) { if (this.inv[slotId] != null) { ItemStack itemstack = this.inv[slotId]; this.inv[slotId] = null; return itemstack; } else { return null; } } @Override public void setInventorySlotContents(int slotId, ItemStack stack) { System.out.println("Set slot content of " + slotId); this.inv[slotId] = stack; if (stack != null && stack.stackSize > this.getInventoryStackLimit()) { stack.stackSize = this.getInventoryStackLimit(); } this.onInventoryChanged(); } @Override public String getInvName() { return "Robot inventory"; } @Override public boolean isInvNameLocalized() { return true; } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return player.getDistanceSq(entity.posX, entity.posY, entity.posZ) < 25; } @Override public void openChest() { } @Override public void closeChest() { } @Override public boolean isItemValidForSlot(int i, ItemStack itemstack) { return true;// (i < 20 || i > 23); } }
Container :
public class RobotInventoryContainer extends Container { private RobotInventory inventory; public RobotInventoryContainer(InventoryPlayer playerinv, RobotInventory robotinv) { this.inventory = robotinv; for(int i=0;i<4;i++) for(int j=0;j<5;j++) addSlotToContainer(new Slot(robotinv, i * 5 + j, 82 + j * 18, 6 + i * 18)); for(int i=0;i<4;i++) addSlotToContainer(new Slot(robotinv, 20 + i, 6, 6 + i * 18)); for(int i=0;i<3;i++) for(int j=0;j<9;j++) addSlotToContainer(new Slot(playerinv, 9 + i * 9 + j, 8 + j * 18, 84 + i * 18)); for(int j=0;j<9;j++) addSlotToContainer(new Slot(playerinv, j, 8 + j * 18, 142)); } public ItemStack transferStackInSlot(EntityPlayer player, int n) { System.out.println("Transfert in slot " + n); ItemStack stack = null; Slot slotObject = (Slot)this.inventorySlots.get(n); if (slotObject != null && slotObject.getHasStack()) { ItemStack stack1 = slotObject.getStack(); stack = stack1.copy(); if(n < 24) { if(!this.mergeItemStack(stack1,24,59,false)) // (! ((RobotInventory) slotObject.inventory).pickUpItem(itemstack)) { return null; } } else if (!this.mergeItemStack(stack1, 0, 20, false)) { return null; } if(stack1.stackSize == 0) { slotObject.putStack(null); } else { slotObject.onSlotChanged(); } } return stack; } @Override public boolean canInteractWith(EntityPlayer entityplayer) { return inventory.isUseableByPlayer(entityplayer); } }
:::
NB : pour info les slots custom sont formé d’un groupe de 20 et d’un groupe de 4. -
Je pense avoir mis le doigt sur le problème :
Coté serveur mon entité à son inventaire correct mais coté client l’inventaire reste vide. Comment se fait la synchronisation entre le serveur et le client dans le cas d’un container de bloc ? Ici j’ai une entité au lieu d’un block, est-ce que je peux utiliser le même système ou je dois passer par des dataWatcher pour synchroniser chaque slots ?
-
Plutôt par des paquets. Il y a quelqu’un du fofo qui l’a fait, mais je ne sais plus qui
-
Mouais, je connais pas la gestion des paquets … C’est en rapport avec ça je suppose : http://www.minecraftforge.net/wiki/Packet_Handling
Dans le cas de container de block ça passe par ce système aussi ? Histoire que je vois comment c’est géré.