its_meow Posted April 5, 2017 Posted April 5, 2017 (edited) Basically, I'm trying to make a block that has an adjustable light value via GUI. I have the GUI, graphics, and incrementing buttons that can output the int anytime. So far I have a packet that sends that int to the server, then I have to somehow feed it into that specific tileentity instance and write the int the that instance's NBT, which then can be read from the block of that instance, which then sets the value to that int. I have absolutely no clue what to do. Here's the code that matters. (Yes, I have registered the block and block as a tile entity) READ COMMENTS IN CODE PLEASE Block Class: Reveal hidden contents package its_meow.spaceheater.block.spaceheater; import java.util.Random; import its_meow.spaceheater.SpaceHeaterMod; import its_meow.spaceheater.gui.GUIHeater; import net.minecraft.block.Block; import net.minecraft.block.BlockContainer; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class BlockSpaceHeater extends BlockContainer { public BlockSpaceHeater() { super(Material.ROCK); this.setCreativeTab(SpaceHeaterMod.tab_spaceheater); this.setUnlocalizedName("spaceheater"); this.setRegistryName("spaceheater"); this.setTickRandomly(true); } @Override public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { if(!worldIn.isRemote){ } else { // I know i did this oddly, I should've just done worldIn.isRemote instead of the weird else TileEntity tileEntity = worldIn.getTileEntity(pos); if(tileEntity instanceof SpaceHeaterTileEntity) { GUIHeater heater = new GUIHeater((SpaceHeaterTileEntity) worldIn.getTileEntity(pos)); //This is how i get the specific tile entity instance fed into the GUI. Minecraft.getMinecraft().displayGuiScreen(heater);//Opens GUI } } return false; } @Override public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand) { boolean isHeaterOn = true;//Going to hook this to a button later. TileEntity tileEntity = worldIn.getTileEntity(pos); //The tile entity of this specific instance //int lLevel = ;//Where it's supposed to read NBT and plug into the variable if(isHeaterOn){ this.setLightLevel(/*lLevel*/20F); } else { this.setLightLevel(0F); } //System.out.println(lLevel); super.updateTick(worldIn, pos, state, rand); } @SideOnly(Side.CLIENT) public void initModel(){ ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), 0, new ModelResourceLocation(getRegistryName(), "inventory")); } @Override public void breakBlock(World world, BlockPos pos, IBlockState state) { super.breakBlock(world, pos, state); world.removeTileEntity(pos); } @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new SpaceHeaterTileEntity(); } GUI Class: Reveal hidden contents package its_meow.spaceheater.gui; import its_meow.spaceheater.Ref; import its_meow.spaceheater.block.spaceheater.BlockSpaceHeater; import its_meow.spaceheater.block.spaceheater.SpaceHeaterTileEntity; import its_meow.spaceheater.network.packets.PacketInt; import its_meow.spaceheater.proxy.CommonProxy; import java.io.IOException; import org.lwjgl.opengl.GL11; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import static net.minecraft.client.Minecraft.getMinecraft; public class GUIHeater extends GuiScreen { final ResourceLocation GUITexture = new ResourceLocation(Ref.MOD_ID, "textures/gui/heater.png"); int guiWidth = 248; int guiHeight = 166; GuiButton buttonplus; GuiButton buttonminus; final int BUTTONMINUS = 0; final int BUTTONPLUS = 1; private SpaceHeaterTileEntity te;//Initiates tile entity's specific instance variable public GUIHeater(SpaceHeaterTileEntity te) { this.te = te;//Sets te to the imported tile entity } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks){ drawDefaultBackground(); Minecraft.getMinecraft().renderEngine.bindTexture(GUITexture); int centerX = (width / 2) - (guiWidth / 2); int centerY = (height / 2) - (guiHeight / 2); drawTexturedModalRect(centerX, centerY, 0, 0, guiWidth, guiHeight); String str1 = "Heat Level"; drawCenteredString(fontRendererObj, str1, (width / 2), centerY + 40, 0xFFFFFF); GL11.glPushMatrix(); { GL11.glColor4f(1, 1, 1, 1); Minecraft.getMinecraft().renderEngine.bindTexture(GUITexture); GL11.glPopMatrix(); } super.drawScreen(mouseX, mouseY, partialTicks); } @Override public void initGui(){ buttonList.add(buttonminus = new GuiButton(BUTTONMINUS, (width/2)-150/2, (height)-guiHeight/2, 18, 18, "-")); buttonList.add(buttonplus = new GuiButton(BUTTONPLUS, (width/2)+150/2, (height)-guiHeight/2, 18, 18, "+")); super.initGui(); } private int lightLevel = 11;//This is eventually going to read the NBT for the variable, it currently resets every time you re-open the GUI @Override protected void actionPerformed(GuiButton button) throws IOException { if(button.id == BUTTONPLUS){ System.out.println("plus"); lightLevel++; if(lightLevel - 11 < 0){ lightLevel = 11; } else if(lightLevel - 11 > 10) { lightLevel = 21; } System.out.println("inGUI-11: " + (lightLevel - 11)); int displayLightLevel = (lightLevel - 11); drawCenteredString(fontRendererObj, Integer.toString(displayLightLevel), (width/2), (height)-guiHeight/2, 0xFFFFFF); CommonProxy.packetHandler.INSTANCE.sendToServer(new PacketInt(lightLevel));//Sends the int to the Server, sice GUIs are clientside } if(button.id == BUTTONMINUS){ System.out.println("minus"); lightLevel--; if(lightLevel - 11 < 0){ lightLevel = 11; } else if(lightLevel - 11 > 10) { lightLevel = 21; } System.out.println("inGUI-11: " + (lightLevel - 11)); int displayLightLevel = (lightLevel - 11); drawCenteredString(fontRendererObj, Integer.toString(displayLightLevel), (width/2), (height)-guiHeight/2, 0xFFFFFF); CommonProxy.packetHandler.INSTANCE.sendToServer(new PacketInt(lightLevel));//See above comment } super.actionPerformed(button); } @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { super.keyTyped(typedChar, keyCode); } @Override public boolean doesGuiPauseGame() { return true; } @Override public void onGuiClosed() { super.onGuiClosed(); } } Tile Entity Class: Reveal hidden contents package its_meow.spaceheater.block.spaceheater; import its_meow.spaceheater.gui.GUIHeater; import javax.annotation.Nullable; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; public class SpaceHeaterTileEntity extends TileEntity implements ITickable { //I have no idea how to use NBT, I tried some tutorials, they're really confusing. @Override public NBTTagCompound getUpdateTag() { // getUpdateTag() is called whenever the chunkdata is sent to the // client. In contrast getUpdatePacket() is called when the tile entity // itself wants to sync to the client. In many cases you want to send // over the same information in getUpdateTag() as in getUpdatePacket(). return writeToNBT(new NBTTagCompound()); } @Nullable @Override public SPacketUpdateTileEntity getUpdatePacket() { // Prepare a packet for syncing our TE to the client. Since we only have to sync the stack // and that's all we have we just write our entire NBT here. If you have a complex // tile entity that doesn't need to have all information on the client you can write // a more optimal NBT here. NBTTagCompound nbtTag = new NBTTagCompound(); this.writeToNBT(nbtTag); return new SPacketUpdateTileEntity(getPos(), 1, nbtTag); } @Override public void readFromNBT(NBTTagCompound compound) { super.readFromNBT(compound); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { super.writeToNBT(compound); return compound; } @Override public void update() { BlockPos blockpos = this.getPos(); Block block = this.getBlockType(); if(block instanceof BlockSpaceHeater){ this.world.scheduleBlockUpdate(blockpos, block, 5, 1);//Makes the actual block tick } } } PacketInt Class (w/ Handler): Reveal hidden contents package its_meow.spaceheater.network.packets; import io.netty.buffer.ByteBuf; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class PacketInt implements IMessage { private int theInt; public PacketInt() {} public PacketInt(int theInt){ this.theInt = theInt; } @Override public void fromBytes(ByteBuf buf) { this.theInt = buf.readInt(); } @Override public void toBytes(ByteBuf buf) { buf.writeInt(this.theInt); } public static class Handler implements IMessageHandler<PacketInt, IMessage> { @Override public IMessage onMessage(PacketInt message, MessageContext ctx) { System.out.println("printed packet: " + message.theInt); //This is where I want to write the the specific instance's NBT, but I don't have access to that instance here, how would I get it here? Could I make like a PacketIntTileEntity that sends both? but ByteBuf doesn't have a tileentity type thing. I'm new to packets and all this serverside stuff, I'm used to making mobs and items... I've never made a tile entity, GUI, or advanced block like this one I'm making. return null; } } } I have no clue what I want answered but.. SOMETHING? I'm desperate lol Edited April 5, 2017 by its_meow Version for title Quote
its_meow Posted April 5, 2017 Author Posted April 5, 2017 Reveal hidden contents On 4/5/2017 at 4:49 PM, diesieben07 said: Don't extend BlockContainer. Override hasTileEntity and createTileEntity. You cannot reference client-only classes such as Minecraft in common code. You must not call setLightLevel after the block was registered. If you need a dynamic light value, override getLightValue(IBlockState, IBlockAccess, BlockPos). The code you have in breakBlock is not needed. Why is your packet called PacketInt? @Override public void update() { BlockPos blockpos = this.getPos(); Block block = this.getBlockType(); if(block instanceof BlockSpaceHeater){ this.world.scheduleBlockUpdate(blockpos, block, 5, 1);//Makes the actual block tick } } This is a terrible idea. Why are you doing this? As for the question in the packet handler comment: You need to track which TileEntity the player is looking at on the server, the easiest way is to use Container and GuiContainer with IGuiHandler, as if you wanted to display an inventory. Then the server can track which TE the player is looking at via the Container. Expand 1. So the other thing I can do is make it implement ITileEntityProvider, and Override hasTileEntity and return true? 2. It's no longer common code when I do the if !isRemote 3. I don't understand 4. Okay, removed 5. I dunno, it's an int, isn't it? 6. I don't know how I would make the light value set from the tile entity other than that, is there a better way? And where would I use Container and GuiContainer with IGuiHandler? Also, I'm sorry for being a clueless, horrible programmer. This entire area makes no sense to me, I'm doing a mod request because I needed something to do, so... I don't know. Quote
Jay Avery Posted April 5, 2017 Posted April 5, 2017 On 4/5/2017 at 5:02 PM, its_meow said: Reveal hidden contents 1. So the other thing I can do is make it implement ITileEntityProvider, and Override hasTileEntity and return true? Expand You don't need to implement ITileEntityProvider, those methods are in Block so you just need to override them. 6 minutes ago, its_meow said: 2. It's no longer common code when I do the if !isRemote Expand Actually it is. Minecraft is a client-only class, which means it only exists on the client. Even if it's only referenced inside an if-statement, it will cause a crash on the server because the code contains a reference to something that doesn't exist at all. 6 minutes ago, its_meow said: 6. I don't know how I would make the light value set from the tile entity other than that, is there a better way? Expand Override the method getLightValue(IBlockState, IBlockAccess, BlockPos). In there, get the TileEntity and get the light level from it, then return that value. No need for block updates, you just need your TE to store its current light level. 6 minutes ago, its_meow said: And where would I use Container and GuiContainer with IGuiHandler? Expand Container is for server-side, GUI is for client-side. 6 minutes ago, its_meow said: Also, I'm sorry for being a clueless, horrible programmer. This entire area makes no sense to me, I'm doing a mod request because I needed something to do, so... I don't know. Expand That seems like kind of an unhealthy justification for this? If you don't enjoy it then just... go for a walk or something instead. It's supposed to be fun y'know? Quote
its_meow Posted April 5, 2017 Author Posted April 5, 2017 On 4/5/2017 at 5:12 PM, Jay Avery said: You don't need to implement ITileEntityProvider, those methods are in Block so you just need to override them. Actually it is. Minecraft is a client-only class, which means it only exists on the client. Even if it's only referenced inside an if-statement, it will cause a crash on the server because the code contains a reference to something that doesn't exist at all. Override the method getLightValue(IBlockState, IBlockAccess, BlockPos). In there, get the TileEntity and get the light level from it, then return that value. No need for block updates, you just need your TE to store its current light level. Container is for server-side, GUI is for client-side. That seems like kind of an unhealthy justification for this? If you don't enjoy it then just... go for a walk or something instead. It's supposed to be fun y'know? Expand 1. Okay, I figured it out. I was confusing createNewTileEntity with createTileEnity. 2. Then how would I open the GUI? 3. so if I override it, what would the return statement be? would I leave it as super(state, world pos) or make a variable in the tile entity and return that? 4. So I made GUIHeater extend GuiContainer and implement IGuiHandler and it made me add a bunch of methods including drawGuiContainerBackgroundLayer, getServerGuiElement, and getClientGuiElement. Is there something I'm supposed to do with these? I also don't know where to put Container 5. I very much am enjoying this, it just gets frusturating at times when it won't do what you want. GRRR. I'm having fun though Quote
stucuk Posted April 5, 2017 Posted April 5, 2017 The following is the packet code i use. Note that i have only tested on 1.10.2 but its likely to work with 1.11. Also note its slightly modified to work outside of my mod. You shouldn't need an int for what you want to do, short should work. The Packet Manager thingy, basically the same as SimpleNetworkWrapper except you don't need to specify packet id numbers. Replace "YOURMODSNAME" with a unique name: package stucuk.square.packets; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.relauncher.Side; public class MCPacketSystem { private int count = 0; private SimpleNetworkWrapper INSTANCE = new MCPacketSystem("YOURMODSNAME"); public MCPacketSystem(String name) { INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(name); } public <REQ extends IMessage, REPLY extends IMessage> void registerPacket(Class<? extends IMessageHandler<REQ, REPLY>> messageHandler, Class<REQ> requestMessageType, Side side) { INSTANCE.registerMessage(messageHandler, requestMessageType, count, side); count++; } public SimpleNetworkWrapper instance() { return INSTANCE; } public void inc() { count++; } } Basic Packet Class (Its used as a base for the actual packets): package stucuk.square.packets; import io.netty.buffer.ByteBuf; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraftforge.fml.client.FMLClientHandler; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class MCBasicPacket implements IMessage { public void handlePacket(EntityPlayer player, Side side) { // } @Override public void fromBytes(ByteBuf buffer) { // } @Override public void toBytes(ByteBuf buffer) { // } @SideOnly(Side.CLIENT) public void hpc(MessageContext ctx) { handlePacket(FMLClientHandler.instance().getClient().thePlayer,ctx.side); } public void onMessage(MessageContext ctx) { switch (ctx.side) { case CLIENT: hpc(ctx); break; case SERVER: handlePacket(ctx.getServerHandler().playerEntity,ctx.side); break; default: } } public static void sendToServer(IMessage packet) { MCPacketSystem.instance().sendToServer(packet); } public static void sendToPlayer(IMessage packet, EntityPlayerMP player) { MCPacketSystem.instance().sendTo(packet, player); } } The actual packet class: package stucuk.square.packets; import java.io.IOException; import stucuk.square.interfaces.IGUIPacketHandler; import io.netty.buffer.ByteBuf; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; 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 net.minecraftforge.fml.relauncher.Side; public class PacketGUI_ClientToServer extends MCBasicPacket implements IMessage, IMessageHandler<PacketGUI_ClientToServer, IMessage> { private int x,y,z; private short value; private long value64; private float valueF; private ItemStack valueStack; private byte extra; private byte datatype; @Override public IMessage onMessage(PacketGUI_ClientToServer message, MessageContext ctx) { message.onMessage(ctx); return null; } public PacketGUI_ClientToServer(){ } public PacketGUI_ClientToServer(int x, int y, int z, short value, byte extra){ this.x = x; this.y = y; this.z = z; this.value = value; this.extra = extra; this.datatype = 0; } public PacketGUI_ClientToServer(int x, int y, int z, long value64, byte extra){ this.x = x; this.y = y; this.z = z; this.value64 = value64; this.extra = extra; this.datatype = 1; } public PacketGUI_ClientToServer(int x, int y, int z, float valueF, byte extra){ this.x = x; this.y = y; this.z = z; this.valueF = valueF; this.extra = extra; this.datatype = 2; } public PacketGUI_ClientToServer(int x, int y, int z, ItemStack valueStack, byte extra){ this.x = x; this.y = y; this.z = z; this.valueStack = valueStack; this.extra = extra; this.datatype = 3; } @Override public void toBytes(ByteBuf buffer) { buffer.writeInt(x); buffer.writeInt(y); buffer.writeInt(z); buffer.writeByte(extra); buffer.writeByte(datatype); if (this.datatype == 0) buffer.writeShort(value); else if (this.datatype == 1) buffer.writeLong(value64); else if (this.datatype == 2) buffer.writeFloat(valueF); else if (this.datatype == 3) { PacketBuffer pb = new PacketBuffer(buffer); pb.writeItemStackToBuffer(valueStack); } } @Override public void fromBytes(ByteBuf buffer) { x = buffer.readInt(); y = buffer.readInt(); z = buffer.readInt(); extra = buffer.readByte(); datatype = buffer.readByte(); if (datatype == 0) value = buffer.readShort(); else if (datatype == 1) value64 = buffer.readLong(); else if (datatype == 2) valueF = buffer.readFloat(); else if (datatype == 3) { PacketBuffer pb = new PacketBuffer(buffer); try { valueStack = pb.readItemStackFromBuffer(); } catch (IOException e) { e.printStackTrace(); } } } public void blockHandlePacket(TileEntity te, EntityPlayer player, BlockPos pos, long value, byte extra) { ((IGUIPacketHandler)te).HandleGUIPacket(player,pos,value,extra); } public void blockHandlePacket(TileEntity te, EntityPlayer player, BlockPos pos, float value, byte extra) { ((IGUIPacketHandler)te).HandleGUIPacket_Float(player,pos,value,extra); } public void blockHandlePacket(TileEntity te, EntityPlayer player, BlockPos pos, ItemStack value, byte extra) { ((IGUIPacketHandler)te).HandleGUIPacket_ItemStack(player,pos,value,extra); } @Override public void handlePacket(EntityPlayer player, Side side) { BlockPos pos = new BlockPos(x,y,z); TileEntity te = player.worldObj.getTileEntity(pos); if (!(te instanceof IGUIPacketHandler)) return; switch (this.datatype) { case (0): blockHandlePacket(te, player, pos, value, extra); break; case (1): blockHandlePacket(te, player, pos, value64, extra); break; case (2): blockHandlePacket(te, player, pos, valueF, extra); break; case (3): blockHandlePacket(te, player, pos, valueStack, extra); break; } } public static void sendShort(int x, int y, int z, short value, byte extra) { sendToServer(new PacketGUI_ClientToServer(x,y,z,value,extra)); } public static void sendShort(int x, int y, int z, short value) { sendShort(x,y,z,value,(byte)0); } public static void sendLong(int x, int y, int z, long value, byte extra) { sendToServer(new PacketGUI_ClientToServer(x,y,z,value,extra)); } public static void sendLong(int x, int y, int z, long value) { sendLong(x,y,z,value,(byte)0); } public static void sendFloat(int x, int y, int z, float value, byte extra) { sendToServer(new PacketGUI_ClientToServer(x,y,z,value,extra)); } public static void sendFloat(int x, int y, int z, float value) { sendFloat(x,y,z,value,(byte)0); } public static void sendItemStack(int x, int y, int z, ItemStack value, byte extra) { sendToServer(new PacketGUI_ClientToServer(x,y,z,value,extra)); } public static void sendItemStack(int x, int y, int z, ItemStack value) { sendItemStack(x,y,z,value,(byte)0); } } The IGUIPacketHandler needs to be implemented in the TileEntity: package stucuk.square.interfaces; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; public interface IGUIPacketHandler { public void HandleGUIPacket(EntityPlayer player, BlockPos pos, long value, byte extra); public void HandleGUIPacket_Float(EntityPlayer player, BlockPos pos, float value, byte extra); public void HandleGUIPacket_ItemStack(EntityPlayer player, BlockPos pos, ItemStack value, byte extra); } Example code for TileEntity: public class BaseTileRedstone extends BaseTile implements IGUIPacketHandler { @Override public void HandleGUIPacket(EntityPlayer player, BlockPos pos, long value, byte extra) { //Do Something! Short and Long values go here! } @Override public void HandleGUIPacket_Float(EntityPlayer player, BlockPos pos, float value, byte extra) { } @Override public void HandleGUIPacket_ItemStack(EntityPlayer player, BlockPos pos, ItemStack value, byte extra) { } } Registering packets: MCPacketSystem.instance().registerPacket(PacketGUI_ClientToServer.class, PacketGUI_ClientToServer.class, Side.SERVER); Usage in a GUIContainer (x,y,z needs to be the coordinates of the TileEntity): PacketGUI_ClientToServer.sendShort(x, y, z, value, extra); note that the extra value doesn't need to be passed (defaults to 0), its basically an id which is useful if you need to send more than 1 value to a TileEntity as you can identify what each number sent is for. Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
stucuk Posted April 5, 2017 Posted April 5, 2017 On 4/5/2017 at 5:40 PM, diesieben07 said: @stucuk Sorry, but I am not sure how your post is supposed to be helpful. Just presenting a solution (and a not-great one at that) and saying "here use this" is not very useful in my opinion. If you want I will elaborate as to why your solution is not great. Expand People can learn from others code. I know from experience looking at actual code rather than being told the name of certain things is alot easier to understand when you can see the "Big Picture". Everything i posted is self contained clean code. Who wouldn't want to know why their solution isn't good? Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
stucuk Posted April 5, 2017 Posted April 5, 2017 (edited) On 4/5/2017 at 5:53 PM, diesieben07 said: True. But without explanation using someone else's code very quickly turns into cargo-culting. Exactly. And that is why it invites people who are new to just copy-paste it and run with it. The aforementioned cargo-culting. Expand I don't think any of what i posted really needed an explanation, everything uses descriptive function/variable names which should mean self-explanatory code(People can always ask questions if they don't understand something). Cargo-cutting behaviour happens because people are impatient or lazy which will also happen when you tell them about a tutorial, which they will ignore all the descriptive text and go to the code at the bottom of it. So its a catch 22. On 4/5/2017 at 5:53 PM, diesieben07 said: Your packet is trying to be "universal", but this leads to very clunky code. You should have one packet dedicated to each purpose, don't try to make a "one size fits all" packet, we have packet types for a reason. Expand I don't see how its bad to group it into a single packet when its just related to a single task. Overall the code is smaller with less duplication than a single packet for each. You would never want a single packet for everything but optimising code is generally a good idea when its applicable to the situation. P.S I won't post further about this as this post is technically off topic and i don't want to derail further (This is a notification of intent rather than a "Please don't post after me"). Edited April 5, 2017 by stucuk Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 5, 2017 Author Posted April 5, 2017 Okay everyone. I've managed to get my problems down to two singular problems. First: How do i get the BlockPos or specific tile entity instance into the GUI class? Second: how does EntityPlayer::openGui work? also, double semicolons don't seem to work, so I have the statement as playerIn.openGui(SpaceHeaterMod.mod, ? what do i do with this "guiID", worldIn, pos.getX(), pos.getY(), pos.getZ()); how do i get a guiID? it says in the comment that it uses Forge's IGuiHandler system. Where can I apply an ID to my GUI? Or have I got the entirely wrong thing? Quote
loordgek Posted April 5, 2017 Posted April 5, 2017 (edited) the IGuiHander IMPL https://github.com/loordgek/Extragenarators/blob/trytofix/src/main/java/loordgek/extragenarators/GuiHander.java#L42 the guiID is used for opening the correct gui see ^ the EntityPlayer::openGui https://github.com/loordgek/Extragenarators/blob/trytofix/src/main/java/loordgek/extragenarators/blocks/BlockGenBase.java#L75 and the gui https://github.com/loordgek/Extragenarators/blob/trytofix/src/main/java/loordgek/extragenarators/client/gui/GuiFurnaceGen.java#L11 does this help you ? Edited April 5, 2017 by loordgek Quote
stucuk Posted April 5, 2017 Posted April 5, 2017 (edited) On 4/5/2017 at 9:32 PM, its_meow said: how do i get a guiID? Expand You make it up. Each Mod handles its own guiID's, which is why you provide the mods instance. Your IGuiHandler basically selects the appropriate Container/GUIContainer based on the guiID you specified. If it makes it any easier you could think of loordgek's code with numbers instead of enums: public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { TileEntity tile = world.getTileEntity(new BlockPos(x, y, z)); // Get the Tile Entity! switch (ID) { //Which GUI do we want? case 0: return new ContainerUpgrade(player, (TileGenBase) tile); //We want GUI 0 case 1: return new ContainerFurnaceGen(player, (TileFurnaceGen) tile); //We want GUI 1 } return null; // ID was invalid... return null. } If you wanted the FurnaceGen GUI you would do: playerIn.openGui(SpaceHeaterMod.mod, 1 , worldIn, pos.getX(), pos.getY(), pos.getZ()); Since your passing the TileEntity to the container, you can use it to get the X/Y/Z coordinates when sending packets from the client to the server. Loordgek's GuiFurnaceGen stores the passed TileEntity in its self. Edited April 5, 2017 by stucuk Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 6, 2017 Author Posted April 6, 2017 (edited) Okay. New main problem. The code works, up until the GuiHandler tries to define the tileEntity. It picks up the x y z, turns it into a blockpos, and runs world.getTileEntity(blockpos); the problem is, by printing that, I see that it returns NULL.. It makes NO sense. I'm sure it has the right coordinates and blockpos, they both print and I check the coord and it's exactly where my block is, but it won't find it. EDIT: I now notice this may have something to do with the fact that the client is executing this. But, HOW is the server supposed to execute a GUI? I'm lost. Edited April 6, 2017 by its_meow Quote
stucuk Posted April 6, 2017 Posted April 6, 2017 Are you sure the tile entity is actually being created? If there is no TileEntity being created it will return null when you try and get it. The onBlockActivated is called on both client and server, though as diesieben07 sais you want to call it on the server side. public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, @Nullable ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) { if(!world.isRemote) player.openGui(SpaceHeaterMod.mod, 1 , world, pos.getX(), pos.getY(), pos.getZ()); return true; } If we look at a trimmed down IGuiHandler you can see it specifies a bit for server and client. Forge does all the work at deciding which is called. You just tell it what to open and it then calls getServerGuiElement or getClientElement when needed: public class GuiHander implements IGuiHandler { @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; // We return a Server GUI Here (one that extends Container) } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; // We return a Client GUI Here (one that extends GUIContainer) } } Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 6, 2017 Author Posted April 6, 2017 (edited) I Figured it out. deisie, my block has to extend BlockContainer, those methods weren't making the tileEntity for some reason EDIT: I also know each GUI and GUI value are unique now because when it prints the tilentity it has an @ (randomid) I just need to adjust some math in my GUI and it should be almost ready I may have just one more issue though if the light value isn't working right Edited April 6, 2017 by its_meow Quote
its_meow Posted April 6, 2017 Author Posted April 6, 2017 On 4/6/2017 at 6:59 PM, diesieben07 said: Then you are doing something wrong. BlockContainer is old and legacy. Expand Well then how do I get it to create a tileEntity? because those overidden methods aren't doing anything. Quote
stucuk Posted April 6, 2017 Posted April 6, 2017 (edited) im guessing that the following is still the way to do things: public class SomeClassName extends Block implements ITileEntityProvider { @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new SomeTileEntityClass(someparameters); } } Edited April 6, 2017 by stucuk Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 6, 2017 Author Posted April 6, 2017 (edited) On 4/6/2017 at 8:39 PM, stucuk said: im guessing that the following is still the way to do things: public class SomeClassName extends Block implements ITileEntityProvider { @Override public TileEntity createNewTileEntity(World worldIn, int meta) { return new SomeTileEntityClass(someparameters); } } Expand Yeah. Also, I have a similar thing to your packet system, but do I have to register IGuiPacketHandler somewhere? because the packet isn't being recieved by the handler in the tileenity EDIT: Okay, it is registered in the Packet file, which is registered as the Handler in the manager, but it's not working... hm Edited April 6, 2017 by its_meow Quote
its_meow Posted April 6, 2017 Author Posted April 6, 2017 On 4/6/2017 at 8:47 PM, diesieben07 said: No, it is not. Do not implement ITileEntityProvider. Override hasTileEntity and createTileEntity. Expand I had it like that, and the tile entity was just null. It looked like this : @Override public boolean hasTileEntity() { return true; } @Override public TileEntity createTileEntity(World world, IBlockState state) { return new TileEntitySpaceHeater(); } Quote
its_meow Posted April 6, 2017 Author Posted April 6, 2017 (edited) On 4/6/2017 at 8:56 PM, diesieben07 said: So you completely ignored the deprecation warning on hasTileEntity(). Good for you, don't expect things to work then. Seriously, why do people just not pay attention? There is a giant fucking line through it, does that scream "Please use me, this is the method you want!" to you? Or what? Seriously, I am trying to figure this out. Yup, checks out. This looks totally fine and totally not like it could cause problems. Expand That's what it looks like in my block. you're the one that told me to override it? Edited April 6, 2017 by its_meow Quote
stucuk Posted April 6, 2017 Posted April 6, 2017 On 4/6/2017 at 8:41 PM, its_meow said: Yeah. Also, I have a similar thing to your packet system, but do I have to register IGuiPacketHandler somewhere? because the packet isn't being recieved by the handler in the tileenity Expand Assuming you have the same basic code as i posted for my packets handlepacket bit, In your TileEntity you need to implement it in the implements bit. I.E: public class BaseTileRedstone extends BaseTile implements IGUIPacketHandler { @Override public void HandleGUIPacket(EntityPlayer player, BlockPos pos, long value, byte extra) { //Do Something! Short and Long values go here! } @Override public void HandleGUIPacket_Float(EntityPlayer player, BlockPos pos, float value, byte extra) { } @Override public void HandleGUIPacket_ItemStack(EntityPlayer player, BlockPos pos, ItemStack value, byte extra) { } } Interfaces which the IGUIPacketHandler is, basically lay out stuff a thing should have. When you use the implements bit your stating what interfaces that class supports (Well implements). You can then treat that class as if it was that interface. Basically it allows you to do: TileEntity te = new MyTileEntity(); if (te instanceof IGUIPacketHandler) //Check its actually implemented the interface { ((IGUIPacketHandler)te).HandleGUIPacket(player,pos,1,0); //we can now treat the TileEntity as if it was a IGUIPacketHandler } Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 6, 2017 Author Posted April 6, 2017 (edited) On 4/6/2017 at 9:01 PM, diesieben07 said: Yes, I told you to override hasTileEntity. But that assumed that you apply some common sense and choose the obviously right one, the one that does not have a giant "do not use me" line through it: Expand I don't have a thing that tells me which one to choose when I override, I just have to type it in, so I had no idea EDIT: Plus, eclipse override/implement method doesn't tell you if it's deprecated. At all. Edited April 6, 2017 by its_meow Quote
stucuk Posted April 6, 2017 Posted April 6, 2017 In the guys defensive i never even knew you could get the IDE to generate an override method using the AutoComplete feature. Iv been playing with it since 2014 (And other languages for alot longer). Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
its_meow Posted April 6, 2017 Author Posted April 6, 2017 On 4/6/2017 at 9:07 PM, stucuk said: In the guys defensive i never even knew you could get the IDE to generate an override method using the AutoComplete feature. Iv been playing with it since 2014 (And other languages for alot longer). Expand You have to go in eclipse keybinds and search for Override/Implement and set a shortcut. IDEA i think already has it as a shortcut. Quote
Draco18s Posted April 6, 2017 Posted April 6, 2017 On 4/6/2017 at 9:04 PM, diesieben07 said: Or at least look at the parent class Expand Quite. Quote 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.
stucuk Posted April 6, 2017 Posted April 6, 2017 On 4/6/2017 at 9:08 PM, its_meow said: You have to go in eclipse keybinds and search for Override/Implement and set a shortcut. IDEA i think already has it as a shortcut. Expand I use eclipse and never have touched the keybindings. By Autocomplete i mean the CTRL+SPACE thing. I just didn't know you could do it for actual method overrides. Quote -Stu MCI Craft (Curse) | MCI Craft (Website)
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.