tiffit Posted May 19, 2015 Share Posted May 19, 2015 So I have my own tile entity with a GUI. Everything works fine, except for 1 thing. Whenever I have the plugin remove an item from a slot, on the client it looks fine. When you click on the itemstack, or exit out of the inventory, the item stacks returns to how it was before. So lets say I put in 10 diamond into the GUI. I let it use up 5 diamond. There is 5 diamond left in the GUI. When I close the GUI and open it up again, there is 10 diamonds in the GUI. I don't know if this is a miscommunication between the server and the client, or what. Below is my tile entity class. It is probably something really obvious, but I spent a while and couldn't find anything public class TileEntityControlledStriker extends TileEntity implements IInventory, IUpdatePlayerListBox{ public int storedMagic = 0; public boolean isStriking; public int timeUntilNextStrike = 100; public ItemStack[] stacks = new ItemStack[3]; protected String customName; public int getSizeInventory(){ return 3; } /** * Returns the stack in slot i */ public ItemStack getStackInSlot(int index) { return this.stacks[index]; } /** * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a * new stack. */ public ItemStack decrStackSize(int index, int count) { if (this.stacks[index] != null) { ItemStack itemstack; if (this.stacks[index].stackSize <= count) { itemstack = this.stacks[index]; this.stacks[index] = null; this.markDirty(); return itemstack; } else { itemstack = this.stacks[index].splitStack(count); if (this.stacks[index].stackSize == 0) { this.stacks[index] = null; } this.markDirty(); return itemstack; } } else { return null; } } /** * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - * like when you close a workbench GUI. */ public ItemStack getStackInSlotOnClosing(int index){ return null; } /** * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). */ public void setInventorySlotContents(int index, ItemStack stack){ this.stacks[index] = stack; if (stack != null && stack.stackSize > this.getInventoryStackLimit()){ stack.stackSize = this.getInventoryStackLimit(); } this.markDirty(); } /** * Gets the name of this command sender (usually username, but possibly "Rcon") */ public String getName() { return this.hasCustomName() ? this.customName : "container.dispenser"; } public void setCustomName(String customName) { this.customName = customName; } /** * Returns true if this thing is named */ public boolean hasCustomName() { return this.customName != null; } public int getInventoryStackLimit() { return 64; } /** * Do not make give this method the name canInteractWith because it clashes with Container */ public boolean isUseableByPlayer(EntityPlayer player) { return this.worldObj.getTileEntity(this.pos) != this ? false : player.getDistanceSq((double)this.pos.getX() + 0.5D, (double)this.pos.getY() + 0.5D, (double)this.pos.getZ() + 0.5D) <= 64.0D; } public void openInventory(EntityPlayer player) {} public void closeInventory(EntityPlayer player) {} /** * Returns true if automation is allowed to insert the given stack (ignoring stack size) into the given slot. */ public boolean isItemValidForSlot(int index, ItemStack stack) { return false; } public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) { return new ContainerDispenser(playerInventory, this); } public int getField(int id) { return 0; } public void setField(int id, int value) {} public int getFieldCount() { return 0; } public void clear() { for (int i = 0; i < this.stacks.length; ++i) { this.stacks[i] = null; } } @Override public IChatComponent getDisplayName() { return null; } @Override public void readFromNBT(NBTTagCompound compound){ super.readFromNBT(compound); stacks = new ItemStack[3]; NBTTagList invStacksTag = compound.getTagList("stacks", 10); for(int i = 0; i < invStacksTag.tagCount(); i++){ NBTTagCompound t = invStacksTag.getCompoundTagAt(i); int index = t.getByte("index"); if(index >= 0 && index < stacks.length){ stacks[index] = ItemStack.loadItemStackFromNBT(t); } } this.storedMagic = compound.getInteger("storedMagic"); } @Override public void writeToNBT(NBTTagCompound compound){ super.writeToNBT(compound); NBTTagList invStacksTag = new NBTTagList(); for(int i = 0; i < stacks.length; i++){ ItemStack stack = stacks[i]; if(stack != null){ NBTTagCompound t = new NBTTagCompound(); stack.writeToNBT(t); t.setByte("index", (byte)i); invStacksTag.appendTag(t); } } compound.setTag("stacks", invStacksTag); compound.setInteger("storedMagic", this.storedMagic); } public void strike(){ EntityLightningBolt lightning = new EntityLightningBolt(this.worldObj, pos.getX(), pos.getY(), pos.getZ()); this.worldObj.spawnEntityInWorld(lightning); if(this.storedMagic != 1000){ this.storedMagic += 10; } this.stacks[0].stackSize--; this.stacks[1].stackSize--; Random r = new Random(); int dropChance = r.nextInt(10); if(dropChance == 4){ //TODO this.stacks[2].stackSize++; } this.markDirty(); } @Override public void update() { if(this.isStriking){ this.timeUntilNextStrike--; if(this.timeUntilNextStrike <= 0){ this.timeUntilNextStrike = 100; this.strike(); } } } Quote Link to comment Share on other sites More sharing options...
Ernio Posted May 19, 2015 Share Posted May 19, 2015 Container, Gui? If you are using those - GuiHandler would be also nice. You need to actually setup some packeting (synchro). You use markDirty(), but where is synchro code? Quote 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
tiffit Posted May 19, 2015 Author Share Posted May 19, 2015 Container, Gui? If you are using those - GuiHandler would be also nice. You need to actually setup some packeting (synchro). You use markDirty(), but where is synchro code? I am using a GuiHandler. Also, I am pretty new to packets, could you show me how to do this? Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 19, 2015 Author Share Posted May 19, 2015 You shouldn't need any packets for this. Please show your Container and Gui. Ok here it is Container: public ContainerControlledStriker(InventoryPlayer pl, TileEntityControlledStriker tileEntity){ this.addSlotToContainer(new Slot(tileEntity, 0, 56, 17){ public boolean isItemValid(ItemStack stack){ return stack.getItem() == Main.magicalCopperIngot; } }); this.addSlotToContainer(new Slot(tileEntity, 1, 56, 53){ public boolean isItemValid(ItemStack stack){ Item i = stack.getItem(); return i == Items.diamond || i == Items.iron_ingot || i == Items.gold_ingot || i == Main.copperIngot; } }); this.addSlotToContainer(new Slot(tileEntity, 2, 99, 53){ public boolean isItemValid(ItemStack stack){ return false; } }); this.addPlayerSlots(pl, 8, 84); this.te = tileEntity; } @Override public boolean canInteractWith(EntityPlayer playerIn) { return te.isUseableByPlayer(playerIn); } protected void addPlayerSlots(InventoryPlayer pi, int x, int y){ for (int i = 0; i < 3; ++i){ for (int j = 0; j < 9; ++j){ this.addSlotToContainer(new Slot(pi, j + i * 9 + 9, x + j * 18, y + i * 18)); } } for (int i = 0; i < 9; ++i){ this.addSlotToContainer(new Slot(pi, i, x + i * 18, y + 58)); } } @Override public ItemStack transferStackInSlot(EntityPlayer pl, int i){ return null; } Gui: public class GuiControlledStriker extends GuiContainer{ private static final ResourceLocation GuiTexture = new ResourceLocation(Main.MODID + ":textures/gui/ControlledStriker.png"); TileEntityControlledStriker te; public GuiControlledStriker(InventoryPlayer pi, TileEntityControlledStriker te) { super(new ContainerControlledStriker(pi, te)); this.te = te; } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { mc.getTextureManager().bindTexture(GuiTexture); this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize); double size = (te.storedMagic/1000.0) * 52; int k = (this.width - this.xSize) / 2 + 126; int l = (this.height - this.ySize) / 2 + 69; for(int i = 0; i <= (int) size; i++){ this.drawTexturedModalRect(k, l - i, 176, 52 - i, 20, 1); } } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY){ this.fontRendererObj.drawString("Controlled Striker", 8, 6, 4210752); this.fontRendererObj.drawString("Inventory", 8, this.ySize - 96 + 2, 4210752); int timeSeconds = te.timeUntilNextStrike; if(te.isStriking){ this.fontRendererObj.drawString(timeSeconds + "", 8, this.ySize - 120, 4210752); } int k = (this.width - this.xSize) / 2 + 126; int l = (this.height - this.ySize) / 2 + 69; if(mouseX > k - 1 && mouseY > l - 52 && mouseX < k + 20 && mouseY < l){ this.fontRendererObj.drawString(te.storedMagic + "/1000", this.xSize/2 + 30, 6, 4210752); } this.buttonList.clear(); int posX = (this.width - this.xSize) / 2 + 126; int posY = (this.height - this.ySize) / 2 + 35; String isStriking = "Off"; if(te.isStriking) isStriking = "On"; this.buttonList.add(new GuiButton(0, posX - 40, posY - 15, 30, 20, isStriking)); } @Override public void actionPerformed(GuiButton button){ if(button.id == 0){ if(!te.isStriking && te.stacks[1] != null && te.stacks[0] != null){ te.isStriking = true; }else{ te.timeUntilNextStrike = 100; te.isStriking = false; } } } } GuiHandler: public class GuiHandler implements IGuiHandler{ public enum GuiIDs{ ControlledStriker; } @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(GuiIDs.values()[iD]){ case ControlledStriker: return new ContainerControlledStriker(player.inventory, (TileEntityControlledStriker)world.getTileEntity(new BlockPos(x, y, z))); } throw new IllegalArgumentException("No gui with id " + ID); } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(GuiIDs.values()[iD]){ case ControlledStriker: return new GuiControlledStriker(player.inventory, (TileEntityControlledStriker)world.getTileEntity(new BlockPos(x, y, z))); } throw new IllegalArgumentException("No gui with id " + ID); } } Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 19, 2015 Author Share Posted May 19, 2015 You are setting the "isStriking" field from your GUI directly, meaning it will be set in the client version of the TileEntity. You cannot do stuff like spawn entities or modify inventories (such as your TileEntity) on the client. In your GUI you need to instead send a packet to the server to set the field there. I am confused, can you go into more detail please? What exactly do I need to do? Quote Link to comment Share on other sites More sharing options...
TheRealMcrafter Posted May 19, 2015 Share Posted May 19, 2015 Instead of setting isStriking to true in your GUI class (on the Client), you need to send a packet to the server, and then in your packet handler, you set isStriking to true (on the Server). Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 20, 2015 Author Share Posted May 20, 2015 Instead of setting isStriking to true in your GUI class (on the Client), you need to send a packet to the server, and then in your packet handler, you set isStriking to true (on the Server). Sorry for these "stupid" questions, I am still getting used to packeting. So would I use description packets? Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 20, 2015 Author Share Posted May 20, 2015 Alright, time to start researching on packers Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 20, 2015 Author Share Posted May 20, 2015 http://goo.gl/SA5Rvp That was the first place I was going to check anyways... lol. I remember you making a packeting tutorial Edit: What do I do after I do (so many dos) MyMod.network.sendToServer(new MyMessage("foobar")); I mean, come on, it can't be that simple, can it? Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 20, 2015 Author Share Posted May 20, 2015 Well, you need to send the data you need and then do stuff in the packet handler. But yes, it is that simple. Packets are very easy actually. Sorry for the (probably) stupid questions, but can you define "stuff" Quote Link to comment Share on other sites More sharing options...
tiffit Posted May 24, 2015 Author Share Posted May 24, 2015 Ok. I get everything setup, but it keeps giving me an NPE on the onMessage part of it. Here is my Message class: package tiffit.tiffitsmachines.packets; import io.netty.buffer.ByteBuf; import net.minecraft.util.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import tiffit.tiffitsmachines.tileEntity.TileEntityControlledStriker; public class ControlledStrikerPackets implements IMessage { public int x; public int y; public int z; public World w; public ControlledStrikerPackets() {} public ControlledStrikerPackets(int x, int y, int z, World w) { this.x = x; this.y = y; this.z = z; this.w = w; } @Override public void fromBytes(ByteBuf buf) { } @Override public void toBytes(ByteBuf buf) { } public static class Handler implements IMessageHandler<ControlledStrikerPackets, IMessage> { @Override public IMessage onMessage(ControlledStrikerPackets message, MessageContext ctx){ System.out.print(message != null); TileEntityControlledStriker te = (TileEntityControlledStriker) message.w.getTileEntity(new BlockPos(message.x, message.y, message.z)); if(!te.isStriking && te.stacks[1] != null && te.stacks[0] != null){ te.isStriking = true; }else{ te.timeUntilNextStrike = 100; te.isStriking = false; } return null; } } } Apparently, the "message" object (ControlledStrikerPackets) that it gives me is empty. By empty, I mean all of its fields are null, even though I set them when I send a packet. This is how I send my packet: Main.network.sendToServer(new ControlledStrikerPackets(te.getPos().getX(), te.getPos().getY(), te.getPos().getZ(), te.getWorld())); EDIT: Nevermind, completely forgot about the byte bufs, I got it working now Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.