Posted September 24, 201411 yr hello I'm trying to change a tag in the NBT data of an itemstack that is in a container from a gui (on the press of a button). when the button is pressed, the packet seems to be successfully sent and processed, but nothing happens. Packet/handler package com.zpig333.runesofwizardry.gui; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; /**@see http://www.minecraftforge.net/forum/index.php/topic,20135.0.html * */ public class DustDyeButtonPacket implements IMessage { private String text; private int color; //private TileEntityDustDye source; private ItemStack stack; private int type; private int x,y,z; //position of the tileentity public final static int TYPE_TEXT=0, TYPE_DYE=1; public DustDyeButtonPacket(){ this.type=-1; } public DustDyeButtonPacket(int color, ItemStack stack){ this.type=TYPE_DYE; this.color=color; this.stack=stack; //DEBUG System.out.println("packet created"); } public DustDyeButtonPacket(int x, int y, int z, int color){ this.type=TYPE_DYE; this.x=x; this.y=y; this.z=z; this.color=color; } @Override public void fromBytes(ByteBuf buf) { type=ByteBufUtils.readVarShort(buf); /* try { ObjectInputStream stream =new ObjectInputStream(new ByteBufInputStream(buf)); Object in=stream.readObject(); if(in instanceof TileEntityDustDye){ source=(TileEntityDustDye)in; } } catch (IOException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); } catch (ClassNotFoundException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); }*/ if(type==TYPE_TEXT){ text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects }else if(type==TYPE_DYE){ color=ByteBufUtils.readVarInt(buf, 5); //stack=ByteBufUtils.readItemStack(buf); x=ByteBufUtils.readVarInt(buf, 5); y=ByteBufUtils.readVarInt(buf, 5); z=ByteBufUtils.readVarInt(buf, 5); } //DEBUG System.out.println("packet decoded"); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeVarShort(buf, type); /* ObjectOutputStream stream; try { stream = new ObjectOutputStream(new ByteBufOutputStream(buf)); stream.writeObject(source); } catch (IOException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); }*/ if(type==TYPE_TEXT){ ByteBufUtils.writeUTF8String(buf, text); }else if(type==TYPE_DYE){ ByteBufUtils.writeVarInt(buf, color, 5); //ByteBufUtils.writeItemStack(buf, stack); ByteBufUtils.writeVarInt(buf, x, 5); ByteBufUtils.writeVarInt(buf, y, 5); ByteBufUtils.writeVarInt(buf, z, 5); } //DEBUG System.out.println("packet encoded"); } public static class Handler implements IMessageHandler<DustDyeButtonPacket, IMessage> { @Override public IMessage onMessage(DustDyeButtonPacket message, MessageContext ctx) { //TODO what to do when the button is clicked System.out.println(String.format("Received %s from %s", message, ctx.getServerHandler().playerEntity.getDisplayName())); // System.out.println("type: "+message.type+" stack: "+message.stack); //System.out.println("stack color: "+message.stack.getTagCompound().getInteger("color")); if(message.type==TYPE_DYE){ System.out.println("color: "+message.color); //FIXME tis not do stuffz //message.stack.getTagCompound().setInteger("color", message.color); //System.out.println("stack color: "+message.stack.getTagCompound().getInteger("color")); //message.stack.writeToNBT(message.stack.getTagCompound()); TileEntity te = ctx.getServerHandler().playerEntity.worldObj.getTileEntity(message.x, message.y, message.z); //FIXME fsr this does not recognize the import? if(te instanceof com.zpig333.runesofwizardry.tileentity.TileEntityDustDye){ com.zpig333.runesofwizardry.tileentity.TileEntityDustDye ted; ted = (com.zpig333.runesofwizardry.tileentity.TileEntityDustDye)te; ted.dye(message.color); } }else if(message.type==TYPE_TEXT){ //message.source.setColor(message.text); } return null; // no response in this case } } } TileEntity package com.zpig333.runesofwizardry.tileentity; import com.zpig333.runesofwizardry.item.ItemDyedDust; import java.io.Serializable; 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; import net.minecraft.tileentity.TileEntity; public class TileEntityDustDye extends TileEntity implements IInventory{ //only 1 slot for now, might change if dyes are required as input private ItemStack[] contents = new ItemStack[1]; //the currently selected color private String colorString; public TileEntityDustDye(){ super(); //colorString="Color"; } public void dye(int color){ contents[0].getTagCompound().setInteger("color", color); setColor(Integer.toHexString(color)); } /** * * @return the currently selected Color of this block as a String */ public String getColor(){ return colorString; } /** * * @param color the selected color */ public void setColor(String color){ colorString=color; } @Override public int getSizeInventory() { return contents.length; } @Override public ItemStack getStackInSlot(int i1) { return contents[i1]; } /** * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a * new stack. */ @Override public ItemStack decrStackSize(int slot, int number) { if (this.contents[slot] != null) { ItemStack itemstack; if (this.contents[slot].stackSize <= number) { itemstack = this.contents[slot]; this.contents[slot] = null; return itemstack; } else { itemstack = this.contents[slot].splitStack(number); if (this.contents[slot].stackSize == 0) { this.contents[slot] = null; } return itemstack; } } else { return null; } } /** * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). */ @Override public void setInventorySlotContents(int slot, ItemStack stack) { contents[slot]=stack; contents[slot] = stack; /* if (stack != null && stack.stackSize > getInventoryStackLimit()) { stack.stackSize = getInventoryStackLimit(); } */ } @Override /** * 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 slot) { ItemStack stack = getStackInSlot(slot); if (stack != null) { setInventorySlotContents(slot, null); } return stack; } @Override /** * Returns the name of the inventory */ public String getInventoryName() { return "RunesWiz.DustDye"; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return worldObj.getTileEntity(xCoord, yCoord, zCoord) == this && player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64; } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { //only allow dyed dust in the dyer return slot==0 ? stack.getItem() instanceof ItemDyedDust : false; //from tileentityBrewingStand //return p_94041_1_ == 3 ? p_94041_2_.getItem().isPotionIngredient(p_94041_2_) : p_94041_2_.getItem() instanceof ItemPotion || p_94041_2_.getItem() == Items.glass_bottle; //TODO auto-generated method: isItemValidForSlot //throw new UnsupportedOperationException("Not supported yet: isItemValidForSlot"); } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean hasCustomInventoryName() { return true; } @Override public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); NBTTagList tagList = tagCompound.getTagList("Inventory",10); for (int i = 0; i < tagList.tagCount(); i++) { NBTTagCompound tag = tagList.getCompoundTagAt(i); byte slot = tag.getByte("Slot"); if (slot >= 0 && slot < contents.length) { contents[slot] = ItemStack.loadItemStackFromNBT(tag); } } this.colorString=tagCompound.getString("Color"); } //FIXME fsr, the color string does not save between game sessions @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); NBTTagList itemList = new NBTTagList(); for (int i = 0; i < contents.length; i++) { ItemStack stack = contents[i]; if (stack != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setByte("Slot", (byte) i); stack.writeToNBT(tag); itemList.appendTag(tag); } } tagCompound.setTag("Inventory", itemList); tagCompound.setString("Color", colorString); } } Container package com.zpig333.runesofwizardry.client.container; import com.zpig333.runesofwizardry.item.ItemDyedDust; import com.zpig333.runesofwizardry.tileentity.TileEntityDustDye; 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.Slot; import net.minecraft.item.ItemStack; public class ContainerDustDye extends Container { protected TileEntityDustDye tileEntity; public ContainerDustDye(InventoryPlayer inventoryPlayer, TileEntityDustDye te) { tileEntity = te; //the Slot constructor takes the IInventory and the slot number in that it binds to //and the x-y coordinates it resides on-screen addSlotToContainer(new ContainerDustDye.Dye(tileEntity, 0, 116,30)); /*for (int i = 0; i < 1; i++) { for (int j = 0; j < 1; j++) { addSlotToContainer(new Slot(tileEntity, j + i * 3, 62 + j * 18, 17 + i * 18)); } }*/ //commonly used vanilla code that adds the player's inventory bindPlayerInventory(inventoryPlayer); } @Override public boolean canInteractWith(EntityPlayer player) { return tileEntity.isUseableByPlayer(player); } 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)); } } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slot) { ItemStack stack = null; Slot slotObject = (Slot) inventorySlots.get(slot); //null checks and checks if the item can be stacked (maxStackSize > 1) if (slotObject != null && slotObject.getHasStack()) { ItemStack stackInSlot = slotObject.getStack(); stack = stackInSlot.copy(); //merges the item into player inventory since its in the tileEntity if (slot < 9) { if (!this.mergeItemStack(stackInSlot, 0, 35, true)) { return null; } } //places it into the tileEntity is possible since its in the player inventory else if (!this.mergeItemStack(stackInSlot, 0, 9, false)) { return null; } if (stackInSlot.stackSize == 0) { slotObject.putStack(null); } else { slotObject.onSlotChanged(); } if (stackInSlot.stackSize == stack.stackSize) { return null; } slotObject.onPickupFromSlot(player, stackInSlot); } return stack; } static class Dye extends Slot{ public Dye(IInventory inv, int a, int b, int c){ super(inv, a, b, c); } @Override public boolean isItemValid(ItemStack stack){ //only allow dyed dusts in the slot return stack.getItem() instanceof ItemDyedDust; } } } GUI package com.zpig333.runesofwizardry.gui; //TODO maybe the lwjgl color should be used? import java.awt.Color; import com.zpig333.runesofwizardry.RunesOfWizardry; import com.zpig333.runesofwizardry.client.container.ContainerDustDye; import com.zpig333.runesofwizardry.core.References; import com.zpig333.runesofwizardry.core.ModLogger; import com.zpig333.runesofwizardry.tileentity.TileEntityDustDye; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.InventoryPlayer; import org.lwjgl.opengl.GL11; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiTextField; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; import org.lwjgl.input.Keyboard; /*TODO major cleanup required, * this is a mashup from many different examples/tutorials * there is probably a lot of useless code */ public class GuiDustDye extends GuiContainer { public static final int GUI_ID = 1; public static final int GUI_DYE_BUTTON=0; private static final int textureX = 175, textureY = 166; private String colorString; private Color color; private int colorInt=0; private boolean validColor=false; private GuiTextField textColor; //the tile entity source for this GUI private final TileEntityDustDye PARENT; public GuiDustDye(InventoryPlayer inventoryPlayer, TileEntityDustDye tileEntity) { //the container is instanciated and passed to the superclass for handling super(new ContainerDustDye(inventoryPlayer, tileEntity)); //sets the parent entity PARENT=tileEntity; colorString=PARENT.getColor(); if(colorString==null)colorString="Color"; } /** runs once every time the GUI is opened * */ @Override public void initGui(){ super.initGui(); Keyboard.enableRepeatEvents(true); //posX, posY defines the top left pixel of the gui display int posX = (this.width - textureX) /2; int posY = (this.height - textureY) /2; //GuiTextField(fontrenderer, x, y, sizeX, sizeY) //here, 0,0 is the top left of the texture... textColor = new GuiTextField(this.fontRendererObj, 105, 14, 45, 12); textColor.setMaxStringLength(6); textColor.setEnableBackgroundDrawing(false); textColor.setVisible(true); textColor.setTextColor(16777215); textColor.setText(colorString); updateColor(); textColor.setFocused(true); textColor.setCanLoseFocus(true); //textColor.setDisabledTextColour(16777215); //textColor.setCursorPositionEnd(); //id, x, y, width, height, text //note: height seems to need to be 20 to display full button texture buttonList.add(new GuiButton(GUI_DYE_BUTTON,posX+99,posY+55,50,20,"Dye")); } @Override public void updateScreen(){ textColor.updateCursorCounter(); } @Override public void onGuiClosed(){ super.onGuiClosed(); Keyboard.enableRepeatEvents(false); } /**when a key is typed. equivalent of keyListener * * @param par1 * @param par2 */ @Override protected void keyTyped(char par1, int par2){ /* if(textColor.isFocused()){ textColor.textboxKeyTyped(par1, par2); colorString = textColor.getText(); PARENT.setColor(colorString); try{ //parsing in hexadecimal allows for a more natural, html-style color input colorInt=Integer.parseInt(colorString,16); color = new Color(colorInt); validColor=true; }catch(NumberFormatException e){ //this might spam a bit... ModLogger.logDebug("GuiDustDye could not parse colorString to Integer"); validColor=false; }catch(Exception e){ e.printStackTrace(); } } if(!textColor.isFocused()||par2 == '27'){ super.keyTyped(par1, par2); }*/ if(textColor.textboxKeyTyped(par1, par2)){ colorString = textColor.getText(); // RunesOfWizardry.networkWrapper.sendToServer(new DustDyeButtonPacket(colorString, PARENT)); updateColor(); }else{ super.keyTyped(par1, par2); } } /** updates the color to the text * */ private void updateColor(){ try{ //parsing in hexadecimal allows for a more natural, html-style color input //that is, 2 (hex) digits per color (RGB) colorInt=Integer.parseInt(colorString,16); color = new Color(colorInt); validColor=true; }catch(NumberFormatException e){ //this might spam a bit... ModLogger.logDebug("GuiDustDye could not parse colorString to Integer"); validColor=false; }catch(Exception e){ e.printStackTrace(); } } @Override protected void mouseClicked(int par1, int par2, int par3){ //posX, posY defines the top left pixel of the gui display int posX = (this.width - textureX) /2; int posY = (this.height - textureY) /2; //DEBUG flag used by textColor.mouseClicked /* boolean flag = par1 >= textColor.xPosition && par1 < textColor.xPosition + textColor.width && par2 >= textColor.yPosition && par2 < textColor.yPosition + textColor.height; System.out.println(flag+": par1="+par1+" par2="+par2+ "\nx="+textColor.xPosition+" y="+textColor.yPosition+ "\nwidth="+textColor.width+" height="+textColor.height+ "\npassed: "+(par1-posX)+", "+(par2-posY)); */ /*Well, it seems the click is located relative to the window, * while the text field position depends on the texture * WTF Minecraft? * anyways, compensating... */ textColor.mouseClicked(par1-posX, par2-posY, par3); super.mouseClicked(par1, par2, par3); } /** runs while the GUI is open * * @param param1 * @param param2 */ @Override protected void drawGuiContainerForegroundLayer(int param1, int param2) { //draw text and stuff here //the parameters for drawString are: string, x, y, color fontRendererObj.drawString("Dust Dye", 8, 6, 4210752); //draws "Inventory" or your regional equivalent fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752); textColor.drawTextBox(); if(!validColor){ //TODO this is slightly small fontRendererObj.drawString("!", 98, 15, 0xFF0000); } // x1, y1, x2, y2, color (NOTE: first byte (2 char) of color is alpha) drawRect(77, 59, 92, 71, 0xff000000+colorInt); //fontRendererObj.drawString("##", 0, 0, colorInt); //super.drawGuiContainerForegroundLayer(param1, param2); } @Override protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3) { //draw your Gui here, only thing you need to change is the path GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.renderEngine.bindTexture(new ResourceLocation(References.texture_path+"textures/gui/GuiDustDye.png")); int x = (width - xSize) / 2; int y = (height - ySize) / 2; this.drawTexturedModalRect(x, y, 0, 0, xSize, ySize); } /** called when a button is clicked * * @param button the button that was clicked (?) */ protected void actionPerformed(GuiButton button){ switch(button.id){ case GUI_DYE_BUTTON: //send the selected colour to the server RunesOfWizardry.networkWrapper.sendToServer(new DustDyeButtonPacket(colorInt,PARENT.getStackInSlot(0))); //Hopefully this will work //FIXME nope, reset when it leaves GUI //PARENT.getStackInSlot(0).getTagCompound().setInteger("color", colorInt); //break; default: System.out.println("Button clicked "+button.displayString+" "+button.id); break; } } } I can't figure what is not working, please help. EDIT: forge 1.7.10 (1.7.10-10.13.0.1188)
September 25, 201411 yr When you say nothing happens, are you logging the expected changes on the server or client? In my example, I send the updated info back to the client as the return to the Imessage (another packet) @Override public IMessage onMessage(ChangeCostUp message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().playerEntity; ContainerShop container = (ContainerShop)player.openContainer; container.tileEntity.Cost++; if(container.tileEntity.Cost > 144) container.tileEntity.Cost = 144; player.worldObj.markBlockForUpdate(container.tileEntity.xCoord, container.tileEntity.yCoord, container.tileEntity.zCoord); container.tileEntity.markDirty(); return new SendCost((short) container.tileEntity.Cost); } whether you are updating a field (in my case) or NBT (yours) the situation should be the same. I'll need help, and I'll give help. Just ask, you know I will!
September 25, 201411 yr ..to clarify my example, the client has a gui open, presses a button, and then this packet is sent to the server for processing, where the value is changed. I returned a packet to update the client from this, where you are only returning null. Guis sit on the client alone, and so will not be updating automatically. Again, my first question would be where are you watching the value to which nothing is happening? I'll need help, and I'll give help. Just ask, you know I will!
September 25, 201411 yr Author where are you watching the value to which nothing is happening I'm not sure... I would guess on the client (the item in question changes its rendering depending on the NBT, and it does not change when the button is pressed). that said, it is not updated on world reload either. I see I don't mark the tileentity as dirty, I'll try that... also, out of curiosity, how do you handle your SendCost packet (reply) on the client?
September 25, 201411 yr return new SendCost((short) container.tileEntity.Cost); In this scenario, SendCost is just another packet, registered on the client side, not the server. So just like any other packet. network.registerMessage(PacketToServer.Handler.class, PacketToServer.class, 0, Side.SERVER); network.registerMessage(ResponseToClient.Handler.class, ResponseToClient.class, 1, Side.CLIENT); @Override public IMessage onMessage(PacketToServer message, MessageContext ctx) { return new ResponseToClient(); } @Override public IMessage onMessage(ResponseToClient message, MessageContext ctx) { return null; } I'll need help, and I'll give help. Just ask, you know I will!
September 25, 201411 yr Author I meant to update the client... I tried setting up a reply, but the item still does not change. I mus be doing something wrong, but I can't find what packet package com.zpig333.runesofwizardry.gui; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; /**@see http://www.minecraftforge.net/forum/index.php/topic,20135.0.html * */ public class DustDyeButtonPacket implements IMessage { private String text; private int color; //private TileEntityDustDye source; private ItemStack stack; private int type; private int x,y,z; //position of the tileentity public final static int TYPE_TEXT=0, TYPE_DYE=1, TYPE_REPLY=2; public DustDyeButtonPacket(){ this.type=-1; } public DustDyeButtonPacket(int color, ItemStack stack){ this.type=TYPE_REPLY; this.color=color; this.stack=stack; //DEBUG System.out.println("packet created"); } public DustDyeButtonPacket(int x, int y, int z, int color){ this.type=TYPE_DYE; this.x=x; this.y=y; this.z=z; this.color=color; } @Override public void fromBytes(ByteBuf buf) { type=ByteBufUtils.readVarShort(buf); /* try { ObjectInputStream stream =new ObjectInputStream(new ByteBufInputStream(buf)); Object in=stream.readObject(); if(in instanceof TileEntityDustDye){ source=(TileEntityDustDye)in; } } catch (IOException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); } catch (ClassNotFoundException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); }*/ if(type==TYPE_TEXT){ text = ByteBufUtils.readUTF8String(buf); // this class is very useful in general for writing more complex objects }else if(type==TYPE_DYE){ color=ByteBufUtils.readVarInt(buf, 5); //stack=ByteBufUtils.readItemStack(buf); x=ByteBufUtils.readVarInt(buf, 5); y=ByteBufUtils.readVarInt(buf, 5); z=ByteBufUtils.readVarInt(buf, 5); }else if(type==TYPE_REPLY){ color=ByteBufUtils.readVarInt(buf, 5); stack=ByteBufUtils.readItemStack(buf); } //DEBUG System.out.println("packet decoded"); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeVarShort(buf, type); /* ObjectOutputStream stream; try { stream = new ObjectOutputStream(new ByteBufOutputStream(buf)); stream.writeObject(source); } catch (IOException ex) { Logger.getLogger(DustDyeButtonPacket.class.getName()).log(Level.SEVERE, null, ex); }*/ if(type==TYPE_TEXT){ ByteBufUtils.writeUTF8String(buf, text); }else if(type==TYPE_DYE){ ByteBufUtils.writeVarInt(buf, color, 5); //ByteBufUtils.writeItemStack(buf, stack); ByteBufUtils.writeVarInt(buf, x, 5); ByteBufUtils.writeVarInt(buf, y, 5); ByteBufUtils.writeVarInt(buf, z, 5); }else if(type==TYPE_REPLY){ ByteBufUtils.writeVarInt(buf, color, 5); ByteBufUtils.writeItemStack(buf, stack); } //DEBUG System.out.println("packet encoded"); } public static class Handler implements IMessageHandler<DustDyeButtonPacket, IMessage> { @Override public IMessage onMessage(DustDyeButtonPacket message, MessageContext ctx) { //TODO what to do when the button is clicked System.out.println(String.format("Received %s from %s", message, ctx.getServerHandler().playerEntity.getDisplayName())); // System.out.println("type: "+message.type+" stack: "+message.stack); //System.out.println("stack color: "+message.stack.getTagCompound().getInteger("color")); if(message.type==TYPE_DYE){ System.out.println("color: "+message.color); //FIXME tis not do stuffz //message.stack.getTagCompound().setInteger("color", message.color); //System.out.println("stack color: "+message.stack.getTagCompound().getInteger("color")); //message.stack.writeToNBT(message.stack.getTagCompound()); EntityPlayer player = ctx.getServerHandler().playerEntity; TileEntity te = player.worldObj.getTileEntity(message.x, message.y, message.z); //FIXME fsr this does not recognize the import? if(te instanceof com.zpig333.runesofwizardry.tileentity.TileEntityDustDye){ com.zpig333.runesofwizardry.tileentity.TileEntityDustDye ted; ted = (com.zpig333.runesofwizardry.tileentity.TileEntityDustDye)te; ted.dye(message.color); player.worldObj.markBlockForUpdate(ted.xCoord, ted.yCoord, ted.zCoord); ted.markDirty(); return new DustDyeButtonPacket(message.color, ted.getStackInSlot(0)); } }else if(message.type==TYPE_TEXT){ return null; //message.source.setColor(message.text); }else if(message.type==TYPE_REPLY){ message.stack.getTagCompound().setInteger("color", message.color); return null; } throw new IllegalArgumentException("Could not process message, "+message.type); } } }
September 25, 201411 yr You can't send the same packet back to the client. What you want to do is simplify your packets as much as possible. For example, make a button that increases a value. This will send an empty pack to the server (and is registered to be handled by the server) called, lets say, InrcreaseValuePacket(). The server sees this packet, and increases the value. You can make as many buttons and packets as you like! Then each of those will have a relative packet, say RespondWithIncreasePacket(), that is registered on the client. If you send packet A to the server - where its registered to be handled - you cant send packet A back to the client, it won't ever hit the handler. You would make packet B and register is to be handled on the client. You can make unlimited packets, just make sure you register the handlers on the right side, and also you can minimize the information stored within. It looks like you are sending an UpdateEveryValueEver() packet to the server, and trying to send the UpdateEveryValueEver() packet right back to client (sometimes.) One possible example of flow could/should be like this: Player activates block which opens gui on the client only Gui sends update request to server(packet A) server responds with data the gui needs to display(packet B) player clicks button to adjust a value gui sends packet to adjust specific value to server(packet C) server receives packet and changes value, responds with either total update (packet B) or value specific update (packet D) Packets A and C would be registered to be handled on the server and would most likely hold 0 specific data whatsoever. the server would know what to do just based on the packet type. Packets B and D would be registered to be handled on the client, and packet D would have the advantage of not carrying much data. ...I sure hope that makes sense/helps! I'll need help, and I'll give help. Just ask, you know I will!
September 26, 201411 yr Author yes, this makes sense. I tried doing that, but I have trouble understanding how to arrange the communication between the GUI and the packethandler. if it helps, the full code is on GitHub.
October 9, 201411 yr Author ok, i've set up a few new packets in an attempt to properly update things, but I get a crash when opening the GUI. log: [15:56:55] [server thread/ERROR] [FML]: FMLIndexedMessageCodec exception caught io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?] at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?] at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?] at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?] at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:247) [NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:736) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:624) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:495) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:762) [MinecraftServer$2.class:?] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?] at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:562) ~[AbstractByteBuf.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readVarInt(ByteBufUtils.java:46) ~[byteBufUtils.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readUTF8String(ByteBufUtils.java:118) ~[byteBufUtils.class:?] at com.zpig333.runesofwizardry.gui.DustDyeUpdatePacket.fromBytes(DustDyeUpdatePacket.java:27) ~[DustDyeUpdatePacket.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?] at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?] ... 13 more [15:56:55] [server thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?] at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?] at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?] at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?] at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:247) [NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:736) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:624) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:495) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:762) [MinecraftServer$2.class:?] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?] at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:562) ~[AbstractByteBuf.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readVarInt(ByteBufUtils.java:46) ~[byteBufUtils.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readUTF8String(ByteBufUtils.java:118) ~[byteBufUtils.class:?] at com.zpig333.runesofwizardry.gui.DustDyeUpdatePacket.fromBytes(DustDyeUpdatePacket.java:27) ~[DustDyeUpdatePacket.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?] at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?] ... 13 more [15:56:55] [server thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?] at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?] at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?] at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?] at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:247) [NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:736) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:624) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:495) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:762) [MinecraftServer$2.class:?] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?] at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:562) ~[AbstractByteBuf.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readVarInt(ByteBufUtils.java:46) ~[byteBufUtils.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readUTF8String(ByteBufUtils.java:118) ~[byteBufUtils.class:?] at com.zpig333.runesofwizardry.gui.DustDyeUpdatePacket.fromBytes(DustDyeUpdatePacket.java:27) ~[DustDyeUpdatePacket.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?] at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?] ... 13 more [15:56:55] [server thread/ERROR] [FML]: SimpleChannelHandlerWrapper exception io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?] at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?] at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) [DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) [DefaultChannelPipeline.class:?] at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) [EmbeddedChannel.class:?] at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:247) [NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:736) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:624) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:495) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:762) [MinecraftServer$2.class:?] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?] at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:562) ~[AbstractByteBuf.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readVarInt(ByteBufUtils.java:46) ~[byteBufUtils.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readUTF8String(ByteBufUtils.java:118) ~[byteBufUtils.class:?] at com.zpig333.runesofwizardry.gui.DustDyeUpdatePacket.fromBytes(DustDyeUpdatePacket.java:27) ~[DustDyeUpdatePacket.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?] at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?] ... 13 more [15:56:55] [server thread/ERROR] [FML]: There was a critical exception handling a packet on channel RunesWiz io.netty.handler.codec.DecoderException: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:99) ~[MessageToMessageDecoder.class:?] at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[MessageToMessageCodec.class:?] at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337) ~[DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323) ~[DefaultChannelHandlerContext.class:?] at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785) ~[DefaultChannelPipeline.class:?] at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169) ~[EmbeddedChannel.class:?] at cpw.mods.fml.common.network.internal.FMLProxyPacket.processPacket(FMLProxyPacket.java:86) [FMLProxyPacket.class:?] at net.minecraft.network.NetworkManager.processReceivedPackets(NetworkManager.java:247) [NetworkManager.class:?] at net.minecraft.network.NetworkSystem.networkTick(NetworkSystem.java:182) [NetworkSystem.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:736) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:624) [MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:118) [integratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:495) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer$2.run(MinecraftServer.java:762) [MinecraftServer$2.class:?] Caused by: java.lang.IndexOutOfBoundsException: readerIndex(11) + length(1) exceeds writerIndex(11): SlicedByteBuf(ridx: 11, widx: 11, cap: 11/11, unwrapped: UnpooledHeapByteBuf(ridx: 1, widx: 12, cap: 12/12)) at io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1160) ~[AbstractByteBuf.class:?] at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:562) ~[AbstractByteBuf.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readVarInt(ByteBufUtils.java:46) ~[byteBufUtils.class:?] at cpw.mods.fml.common.network.ByteBufUtils.readUTF8String(ByteBufUtils.java:118) ~[byteBufUtils.class:?] at com.zpig333.runesofwizardry.gui.DustDyeUpdatePacket.fromBytes(DustDyeUpdatePacket.java:27) ~[DustDyeUpdatePacket.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7) ~[simpleIndexedCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77) ~[FMLIndexedMessageToMessageCodec.class:?] at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17) ~[FMLIndexedMessageToMessageCodec.class:?] at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81) ~[MessageToMessageCodec$2.class:?] at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89) ~[MessageToMessageDecoder.class:?] ... 13 more [15:56:55] [server thread/INFO]: Player180 lost connection: TextComponent{text='A fatal error has occured, this connection is terminated', siblings=[], style=Style{hasParent=false, color=null, bold=null, italic=null, underlined=null, obfuscated=null, clickEvent=null, hoverEvent=null}} [15:56:55] [server thread/INFO]: Player180 left the game I can't find where this comes from code (GitHub because IMO it's easier than copy-pasting 5 files and miss those you need to see)
October 9, 201411 yr I can tell you from that error that you haven't numbered your packets correctly - they each need an individual number - or you haven't referenced that number correctly. I'll need help, and I'll give help. Just ask, you know I will!
October 9, 201411 yr Author numbered? do you mean the "discriminator"/[whatever it's called int] parameter of registerMessage?
October 11, 201411 yr Author yep, that was it. However, for the packet that updates the GUI/TileEntity, should I register it on Side.SERVER or Side.CLIENT? if it is on Client, how do I access the TileEntity? the client handler (MessageContext.getClientHandler()) does not have access to the player/world to obtain the TE (and, of course, getServerHandler crashes since it's client-side)
October 12, 201411 yr Yes, that can be tricky! I added a field to store my TE in my container, which I assigned in construction. Then, I was able to access the TE through the container in the client packet handler like such: GuiScreen screen = Minecraft.getMinecraft().currentScreen; if (screen instanceof GuiShopper) { ContainerShopper container = ((GuiShopper) screen).container; container.tileEntity.Cost = message.cost; container.tileEntity.markDirty(); } Your usage will look different, but you get the idea. You are right, you cant access the player simply! I'll need help, and I'll give help. Just ask, you know I will!
October 13, 201411 yr Author thanks! I can now successfully save stuff in my TileEntity now, all I have to do is get those ItemStacks to change their NBT on button press...
October 13, 201411 yr You should be able to get it now. Maybe the flow would be like: Client presses button(handled in the gui) Gui sends a packet "pressedUpButton" to server Server makes changes to item nbt according to "up button" packet Server responds with a "ichangedthenbt" packet Client changes the local nbt or refreshes from server, etc. to you can see the changes in the gui Eat a cookie I'll need help, and I'll give help. Just ask, you know I will!
October 14, 201411 yr Author that is indeed what I did, and it works (also, the reply from the server does not seem necessary either). however, I noticed that if I break the tileEntity and place a new one in the same spot, the new one takes the properties of the old one, and if there was an ItemStack in it (dropped when the TE is broken), it is still there, although with only 1 item. Reloading the world between the breaking and placing of the TE fixes it. do I need to do something specific to reset the TileEntity when it is broken?
October 14, 201411 yr Author here you go. also, I didn't notice before, but the block seems to be instantly broken (and does not drop) with the empty hand in survival mode, even though the harvest level has been set. package com.zpig333.runesofwizardry.block; import com.zpig333.runesofwizardry.RunesOfWizardry; import com.zpig333.runesofwizardry.core.ModLogger; import com.zpig333.runesofwizardry.gui.GuiDustDye; import com.zpig333.runesofwizardry.tileentity.TileEntityDustDye; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class BlockDustDye extends BlockContainer { private Random random = new Random(); public BlockDustDye(Material mat) { super(mat); setCreativeTab(RunesOfWizardry.wizardry_tab); setHarvestLevel("pickaxe", 0); } @Override public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) { return new TileEntityDustDye(); } //drops the items when the block is broken (?) @Override public void breakBlock(World p_149749_1_, int p_149749_2_, int p_149749_3_, int p_149749_4_, Block p_149749_5_, int p_149749_6_) { TileEntityDustDye tileentityDustDye = (TileEntityDustDye) p_149749_1_.getTileEntity(p_149749_2_, p_149749_3_, p_149749_4_); if (tileentityDustDye != null) { for (int i1 = 0; i1 < tileentityDustDye.getSizeInventory(); ++i1) { ItemStack itemstack = tileentityDustDye.getStackInSlot(i1); if (itemstack != null) { float f = this.random.nextFloat() * 0.8F + 0.1F; float f1 = this.random.nextFloat() * 0.8F + 0.1F; EntityItem entityitem; for (float f2 = this.random.nextFloat() * 0.8F + 0.1F; itemstack.stackSize > 0; p_149749_1_.spawnEntityInWorld(entityitem)) { int j1 = this.random.nextInt(21) + 10; if (j1 > itemstack.stackSize) { j1 = itemstack.stackSize; } itemstack.stackSize -= j1; entityitem = new EntityItem(p_149749_1_, (double) ((float) p_149749_2_ + f), (double) ((float) p_149749_3_ + f1), (double) ((float) p_149749_4_ + f2), new ItemStack(itemstack.getItem(), j1, itemstack.getItemDamage())); float f3 = 0.05F; entityitem.motionX = (double) ((float) this.random.nextGaussian() * f3); entityitem.motionY = (double) ((float) this.random.nextGaussian() * f3 + 0.2F); entityitem.motionZ = (double) ((float) this.random.nextGaussian() * f3); if (itemstack.hasTagCompound()) { entityitem.getEntityItem().setTagCompound((NBTTagCompound) itemstack.getTagCompound().copy()); } } } } p_149749_1_.func_147453_f(p_149749_2_, p_149749_3_, p_149749_4_, p_149749_5_); } } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int metadata, float what, float these, float are){ /* if (world.isRemote) { return true; } else { */ TileEntityDustDye tileentityDD = (TileEntityDustDye)world.getTileEntity(x,y,z); if (tileentityDD == null || player.isSneaking()) { return false; } player.openGui(RunesOfWizardry.instance, GuiDustDye.GUI_ID, world, x, y, z); return true; } }
October 15, 201411 yr Author adding tileentityDustDye.invalidate(); at the end of the the breakBlock method seems to fix the issue where the issue of the container staying the same after breaking it, although I am unsure of what this method does.
October 18, 201411 yr Author SOLVED. it seems the proper way of fixing the "ghost" tileEntity was to call super.breakBlock() also, harvesting problem was solved by using setHardness() and making canHarvest() always return true.
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.