Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Tekner

Members
  • Joined

  • Last visited

Everything posted by Tekner

  1. Try using GameRegistry.findBlock(string modId, String name); You can then just access its blockId through that.
  2. Depending on what your tile entities do, you may need to employ custom packets, but since I'm assuming your single-player tests have worked out fine, you probably don't. If your blocks that use tile entities become desynced between the client and server, you'll need to implement a packet handler and sync data that way. The only real things that need @SideOnly(Side.CLIENT) are GUIs and KeyHandlers. There are probably a couple other things too, but I haven't come across them yet. It's unlikely that you need to worry about it based on what you said, though. If you start up a server and it says that it can't find a class, but it works fine in single-player, you probably need to use SideOnly(SIDE.CLIENT) on that class.
  3. Depending on what your tile entities do, you may need to employ custom packets, but since I'm assuming your single-player tests have worked out fine, you probably don't. If your blocks that use tile entities become desynced between the client and server, you'll need to implement a packet handler and sync data that way. The only real things that need @SideOnly(Side.CLIENT) are GUIs and KeyHandlers. There are probably a couple other things too, but I haven't come across them yet. It's unlikely that you need to worry about it based on what you said, though. If you start up a server and it says that it can't find a class, but it works fine in single-player, you probably need to use SideOnly(SIDE.CLIENT) on that class.
  4. Right. I'm assuming this isn't the case, though, since he would have figured out that he needs to do this in a singleplayer test as well, unless he has residual bugs that he doesn't even know about .
  5. Right. I'm assuming this isn't the case, though, since he would have figured out that he needs to do this in a singleplayer test as well, unless he has residual bugs that he doesn't even know about .
  6. All he has to do is have his block implement ITileEntityProvider That's one of the two purposes of it.
  7. All he has to do is have his block implement ITileEntityProvider That's one of the two purposes of it.
  8. I second this. Technically speaking, you can put the mod on your server and client and it should work (assuming you have correctly put all @SideOnly annotations as well to prevent the mod from referencing nonexistent classes.) If all your mod does is add simple blocks and items, it should work fine. In most cases, if your mod works in single player (since it actually runs an internal server), it'll work in multiplayer too. So if you want the question fully answered, you have to tell us what your mod does.
  9. I second this. Technically speaking, you can put the mod on your server and client and it should work (assuming you have correctly put all @SideOnly annotations as well to prevent the mod from referencing nonexistent classes.) If all your mod does is add simple blocks and items, it should work fine. In most cases, if your mod works in single player (since it actually runs an internal server), it'll work in multiplayer too. So if you want the question fully answered, you have to tell us what your mod does.
  10. It's the onBlockActivated method in the Block class that opens the gui, so yes if I understood what you said correctly. I knew I was forgetting something! I edited my post Look at the MainModClass definition again.
  11. It's the onBlockActivated method in the Block class that opens the gui, so yes if I understood what you said correctly. I knew I was forgetting something! I edited my post Look at the MainModClass definition again.
  12. I don't want to post entire class files, so I'll assume you know how to set up a basic block and tile entity. Ensure these methods are in your respective classes and tweak them from there. Block: //If you want your gui to have an inventory, have your block extend BlockContainer //If not, have it extend Block and implement ITileEntityProvider @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer playerEntity, int w, float px, float py, float pz) { //the second parameter (0) is the gui ID and is used in the gui handler //for it to know which gui window to use - use a different ID for each gui window playerEntity.openGui(MainModClass.instance, 0, world, x, y, z); return false; } public TileEntity createNewTileEntity(World world) { return new TileEntityClass (); } GuiHandler: public class GuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { //I don't use any containers in my GUIs (GuiContainer), but if I did, I'd return them here. //You can only get away with what I'm doing here if your GUIs extend GuiScreen and not GuiContainer //Servers get containers - Clients get GUIs return null; } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(ID) { case 0: return new BlockGuiWindow(); //etc case 1: return new DialogGUI(); //etc case 2: return new QuestGUI(); //etc case 3: return new ShopGUI(); } return null; //It is common Java convention to "break;" a switch case, but because all my cases end in returns, I don't need to } } BlockGuiWindow: @SideOnly(Side.CLIENT) public class BlockGuiWindow extends GuiScreen //extend GuiContainer if you want your gui to have an inventory { final int xSizeOfTexture = 192 , ySizeOfTexture = 135 , white = Color.white.getRGB(); int posX , posY; //If you want your gui to change based on TileEntity values, reference the tile entity in the constructor //you must pass the tile entity using "return new BlockGuiWindow(world.getBlockTileEntity(x, y, z))" in the GuiHandler TileEntityClass te; public BlockGuiWindow(TileEntityClass te) { this.te = te; } public void initGui() { this.buttonList.clear(); posX = (this.width - xSizeOfTexture) / 2; posY = (this.height - ySizeOfTexture) / 2; this.buttonList.add(new GuiButton(0, posX + 4, posY + 4, 20, 20, "ButtonText")); /*Parameters: * button id used when checking what to do when a button is pressed * The X position of the button * The Y position of the button * The width * The height (keep this at 20 if you can) * The text to be displayed on the button*/ } public void actionPerformed(GuiButton button) { switch(button.id) { case 0: //Do button stuff break; } } @Override public void drawScreen(int x, int y, float f) { drawDefaultBackground(); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.renderEngine.bindTexture("path/to/the/background/texture"); int posX = (this.width - xSizeOfTexture) / 2; int posY = (this.height - ySizeOfTexture) / 2; drawTexturedModalRect(posX, posY, 0, 0, xSizeOfTexture, ySizeOfTexture); //This draws the background //Make sure your background texture is a multiple of 256x256. //The xSizeOfTexture and ySizeOfTexture assume that the texture is 256x256. so 128 and 128 always reference half of the texture. //Look in the Gui class to see what else you can do here (like rendering textures and strings) this.drawString(fontRenderer, "Text", posX + 20, posY + 31, white); //this is where the white variable we set up at the beginning is used super.drawScreen(x, y, f); /*Here is a trick: If you reset the texture after "super.drawScreen(x, y, f);" (this.mc.renderEngine.bindTexture("path/to/the/background/texture"), you can draw on top of everything, including buttons. Use this to texture buttons, if you don't want them to have text.*/ } MainModClass: @Instance //The @Instance goes with the following line, nothing else public static MainModClass instance = new MainModClass(); GameRegistry.registerTileEntity(TileEntityClass.class, "TileEntityName"); NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler()); Those are the major snippets of the code I use for my stuff (with the names changed.) I have specific needs and you'll need to change the code a bit to do what you want it to, mainly adding a Container class and referencing it in the GuiHandler if you need a GuiContainer. You also may want to change my parenthetical syntax. I'm a C# programmer and the java parenthetical syntax bugs me
  13. I don't want to post entire class files, so I'll assume you know how to set up a basic block and tile entity. Ensure these methods are in your respective classes and tweak them from there. Block: //If you want your gui to have an inventory, have your block extend BlockContainer //If not, have it extend Block and implement ITileEntityProvider @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer playerEntity, int w, float px, float py, float pz) { //the second parameter (0) is the gui ID and is used in the gui handler //for it to know which gui window to use - use a different ID for each gui window playerEntity.openGui(MainModClass.instance, 0, world, x, y, z); return false; } public TileEntity createNewTileEntity(World world) { return new TileEntityClass (); } GuiHandler: public class GuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { //I don't use any containers in my GUIs (GuiContainer), but if I did, I'd return them here. //You can only get away with what I'm doing here if your GUIs extend GuiScreen and not GuiContainer //Servers get containers - Clients get GUIs return null; } @Override public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { switch(ID) { case 0: return new BlockGuiWindow(); //etc case 1: return new DialogGUI(); //etc case 2: return new QuestGUI(); //etc case 3: return new ShopGUI(); } return null; //It is common Java convention to "break;" a switch case, but because all my cases end in returns, I don't need to } } BlockGuiWindow: @SideOnly(Side.CLIENT) public class BlockGuiWindow extends GuiScreen //extend GuiContainer if you want your gui to have an inventory { final int xSizeOfTexture = 192 , ySizeOfTexture = 135 , white = Color.white.getRGB(); int posX , posY; //If you want your gui to change based on TileEntity values, reference the tile entity in the constructor //you must pass the tile entity using "return new BlockGuiWindow(world.getBlockTileEntity(x, y, z))" in the GuiHandler TileEntityClass te; public BlockGuiWindow(TileEntityClass te) { this.te = te; } public void initGui() { this.buttonList.clear(); posX = (this.width - xSizeOfTexture) / 2; posY = (this.height - ySizeOfTexture) / 2; this.buttonList.add(new GuiButton(0, posX + 4, posY + 4, 20, 20, "ButtonText")); /*Parameters: * button id used when checking what to do when a button is pressed * The X position of the button * The Y position of the button * The width * The height (keep this at 20 if you can) * The text to be displayed on the button*/ } public void actionPerformed(GuiButton button) { switch(button.id) { case 0: //Do button stuff break; } } @Override public void drawScreen(int x, int y, float f) { drawDefaultBackground(); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.renderEngine.bindTexture("path/to/the/background/texture"); int posX = (this.width - xSizeOfTexture) / 2; int posY = (this.height - ySizeOfTexture) / 2; drawTexturedModalRect(posX, posY, 0, 0, xSizeOfTexture, ySizeOfTexture); //This draws the background //Make sure your background texture is a multiple of 256x256. //The xSizeOfTexture and ySizeOfTexture assume that the texture is 256x256. so 128 and 128 always reference half of the texture. //Look in the Gui class to see what else you can do here (like rendering textures and strings) this.drawString(fontRenderer, "Text", posX + 20, posY + 31, white); //this is where the white variable we set up at the beginning is used super.drawScreen(x, y, f); /*Here is a trick: If you reset the texture after "super.drawScreen(x, y, f);" (this.mc.renderEngine.bindTexture("path/to/the/background/texture"), you can draw on top of everything, including buttons. Use this to texture buttons, if you don't want them to have text.*/ } MainModClass: @Instance //The @Instance goes with the following line, nothing else public static MainModClass instance = new MainModClass(); GameRegistry.registerTileEntity(TileEntityClass.class, "TileEntityName"); NetworkRegistry.instance().registerGuiHandler(this, new GuiHandler()); Those are the major snippets of the code I use for my stuff (with the names changed.) I have specific needs and you'll need to change the code a bit to do what you want it to, mainly adding a Container class and referencing it in the GuiHandler if you need a GuiContainer. You also may want to change my parenthetical syntax. I'm a C# programmer and the java parenthetical syntax bugs me
  14. Here are some snippets from how I render one of my blocks. I'll eventually change it to use UVs, but right now it renders a gray block as a placeholder (that's why I'm wastefully creating six new color objects each render pass ): //Draw monolith renderPlane(x, y, z, 1, 1, Orientation.North, new Color(128, 128, 128)); renderPlane(x+1, y, z, 1, 1, Orientation.West, new Color(128, 128, 128)); renderPlane(x, y, z, 1, 1, Orientation.East, new Color(128, 128, 128)); renderPlane(x, y, z+1, 1, 1, Orientation.South, new Color(128, 128, 128)); renderPlane(x, y+1, z, 1, 1, Orientation.Up, new Color(128, 128, 128)); renderPlane(x, y, z, 1, 1, Orientation.Down, new Color(128, 128, 128)); renderPlane: private void renderPlane(double x, double y, double z, double width, double height, Orientation orientation, Color color) { tessellator.startDrawingQuads(); tessellator.setColorRGBA(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); switch(orientation) { case Up: tessellator.setNormal(0, -1.0f, 0); tessellator.addVertex(x, y, z); tessellator.addVertex(x, y, z+height); tessellator.addVertex(x+width, y, z+height); tessellator.addVertex(x+width, y, z); break; case Down: tessellator.setNormal(0, 1.0f, 0); tessellator.addVertex(x+width, y, z); tessellator.addVertex(x+width, y, z+height); tessellator.addVertex(x, y, z+height); tessellator.addVertex(x, y, z); break; case North: tessellator.setNormal(0, 0, -1.0f); tessellator.addVertex(x, y, z); tessellator.addVertex(x, y+height, z); tessellator.addVertex(x+width, y+height, z); tessellator.addVertex(x+width, y, z); break; case South: tessellator.setNormal(0, 0, 1.0f); tessellator.addVertex(x+width, y, z); tessellator.addVertex(x+width, y+height, z); tessellator.addVertex(x, y+height, z); tessellator.addVertex(x, y, z); break; case East: tessellator.setNormal(1.0f, 0, 0); tessellator.addVertex(x, y, z+width); tessellator.addVertex(x, y+height, z+width); tessellator.addVertex(x, y+height, z); tessellator.addVertex(x, y, z); break; case West: tessellator.setNormal(-1.0f, 0, 0); tessellator.addVertex(x, y, z); tessellator.addVertex(x, y+height, z); tessellator.addVertex(x, y+height, z+width); tessellator.addVertex(x, y, z+width); break; } tessellator.draw(); } I'm sure there are better ways to do it, as renderPlane and another method I wrote, renderDoublePlane, weren't actually written to render small cubes, but it shows you the normals and vertex ordering to get them to render in the right direction. Also, as you noticed, most of the planes are rendered from the Block's origin and are oriented from there, which may or may not confuse you. This is because renderPlane renders things in a positive direction. You can provide a negative width/height to flip the plane, but I have a feeling that'll also flip the orientation/normal.
  15. First off, there is a difference between asking how to program in Java, and not knowing enough to know if it's a Java issue or a Forge issue. Yes it is an essential part of Java that any Forge programmer ought to know, but he is also asking a valid question regardless of his aptitude for the language. Now, on to your question: Usually when you want to do something that is already done in the game, or another forge mod, the best thing to do is to look in the source code: if (!this.worldObj.isRemote) { Block.blocksList[par4].onBlockAdded(this.worldObj, j2, par2, k2); } if (Block.blocksList[par4] != null && Block.blocksList[par4].hasTileEntity(par5)) { tileentity = this.getChunkBlockTileEntity(par1, par2, par3); if (tileentity == null) { tileentity = Block.blocksList[par4].createTileEntity(this.worldObj, par5); this.worldObj.setBlockTileEntity(j2, par2, k2, tileentity); } if (tileentity != null) { tileentity.updateContainingBlockInfo(); tileentity.blockMetadata = par5; } } These are lines 765-785 in Chunk.java (net.minecraft.world.chunk) I'd suggest you use the code that this uses, seeing as how it obviously works. This means that you first check if the block you are adding has a tile entity with hasTileEntity(int metadata) Note that the metadata value doesn't actually matter unless it is overridden in the block. Once you've confirmed that the block has a tile entity, call TileEntity tileentity = blockToCopy.createTileEntity(worldObj, metadata); worldObj.setBlockTileEntity(x, y, z, tileentity); or worldObj.setBlockTileEntity(x, y, z, blockToCopy.createTileEntity(worldObj, metadata)); if you want to shorten it and don't need to reference the TileEntity again, which you will if you're going to copy nbt data as I'll show below. As for copying the NBT data out of the block and into a new one, add an NBTTagCompound variable (let's call it "nbt" for the following example) to ChainSettings for storage. When you copy the block, simply call copiedBlockTileEntity.writeToNBT(nbt) That will set your nbt data to be passed into the pasted block (assuming that the block has a tile entity. Make sure to check for this as well.) After you create your new block and ensure that a new TileEntity is in place, use the converse nbt storage method: pastedBlockTileEntity.readFromNBT(ChainSettings.nbt) Make sure to check if ChainSettings.nbt is null before doing this or you could run into problems. If it's null, then you don't have any data to copy and we can assume that the copied block doesn't have any nbt data (no tile entity.) Also make sure to clear ChainSettings.nbt by setting it to null after reading it, for safety. Please note that I haven't tested any of the above code, but it should work or give you good start to getting your wrenches working. If I helped you, please give me some karma
  16. There is already a tutorial for this and the full answer is too long to put in one post anyhow.
  17. I am requesting modder status. I am admittedly new to Forge and Bukkit as of a few weeks ago, but have been programming for about nine years and picked them both up very quickly. My current forge project is called LoECraft and is being designed for my new server (by the same name) that I'm working on. All of the info can be found on my website. Thus, I do not require a subforum for this project as I already have my own forum.
  18. Try using Ic2Recipes.addCraftingRecipe(ItemInterface.getItem(Item.canBiofuel), new Object[]{ "TT ","TTT","TTT, 'T', Items.getItem("matter") }); What I did was remove the "new ItemStack()". It makes no sense for any class to have its constructor just take an instance of that exact same class. If it needs an ItemStack, then just use the ItemInterface method that already provides one.

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.