Hi all, i've recently tried to make my first GUI for minecraf 1.6.4 but i've been having severe trouble after about 8 hours of searching the internet it still isn't working, there have been several bugs mixed together i think incuding a desync between player and server caused by calling player.openGUI not FMLNetworkHandler.openGui, some weird slot index errors and some other just weird errors, the current errors that i need help fixing are as follows:
- my shift click code is weird, ghost items used to appear, stacks didn't decrement, but now i just get a StackOverflow error in the console that looks like this:
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.retrySlotClick(Container.java:520)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.slotClick(Container.java:291)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.retrySlotClick(Container.java:520)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.slotClick(Container.java:291)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.retrySlotClick(Container.java:520)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.slotClick(Container.java:291)
2013-12-29 11:28:47 [iNFO] [sTDOUT] at net.minecraft.inventory.Container.retrySlotClick(Container.java:520)
- when you double-click an item the stack size is weird (e.g if i fill my inv with single stacks of stone and double click sometimes it will give me a 29 stack but hen i do it again a 31 and when i do it again the correct size of 36)
- sometimes you can't pick up items in your inventory
- sometimes left click will act as right click in the GUI slots
Here is the important parts of my load class (NOTE: the spoiler/code button in the post editor isn't working(or i'm doign it wrong)):
Mod(modid = "EndoEnergy", name = "Endo-Energy", version = "Alpha 0.1.0")
@NetworkMod(clientSideRequired = true,serverSideRequired = true)
public class EndoEnergy {
@Instance(value = "EndoEnergy")
public static EndoEnergy instance;
public EndoEnergy() {
// rendering stuff
CommonProxy proxy2 = new CommonProxy();
proxy2.registerRenderers();
ClientRegistry.bindTileEntitySpecialRenderer(
endernoobs.mods.endoEnergy.entity.TileEntityWire.class,
new TileEntityWireRenderer());
ClientRegistry.bindTileEntitySpecialRenderer(
endernoobs.mods.endoEnergy.entity.TileEntityBatteryRack.class,
new TileEntityWireRenderer());
GameRegistry.registerTileEntity(TileEntityWire.class, "TileEntityWire");
GameRegistry.registerTileEntity(TileEntityStorageWire.class, "TileEntityStorageWire");
GameRegistry.registerBlock(BlockBatteryRack, "BlockBatteryRack");
NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler());
MinecraftForge.EVENT_BUS.register(BlockBatteryRack);
}
}
Here is BlockBatteryRack:
public class BlockBatteryRack extends BlockContainer{
@Override
public TileEntity createNewTileEntity(World world) { //says:int metadata, no 'new'
return new TileEntityBatteryRack(5);
}
public BlockBatteryRack(int id, Material material) {
super(id, material);
this.setBlockBounds(0F, 0F, 0F, 1F, 1F, 1F);
}
public boolean shouldSideBeRendered(IBlockAccess iblockaccess, int i, int j, int k, int l)
{
return false;
}
public boolean isOpaqueCube()
{
return false;
}
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int metadata, float what, float these, float are) {
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
if (tileEntity == null || player.isSneaking()) {
return false;
}
FMLNetworkHandler.openGui(player, EndoEnergy.instance, 0, world, x,y,z);
return true;
}
public int idDropped(int par1, Random random, int zero) {
return EndoEnergy.ItemBatteryRack.itemID;
}
@Override
public void breakBlock(World world, int x, int y, int z, int par5, int par6) {
dropItems(world, x, y, z);
world.removeBlockTileEntity(x, y, z);
super.breakBlock(world, x, y, z, par5, par6);
}
private void dropItems(World world, int x, int y, int z){
Random rand = new Random();
TileEntity tileEntity = world.getBlockTileEntity(x, y, z);
if (!(tileEntity instanceof IInventory)) {
return;
}
IInventory inventory = (IInventory) tileEntity;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack item = inventory.getStackInSlot(i);
if (item != null && item.stackSize > 0) {
float rx = rand.nextFloat() * 0.8F + 0.1F;
float ry = rand.nextFloat() * 0.8F + 0.1F;
float rz = rand.nextFloat() * 0.8F + 0.1F;
EntityItem entityItem = new EntityItem(world,
x + rx, y + ry, z + rz,
new ItemStack(item.itemID, item.stackSize, item.getItemDamage()));
if (item.hasTagCompound()) {
entityItem.getEntityItem().setTagCompound((NBTTagCompound) item.getTagCompound().copy());
}
float factor = 0.05F;
entityItem.motionX = rand.nextGaussian() * factor;
entityItem.motionY = rand.nextGaussian() * factor + 0.2F;
entityItem.motionZ = rand.nextGaussian() * factor;
world.spawnEntityInWorld(entityItem);
item.stackSize = 0;
}
}
}
}
Here is TileEntityBatteryRack:
public class TileEntityBatteryRack extends TileEntityStorageWire implements IInventory{
public ItemStack[] inv;
public TileEntityBatteryRack(int i) {
super(i);
inv = new ItemStack[2];
}
public TileEntityBatteryRack() {
super();
}
@Override
public int getSizeInventory() {
if (inv != null) {
return inv.length;
} else {
return 0;
}
}
@Override
public ItemStack getStackInSlot(int slot) {
//slot = slot - 36;
return inv[slot];
}
@Override
public ItemStack decrStackSize(int slot, int amt) {
//slot = slot - 36;
ItemStack stack = getStackInSlot(slot);
if (stack != null) {
if (stack.stackSize <= amt) {
setInventorySlotContents(slot, null);
} else {
ItemStack newstack = stack.splitStack(stack.stackSize - amt);
setInventorySlotContents(slot, newstack);
}
}
return stack;
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
//slot = slot - 36;
ItemStack stack = getStackInSlot(slot);
if (stack != null) {
setInventorySlotContents(slot, null);
}
return stack;
}
@Override
public void setInventorySlotContents(int slot, ItemStack stack) {
inv[slot] = stack;
//if (stack != null && stack.stackSize > getInventoryStackLimit()) {
// stack.stackSize = getInventoryStackLimit();
//}
}
@Override
public String getInvName() {
return "Battery Rack";
}
@Override
public boolean isInvNameLocalized() {
// TODO Auto-generated method stub
return false;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return worldObj.getBlockTileEntity(xCoord, yCoord, zCoord) == this &&
player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64;
}
@Override
public void openChest() { }
@Override
public void closeChest() {}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack) {
// TODO Auto-generated method stub
return false;
}
@Override
public void readFromNBT(NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
NBTTagList tagList = tagCompound.getTagList("Inventory");
for (int i = 0; i < tagList.tagCount(); i++) {
NBTTagCompound tag = (NBTTagCompound) tagList.tagAt(i);
byte slot = tag.getByte("Slot");
if (slot >= 0 && slot < inv.length) {
inv[slot] = ItemStack.loadItemStackFromNBT(tag);
}
}
}
@Override
public void writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
NBTTagList itemList = new NBTTagList();
if (inv != null) {
for (int i = 0; i < inv.length; i++) {
ItemStack stack = inv;
if (stack != null) {
NBTTagCompound tag = new NBTTagCompound();
tag.setByte("Slot", (byte) i);
stack.writeToNBT(tag);
itemList.appendTag(tag);
}
}
tagCompound.setTag("Inventory", itemList);
}
}
}
Here is ContainerBatteryRack:
public class ContainerBatteryRack extends Container{
private TileEntityBatteryRack tileEntity;
private float lastEnergyStored;
public ContainerBatteryRack (InventoryPlayer inventoryPlayer, TileEntityBatteryRack te){
tileEntity = te;
addSlotToContainer(new Slot(tileEntity, 0,44,53));
addSlotToContainer(new Slot(tileEntity, 1,116,53));
bindPlayerInventory(inventoryPlayer);
}
@Override
public boolean canInteractWith(EntityPlayer player) {
return true;//tileEntity.isUseableByPlayer(player);
}
/**
* Called to transfer a stack from one inventory to the other eg. when shift
* clicking.
*/
@Override
public ItemStack transferStackInSlot(EntityPlayer player, int index){
ItemStack stack = null;
Slot slot = (Slot) this.inventorySlots.get(index);
if(slot!=null&&slot.getHasStack()){
ItemStack slotstack = slot.getStack();
stack = slotstack.copy();
System.out.println(slotstack + " is in " + index);
} else {
return null;
}
System.out.println(index);
int slotid = index;
if (index > 1 && index < 29) {
slotid = index + 7;
} else if (index > 28 && index < 38) {
slotid = index - 29;
}
if (index == 36 || index == 37) {
slotid = index - 36;
//tileEntity.decrStackSize(slotid, 1);
} else {
//slotid -= 2;
//this.inventorySlots.set(index, ((Slot) this.inventorySlots.get(index)).decrStackSize(1));
//player.inventory.decrStackSize(index, 1);
}
return stack;//stack;
}
@Override
public boolean mergeItemStack(ItemStack stack, int start, int end, boolean reverse){
return super.mergeItemStack(stack,start,end,reverse);
}
/**
* Does the same as mergeItemStack with the same args, except does not
* actually merge— just returns the number of items that can be merged
* (usually either stack.stackSize or 0, but can be in between)
* @param stack
* @param start
* @param end
* @param reverse
* @return
*/
int dryMerge(ItemStack stack, int start, int end, boolean reverse){
boolean flag1 = false;
int i = start;
if(reverse){
i = end-1;
}
int quantity = stack.stackSize;
Slot slot;
ItemStack slotstack;
if(stack.isStackable()){
while(stack.stackSize>0&&(!reverse&&i<end||reverse&&i>=start)){
slot = this.getSlot(i);
slotstack = slot.getStack();
if(slotstack!=null&&slotstack.itemID==stack.itemID&&(!stack.getHasSubtypes()||stack.getItemDamage()==slotstack.getItemDamage())&&ItemStack.areItemStackTagsEqual(stack,slotstack)){
int l = slotstack.stackSize+stack.stackSize;
if(l<=stack.getMaxStackSize()){
quantity -= slotstack.stackSize;
}else if(slotstack.stackSize<stack.getMaxStackSize()){
quantity -= (stack.getMaxStackSize() - slotstack.stackSize);
}
}
if(reverse) --i;
else ++i;
}
}
if(stack.stackSize>0){
if(reverse){
i = end-1;
}else{
i = start;
}
while(!reverse&&i<end||reverse&&i>=start){
slot = (Slot) this.inventorySlots.get(i);
slotstack = slot.getStack();
if(slotstack==null){
quantity = 0;
break;
}
if(reverse){
--i;
}else{
++i;
}
}
}
return stack.stackSize-quantity;
}
@Override
public void addCraftingToCrafters(ICrafting par1ICrafting) {
super.addCraftingToCrafters(par1ICrafting);
par1ICrafting.sendProgressBarUpdate(this, 0, (int) this.tileEntity.energyStored);
}
@Override
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for (int i = 0; i < this.crafters.size(); ++i)
{
ICrafting icrafting = (ICrafting)this.crafters.get(i);
if (this.lastEnergyStored != this.tileEntity.energyStored)
{
icrafting.sendProgressBarUpdate(this, 0, (int) this.tileEntity.energyStored);
}
}
this.lastEnergyStored= this.tileEntity.energyStored;
}
@SideOnly(Side.CLIENT)
public void updateProgressBar(int par1, int par2)
{
if (par1 == 0) {
this.tileEntity.energyStored = par2;
}
}
protected void bindPlayerInventory(InventoryPlayer inventoryPlayer) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 9; j++) {
addSlotToContainer(new Slot(inventoryPlayer, j + i * 9 + 9,8 + j * 18, 84 + i * 18));
}
}
for (int i = 0; i < 9; i++) {
addSlotToContainer(new Slot(inventoryPlayer, i, 8 + i * 18, 142));
}
}
}
Here is GuiBatteryRack:
public class GuiBatteryRack extends GuiContainer{
private TileEntityBatteryRack rack;
public GuiBatteryRack (InventoryPlayer inventoryPlayer, TileEntityBatteryRack tileEntity) {
super(new ContainerBatteryRack(inventoryPlayer, tileEntity));
this.rack = tileEntity;
}
@Override
protected void drawGuiContainerForegroundLayer(int param1, int param2) {
String s = this.rack.isInvNameLocalized() ? this.rack.getInvName() : "Battery Rack";
//draw text and stuff here
//the parameters for drawString are: string, x, y, color
this.fontRenderer.drawString(s, this.xSize / 2 - this.fontRenderer.getStringWidth(s) / 2, 6, 4210752);
//draws "Inventory" or your regional equivalent
fontRenderer.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752);
}
@Override
protected void drawGuiContainerBackgroundLayer(float par1, int par2,int par3) {
//draw your Gui here, only thing you need to change is the path
float bar = this.rack.energyStored;
int k = (this.width - this.xSize) / 2;
int l = (this.height - this.ySize) / 2;
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.mc.renderEngine.bindTexture((new ResourceLocation("endoenergy", "textures/gui/GuiBatteryRack.png")));
int x = (width - xSize) / 2;
int y = (height - ySize) / 2;
this.drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
this.drawTexturedModalRect(x+40, y+19, 0, 179, (int) (bar/EndoEnergy.BatteryRackCapacity*96), 12);
}
}
Thanks in advance,
Redstonedude, head programmer of the endernoobs modding team