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 !


  • Moddeurs confirmés Rédacteurs Administrateurs

    @'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 …


  • Moddeurs confirmés Rédacteurs Administrateurs

    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 ^^


Log in to reply