Jump to content

Block with inventory crashes on click: Slot 0 not in valid range - [0,0)


Recommended Posts

Posted

Hi,

i am trying to implement a Block with Inventory and GUI. When clicking it, the game crashes with "Slot 0 not in valid range - [0,0)". Now this sounds like the ItemStack is initialized with a size of 0. But i am initializing it with size 6. The GUI is opened, but after about half a second the crash occurs.

Coding so far:

 

abstract NodeTileEntity:

Spoiler

package com.kalaskow.kc.tile;

import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;

public abstract class NodeTileEntity extends TileEntity implements ITickable {

  private ItemStackHandler itemStackHandler;

  @Override
  public void readFromNBT(NBTTagCompound compound) {
    super.readFromNBT(compound);
    if (compound.hasKey("items")) {
      getItemStackHandler().deserializeNBT((NBTTagCompound) compound.getTag("items"));
    }
  }

  @Override
  public NBTTagCompound writeToNBT(NBTTagCompound compound) {
    super.writeToNBT(compound);
    compound.setTag("items", getItemStackHandler().serializeNBT());
    return compound;
  }

  public boolean canInteractWith(EntityPlayer playerIn) {
    // If we are too far away from this tile entity you cannot use it
    return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
  }

  @Override
  public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) {
    return false;
  }

  @Override
  public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
    if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
      return true;
    }
    return super.hasCapability(capability, facing);
  }

  @Override
  public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
    if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
      return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(getItemStackHandler());
    }
    return super.getCapability(capability, facing);
  }

  public ItemStackHandler getItemStackHandler() {
    if (itemStackHandler == null) {
      itemStackHandler = new ItemStackHandler(getSIZE()) {
        @Override
        protected void onContentsChanged(int slot) {
          markDirty();
        }
      };
    }
    return itemStackHandler;
  }

  public abstract int getSIZE();
}

CityCenterEntity:

Spoiler

package com.kalaskow.kc.tile;

public class CityCenterEntity extends NodeTileEntity {

  public static final String ID = "city_center_entity";

  @Override
  public int getSIZE() {
    return 6;
  }

  @Override
  public void update() {

  }
}

Abstract NodeContainer:

Spoiler

package com.kalaskow.kc.container;


import com.kalaskow.kc.tile.NodeTileEntity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;

import javax.annotation.Nullable;

public abstract class NodeContainer extends Container {

  protected final int START_SLOTS_X = 8;
  protected final int START_NODE_INVENTORY_Y = 8;
  protected final int START_PLAYER_INVENTORY_Y = 84;
  protected final int START_PLAYER_HOTBAR_Y = 142;
  protected final int SLOT_DIMENS = 18;

  private char[][] inventory;

  protected NodeTileEntity te;

  public NodeContainer(IInventory playerInventory, NodeTileEntity te, char[][] inventory) {
    this.te = te;
    this.inventory = inventory;

    // This container references items out of our own inventory (the 9 slots we hold ourselves)
    // as well as the slots from the player inventory so that the user can transfer items between
    // both inventories. The two calls below make sure that slots are defined for both inventories.
    addOwnSlots();
    addPlayerSlots(playerInventory);
  }

  public void addOwnSlots() {
    IItemHandler itemHandler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
    int slotIndex = 0;
    for (int row = 0; row < 4; row++) {
      for (int col = 0; col < 9; col++) {
        if (inventory[row][col] == 'X') {
          int x = START_SLOTS_X + col * SLOT_DIMENS;
          int y = START_NODE_INVENTORY_Y + row * SLOT_DIMENS;
          addSlotToContainer(new SlotItemHandler(itemHandler, slotIndex++, x, y));
        }
      }
    }
  }

  @Override
  public boolean canInteractWith(EntityPlayer playerIn) {
    return te.canInteractWith(playerIn);
  }

  private void addPlayerSlots(IInventory playerInventory) {
    // Slots for the hotbar
    int slotID = 0;
    for (int col = 0; col < 9; col++) {
      int x = START_SLOTS_X + col * SLOT_DIMENS;
      this.addSlotToContainer(new Slot(playerInventory, slotID++, x, START_PLAYER_HOTBAR_Y));
    }

    // Slots for the main inventory
    for (int row = 0; row < 3; row++) {
      for (int col = 0; col < 9; col++) {
        int x = START_SLOTS_X + col * SLOT_DIMENS;
        int y = START_PLAYER_INVENTORY_Y + row * SLOT_DIMENS;
        this.addSlotToContainer(new Slot(playerInventory, slotID++, x, y));
      }
    }
  }

  @Nullable
  @Override
  public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) {
    ItemStack itemstack = null;
    Slot slot = this.inventorySlots.get(index);
    if (slot != null && slot.getHasStack()) {
      ItemStack itemstack1 = slot.getStack();
      itemstack = itemstack1.copy();
      if (index < te.getSIZE()) {
        if (!this.mergeItemStack(itemstack1, te.getSIZE(), this.inventorySlots.size(), true)) {
          return null;
        }
      } else if (!this.mergeItemStack(itemstack1, 0, te.getSIZE(), false)) {
        return null;
      }
      if (itemstack1.isEmpty()) {
        slot.putStack(ItemStack.EMPTY);
      } else {
        slot.onSlotChanged();
      }
    }
    return itemstack;
  }
}

CityCenterContainer:

Spoiler

package com.kalaskow.kc.container;


import com.kalaskow.kc.tile.CityCenterEntity;
import net.minecraft.inventory.IInventory;

public class CityCenterContainer extends NodeContainer {

  private final static char[][] inventory = {
          {'X', 'X', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
          {'X', 'X', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
          {'X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
          {'X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},
  };

  public CityCenterContainer(IInventory playerInventory, CityCenterEntity te) {
    super(playerInventory, te, inventory);
  }
}

 

Posted (edited)
1 hour ago, Kalaskow said:

  @Override
  public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newSate) {
    return false;
  }

This isn't related to your problem...but OH GOD WHY.

You're essentially telling Minecraft that your TileEntity will never be invalid. Yes, even if you break your block and place a chest there, your TE is still valid.

Good job.

 

1 hour ago, Kalaskow said:

implements ITickable

Why is your base TE class implementing ITickable when your subclass does fuckall with it? Leave this off and let the subclass implement it (or not). By making all of your TEs ticking you consume system resources to do nothing.

Good job.

 

 

As for your problem. Use the debugger. Why is your IItemStackhandler getting created with 0 size? The debugger can answer this for you.

Edited by Draco18s

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
4 minutes ago, Draco18s said:

You're essentially telling Minecraft that your TileEntity will never be invalid. Yes, even if you break your block and place a chest there, your TE is still valid.

Good job.

Ok, ill fix that.

 

4 minutes ago, Draco18s said:

Why is your base TE class implementing ITickable when your subclass does fuckall with it? Leave this off and let the subclass implement it (or not). By making all of your TEs ticking you consume system resources to do nothing.

Good job.

Because the Entities will be ticking at a later time. I've added it in advance. No worries. I wont let them do stuff every single tick.

Posted

I will be implementing stuff there anyways. There is no reason for me not to implement it already. The only CPU Power i am wasting is my own ;) 

I wouldnt implement the Interface if i werent to use it. And i will.

Posted

Back to the original problem, it says that the slot is not in valid range. I don't think that has anything to do with the size of the itemstack, I think you're trying to access a slot that doesn't "exist" based on the slot numbers. I usually find these errors have to do with some mismatch in how I add my own slots and then access them later. As mentioned, use standard debugging methods but I think focus should be on your slot numbering not the itemstack size.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.