Création d'Items avec container
-
version de forge : 9.11.1.953
Bonjour,
Après des heures et des heures de recherche, je viens demander de l’aide ici ! Je commence le modding (1 - 2 semaine) et j’ai déjà bien envie de faire des choses sans suivre à la lettre un tuto, j’essaie donc de créer un item avec Gui et Container; pour le Gui pas de problème mais pour le container j’ai essayé tout ce que sais faire mais pas moyen d’obtenir un Container avec des slots …
L’erreur que j’ai le plus souvent après mes essais est une erreur IndexOutOfBoundsException: Index: 45, Size: 45, je crois que le 45 est le nombre de slots d’un inventaire joueur normal (avec les slots d’armure, le craft et le résultat de craft) mais je pas ce que cet inventaire vient faire dans mon code sachant que je fais des addslot(moninventaireperso …) et que mon inventaire contient [27] slots, d’ailleurs je suis à la recherche d’un tuto complet sur les slots etc ….
Voila le crashreport complet---- Minecraft Crash Report ---- // You should try our sister game, Minceraft! Time: 29/12/13 17:41 Description: Exception in world tick java.lang.IndexOutOfBoundsException: Index: 45, Size: 45 at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) at net.minecraft.inventory.Container.getSlot(Container.java:133) at net.minecraft.inventory.Container.putStacksInSlots(Container.java:562) at net.minecraft.client.multiplayer.NetClientHandler.handleWindowItems(NetClientHandler.java:1288) at net.minecraft.network.packet.Packet104WindowItems.processPacket(Packet104WindowItems.java:67) at net.minecraft.network.MemoryConnection.processReadPackets(MemoryConnection.java:89) at net.minecraft.client.multiplayer.NetClientHandler.processReadPackets(NetClientHandler.java:281) at net.minecraft.client.multiplayer.WorldClient.tick(WorldClient.java:99) at net.minecraft.client.Minecraft.runTick(Minecraft.java:1930) at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:910) at net.minecraft.client.Minecraft.run(Minecraft.java:838) at net.minecraft.client.main.Main.main(Main.java:93) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at net.minecraft.launchwrapper.Launch.launch(Launch.java:131) at net.minecraft.launchwrapper.Launch.main(Launch.java:27) A detailed walkthrough of the error, its code path and all known details is as follows: --------------------------------------------------------------------------------------- -- Head -- Stacktrace: at java.util.ArrayList.rangeCheck(Unknown Source) at java.util.ArrayList.get(Unknown Source) at net.minecraft.inventory.Container.getSlot(Container.java:133) at net.minecraft.inventory.Container.putStacksInSlots(Container.java:562) at net.minecraft.client.multiplayer.NetClientHandler.handleWindowItems(NetClientHandler.java:1288) at net.minecraft.network.packet.Packet104WindowItems.processPacket(Packet104WindowItems.java:67) at net.minecraft.network.MemoryConnection.processReadPackets(MemoryConnection.java:89) at net.minecraft.client.multiplayer.NetClientHandler.processReadPackets(NetClientHandler.java:281)
Pour info voici mes classes : -Inventaire persos, -Container, -Gui, -GuiHandler, -Mon item.
Demandez moi si vous voulez le contenu d’une classe en particulier …
Si jamais un tuto est sur le net et que vous avez le lien n’hésitez pas à me le donner (même en anglais) …
Et merci d’avance à vous ,je commence à désespérer ! -
@‘OpumaO’:
Pour info voici mes classes : -Inventaire persos, -Container, -Gui, -GuiHandler, -Mon item.
Heu, je les trouve où ? x) Il y a aucun code, ça serait plus pratique si on les avait.
-
IndexOutOfBoundsException
Cherche tous les nombres 45 dans ton code, ton container a une limite de 45 slots mais en a 46 je présume ( 45 + 1 car 0 est un slot ).
-
Oui, j’aurais du mettre les classes XD (Je ne sais pas pourquoi je ne l’ai pas fait …), il y des commentaires qui ne viennent pas de moi, ça m’aide à savoir à quoi ça sert (mieux expliqué que si je les écrivais)
Mon Item :package tutoriel.common; import cpw.mods.fml.common.network.FMLNetworkHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.world.World; public class dummyitem extends Item { public dummyitem(int id) { super(id); this.setCreativeTab(ModTutoriel.TutorialCreativeTabs); } public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer player) { player.openGui(ModTutoriel.instance, 0, world, (int)player.posX, (int)player.posY, (int)player.posZ); return itemstack; } }
Mon Container, j’ai pris le même modèle que pour le tuto avec le block en arrangeant pour avoir mon inventaire à la place du tile entity (
package tutoriel.common.gui; import tutoriel.common.ModTutoriel; import tutoriel.common.TileEntityBigChest; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryBasic; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; public class ContainerDummy extends Container{ static InventoryItem invitem; public ContainerDummy(InventoryPlayer playerInventory, InventoryItem inventoryitem) { this.invitem = inventoryitem; for(int i = 0; i < 3; i++) { for(int j = 0; j < 9; j++) { this.addSlotToContainer(new Slot(inventoryitem, j + i * 10, 8 + j * 18, 18 + i * 18)); } } this.bindPlayerInventory(playerInventory); } private void bindPlayerInventory(InventoryPlayer playerInventory) { int i; for(i = 0; i < 3; i++) { for(int j = 0; j < 9; j++) { this.addSlotToContainer(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 103 + i * 18 + 37)); } } for(i = 0; i < 9; i++) { this.addSlotToContainer(new Slot(playerInventory, i, 8 + i * 18, 161 + 37)); } } @Override public boolean canInteractWith(EntityPlayer entityplayer) { return true; } public ItemStack transferStackInSlot(EntityPlayer player, int slotId) { ItemStack itemstack = null; Slot slot = (Slot)this.inventorySlots.get(slotId); if(slot != null && slot.getHasStack()) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); if(slotId < 9) { if(!this.mergeItemStack(itemstack1, 9, this.inventorySlots.size(), true)) { return null; } } else if(!this.mergeItemStack(itemstack1, 0, 9, false)) { return null; } if(itemstack1.stackSize == 0) { slot.putStack((ItemStack)null); } else { slot.onSlotChanged(); } } return itemstack; } } }
Mon inventaire (sur le même modele que le tile entity du tuto)
package tutoriel.common.gui; import tutoriel.common.dummyitem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; public class InventoryItem implements IInventory { private String name = "Inventory Item"; /** Provides NBT Tag Compound to reference */ private final ItemStack stack; /** Defining your inventory size this way is handy */ public static final int INV_SIZE = 46; /** Inventory's size must be same as number of slots you add to the Container class */ ItemStack[] inventory = new ItemStack[46]; /** * @param itemstack - the ItemStack to which this inventory belongs */ public InventoryItem(ItemStack itemstack) { this.stack = itemstack; // Create a new NBT Tag Compound if one doesn't already exist, or you will crash if (!this.stack.hasTagCompound()) { this.stack.setTagCompound(new NBTTagCompound()); } // Read the inventory contents from NBT readFromNBT(this.stack.getTagCompound()); } @Override public int getSizeInventory() { return inventory.length; } @Override public ItemStack getStackInSlot(int slot) { return inventory[slot]; } @Override public ItemStack decrStackSize(int slot, int amount) { ItemStack stack = getStackInSlot(slot); if(stack != null) { if(stack.stackSize > amount) { stack = stack.splitStack(amount); // Don't forget this line or your inventory will not be saved! this.onInventoryChanged(); } else { setInventorySlotContents(slot, null); } } return stack; } @Override public ItemStack getStackInSlotOnClosing(int slot) { ItemStack stack = getStackInSlot(slot); setInventorySlotContents(slot, null); return stack; } @Override public void setInventorySlotContents(int slot, ItemStack itemstack) { this.inventory[slot] = itemstack; if (itemstack != null && itemstack.stackSize > this.getInventoryStackLimit()) { itemstack.stackSize = this.getInventoryStackLimit(); } // Don't forget this line or your inventory will not be saved! this.onInventoryChanged(); } @Override public String getInvName() { return name; } @Override public boolean isInvNameLocalized() { return name.length() > 0; } @Override public int getInventoryStackLimit() { return 64; } /** * This is the method that will handle saving the inventory contents, as it is called (or should be called!) * anytime the inventory changes. Perfect. Much better than using onUpdate in an Item, as this will also * let you change things in your inventory without ever opening a Gui, if you want. */ @Override public void onInventoryChanged() { for (int i = 0; i < this.getSizeInventory(); ++i) { if (this.getStackInSlot(i) != null && this.getStackInSlot(i).stackSize == 0) this.setInventorySlotContents(i, null); } // This line here does the work: this.writeToNBT(this.stack.getTagCompound()); } @Override public boolean isUseableByPlayer(EntityPlayer player) { return true; } @Override public void openChest() {} @Override public void closeChest() {} /** * This method doesn't seem to do what it claims to do, as * items can still be left-clicked and placed in the inventory * even when this returns false */ @Override public boolean isItemValidForSlot(int slot, ItemStack itemstack) { // Don't want to be able to store the inventory item within itself // Bad things will happen, like losing your inventory // Actually, this needs a custom Slot to work return true; } /** * A custom method to read our inventory from an ItemStack's NBT compound */ public void readFromNBT(NBTTagCompound compound) { // Gets the custom taglist we wrote to this compound, if any NBTTagList items = compound.getTagList("ItemInventory"); for (int i = 0; i < items.tagCount(); ++i) { NBTTagCompound item = (NBTTagCompound) items.tagAt(i); int slot = item.getInteger("Slot"); // Just double-checking that the saved slot index is within our inventory array bounds if (slot >= 0 && slot < getSizeInventory()) { setInventorySlotContents(slot, ItemStack.loadItemStackFromNBT(item)); } } } /** * A custom method to write our inventory to an ItemStack's NBT compound */ public void writeToNBT(NBTTagCompound compound) { // Create a new NBT Tag List to store itemstacks as NBT Tags NBTTagList items= new NBTTagList(); for (int i = 0; i < getSizeInventory(); ++i) { // Only write stacks that contain items if (getStackInSlot(i) != null) { // Make a new NBT Tag Compound to write the itemstack and slot index to NBTTagCompound item = new NBTTagCompound(); item.setInteger("Slot", i); // Writes the itemstack in slot(i) to the Tag Compound we just made getStackInSlot(i).writeToNBT(item); // add the tag compound to our tag list items.appendTag(item); } } // Add the TagList to the ItemStack's Tag Compound with the name "ItemInventory" compound.setTag("ItemInventory", items); } }
Et enfin le GuiHandler (je pense que l’erreur vient de cette class en premier)
import tutoriel.common.ModTutoriel; import tutoriel.common.TileEntityBigChest; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import cpw.mods.fml.common.network.IGuiHandler; import cpw.mods.fml.common.network.NetworkRegistry; public class GuiHandler implements IGuiHandler{ private InventoryItem tileEntity; public GuiHandler() { NetworkRegistry.instance().registerGuiHandler(ModTutoriel.instance, this); } @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { IInventory ii = new InventoryItem(new ItemStack(ModTutoriel.dummyitem)); switch(ID){ default: return null; case 0: /*if (ContainerDummy.tileEntity != null){ System.out.println("!=null");*/ return new ContainerDummy(player.inventory, (InventoryItem)ii ); /*if(ContainerDummy.tileEntity == null){ System.out.println("==null"); }*/ case 1: return new ContainerDummy2(player); } } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(ID){ default: return null; case 0: return new DummyGui(player); case 1: return new DummyGui2(player); } } }
Voila pour mes classes, après pour le 45, je n’en ai aucun dans code c’est pour ça que je pense que c’est le nombre de slots d’un inventaire en survie …
-
static InventoryItem invitem;
C’est pas bon ça. Une variable static peut être utilisé partout sans être instancier car elle à une celle instance. Or des items, il peut en avoir plusieurs, donc il faut plusieurs instance. Enlève le static.J’ai jamais mit de container sur un item, c’est assez complexe, il faudrait que je fasse des tests pour te donner un coup de main.
-
Ok pour le static, j’ai arrêté mes recherches pour aujourd’hui. Si tu as le temps ça serait sympa de m’aider mais si c’est trop long te prends pas la tête ^^