Bugsy6 Posted May 9, 2013 Posted May 9, 2013 I'm trying to make a water pipe system that works like redstone. This is my first project, it has already helped me learn so much, but now I'm a bit stuck. I would like the Pipe block to change model depending on the blocks surrounding it. So if there is a block above the new block and to the right of the new block then it should place a corner pipe, or if there is a block above, below and to the side or both sides lay a junction type pipe block. I have made the corner model and it works in the game, I just can't get the logic to make it change block model. Here's the code I've written to try and do it. If more code is needed I can post more. public void getBlockMetadata(World world, int x, int y, int z) { int i = world.getBlockId(x + 1, y, z); int j = world.getBlockId(x, y, z - 1); int k = world.getBlockId(x, y, z + 1); int l = world.getBlockId(x - 1, y, z); if(j == this.blockID && i == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(i == this.blockID && k == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(k == this.blockID && l == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(l == this.blockID && j == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else { world.setBlock(x, y, z, SteamPower.LeadPipe.blockID); } } Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 if(...) corner pipe else if(...) corner pipe else if(...) corner pipe else if(...) corner pipe else if(...) corner pipe else if(...) corner pipe else if(...) corner pipe ... Gee. I wonder what's wrong with this picture. 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.
Bugsy6 Posted May 9, 2013 Author Posted May 9, 2013 With the risk of me not seeing how the previous post was the most helpful post ever could someone please elaborate. I'm staring at this if statement trying to see the issue. It always displays the straight pipe even though my if statement says if these to conditions are there then lay a different block ID. Quote
endershadow Posted May 9, 2013 Posted May 9, 2013 you should render it differently based on meta-data. Then the corner pipes can have a different model per meta-data. Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 With the risk of me not seeing how the previous post was the most helpful post ever could someone please elaborate. Your entire if-block results in corner pieces, with exception of the final else. Your code CANNOT generate anything else: if(j == this.blockID && i == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(i == this.blockID && k == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(k == this.blockID && l == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(l == this.blockID && j == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else { world.setBlock(x, y, z, SteamPower.LeadPipe.blockID); } 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.
Bugsy6 Posted May 9, 2013 Author Posted May 9, 2013 Ok, but I want it to find and generate corner pieces. At the moment all that is placed in the world is straight pieces, the code doesn't seem to change them to the corner pieces. It almost seems to either disregard the code or using setBlockId isn't the right function, maybe? Thanks for trying to help. Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 It almost seems to either disregard the code or using setBlockId isn't the right function, maybe? Let's see... public void getBlockMetadata(...) {...} Yeah, I'd say that's the wrong function. You should be using onPlaced or onAdded as well as onNeighborChanged. 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.
Bugsy6 Posted May 9, 2013 Author Posted May 9, 2013 Ok so I'm not having any luck with these addition, can't think what I need to add. I've been looking at the redstone block to try and use similar code it uses to change texture, but it doesn't seem to transfer across. I think it is because I'm using a full model as opposed to just a texture. Anymore guidance would be appreciated. public void onPlaced(World world, int x, int y, int z) { int i = world.getBlockId(x + 1, y, z); int j = world.getBlockId(x, y, z - 1); int k = world.getBlockId(x, y, z + 1); int l = world.getBlockId(x - 1, y, z); if(j == this.blockID && i == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(i == this.blockID && k == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(k == this.blockID && l == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else if(l == this.blockID && j == this.blockID) { world.setBlock(x, y, z, SteamPower.LeadPipeCorner.blockID); } else { world.setBlock(x, y, z, SteamPower.LeadPipe.blockID); } } /** * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z */ public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) { return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4); } public void onNeighborChanged(World par1World, int par2, int par3, int par4, int par5) { if (!par1World.isRemote) { boolean flag = this.canPlaceBlockAt(par1World, par2, par3, par4); if (flag) { } else { this.dropBlockAsItem(par1World, par2, par3, par4, 0, 0); par1World.setBlockToAir(par2, par3, par4); } super.onNeighborBlockChange(par1World, par2, par3, par4, par5); } } Quote
Bugsy6 Posted May 9, 2013 Author Posted May 9, 2013 Haven't had any luck with trying a few bits out. I've been pouring over the redstone block files and render files to try and see how it decides on what textures, but in the end ths wasn't that helpful as I want to use a different Block model all together. Any help on how to check surrounding blocks and then place the relevant block model would be appreciated. Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 BuildCraft is open source I believe. Look for it on Github. 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.
robustus Posted May 9, 2013 Posted May 9, 2013 The first step to do this is using metadata. I created a similar block, like a fence block, you need to check each block next to it set every scenario to a metadata, for example, I set up booleans representing north, south, east, west, up. Do a check on each spot, if there is a pipe north of the block set boolean to true, if not set it to false. Do this for all the directions and then you will have to set a metadata for each scenario. For example if(!south && !north && !east && !west) { set metdata to 0. that would mean the block has no surrounding pipes, then you would have to do each possible outcome as a metdata. If only pipe to the east, that would be one metadata, if pipe is to the east and west another seperate metata. Then in the TileEntityRender you get the blocks metadata and based on the metadata you render the proper model. Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 Fences actually don't use metadata The fence renderer checks neighboring blocks in the render function. 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.
robustus Posted May 9, 2013 Posted May 9, 2013 True it doesn't, but someone had once advised me that checking neighboring blocks in the render call is a drain on resources, but what do I know Quote
Bugsy6 Posted May 9, 2013 Author Posted May 9, 2013 Thanks a bunch Robustus for that I've started implementing that way of doing it, I will report my progress lol. Also thanks Draco for pointing me at Buildcraft source code that has been a huge help. Hopefully get this cracked after work! Quote
Draco18s Posted May 9, 2013 Posted May 9, 2013 True it doesn't, but someone had once advised me that checking neighboring blocks in the render call is a drain on resources, but what do I know It would be more intensive than if you used metadata. But if you can't use metadata (like redstone, because metadata is being used for other things, or for devices that have more than 16 configurations, like pipes) then it's not too bad. You'd actually be surprised, but the 3D render calls (the tessalator) aren't performed that often. 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.
Bugsy6 Posted May 10, 2013 Author Posted May 10, 2013 Ok, I've got myself stuck any guidance would be appreciated. So I added this in the renderer to get the meta data, though I don't think this is right lol. public TileEntityLeadPipeRenderer(World world, int x, int y, int z, Block block, int d) { this.blockMetadata = BlockLeadPipe.checkNeighbour(world, x, y, z, block, d); int i = world.getBlockMetadata(x, y, z); if(i == 0) { model = new ModelLeadPipe(); } else if(i == 1) { model1 = new ModelLeadPipeCorner(); } } Then I made this function in the block file to set block meta data, I think. public static boolean checkNeighbour(World world, int x, int y, int z, Block block, int d) { int g = world.getBlockId(x, y, z); int i = world.getBlockId(x, y, z - 1); int j = world.getBlockId(x + 1, y, z); int k = world.getBlockId(x, y, z + 1); int l = world.getBlockId(x-1, y, z); int m = world.getBlockId(x, y + 1, z); int n = world.getBlockId(x, y - 1, z); if(i == g) { world.setBlock(x, y, z, g, 0, 2); return true; } if(j == g) { world.setBlock(x, y, z, g, 0, 2); return true; } if(k == g) { world.setBlock(x, y, z, g, 0, 2); return true; } if(l == g) { world.setBlock(x, y, z, g, 0, 2); return true; } if(i == g && j == g) { world.setBlock(x, y, z, g, 1, 2); return true; } if(i == g && l == g) { world.setBlock(x, y, z, g, 1, 2); return true; } if(k == g && j == g) { world.setBlock(x, y, z, g, 1, 2); return true; } if(k == g && l == g) { world.setBlock(x, y, z, g, 1, 2); return true; } return false; } Quote
Bugsy6 Posted May 11, 2013 Author Posted May 11, 2013 Instead of trying to change the renderer to choose a certain model and texture depending on metadata, would it be easier to get the Block file to choose a different TileEntityRenderer depending on the meta data? Quote
Bugsy6 Posted May 11, 2013 Author Posted May 11, 2013 So in the Block file I now have this: public void checkNeighbour(World world, int x, int y, int z, Block block, int d) { int g = world.getBlockId(x, y, z); int i = world.getBlockId(x, y, z - 1); int j = world.getBlockId(x + 1, y, z); int k = world.getBlockId(x, y, z + 1); int l = world.getBlockId(x-1, y, z); int m = world.getBlockId(x, y + 1, z); int n = world.getBlockId(x, y - 1, z); if(i == g) { world.setBlockMetadata(x, y, z, 0); } if(j == g) { world.setBlockMetadata(x, y, z, 0); } if(k == g) { world.setBlockMetadata(x, y, z, 0); } if(l == g) { world.setBlockMetadata(x, y, z, 0); } if(i == g && j == g) { world.setBlockMetadata(x, y, z, 1); } if(i == g && l == g) { world.setBlockMetadata(x, y, z, 1); } if(k == g && j == g) { world.setBlockMetadata(x, y, z, 1); } if(k == g && l == g) { world.setBlockMetadata(x, y, z, 1); } } Then instead of using the creatTileentity method I put this inside the onBlockAdded: int i = par1World.getBlockMetadata(par2, par3, par4); if(i == 0) { par1World.setBlockTileEntity(par2, par3, par4, new TileEntityLeadPipe()); } else if(i == 1) { par1World.setBlockTileEntity(par2, par3, par4, new TileEntityLeadPipeCorner()); } Though now when I go into the game the block still places (I can see the bounding lines around the cube), but there is no model rendered. So it doesn't seem to be picking a tileentity in my if statement. Help I'm lost lol. Edit: So my issue (after using the system.out) seems to be in the createTileEntity method. I'm not sure how to pass the metadata into that method so I can then do an if statement to choose which rendering to use depending on the metadata. Thanks for any help. Quote
Bugsy6 Posted May 13, 2013 Author Posted May 13, 2013 Ok so I have got the onBlockAdded function to send the metadata of the newly placed block to the create TileEntity class, but now the block isn't rendering. It has the correct metadata and seems to be receiving it correctly, I've checked by using System outs, here's the code: @Override public TileEntity createTileEntity(World world, int metadata) { System.out.println(metadata); if(metadata == 0) { return new TileEntityLeadPipe(); } else if(metadata == 1) { return new TileEntityLeadPipeCorner(); } return null; } The problem seems to be that the renderer isn't running through, if I put a system out in the renderer nothing prints to the console, I'm just left with invisible blocks. Here's the renderer: package SteamPower.Blocks; import org.lwjgl.opengl.GL11; import SteamPower.Models.ModelLeadPipe; import SteamPower.Models.ModelLeadPipeCorner; import net.minecraft.block.Block; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class TileEntityLeadPipeRenderer extends TileEntitySpecialRenderer { public TileEntityLeadPipeRenderer() { model = new ModelLeadPipe(); } public void renderAModelAt(TileEntityLeadPipe tile, double d, double d1, double d2, float f) { int rotation = 0; if(tile.worldObj != null) { System.out.println("hello"); rotation = tile.getBlockMetadata(); } bindTextureByName("/textures/models/ModelLeadPipe.png"); GL11.glPushMatrix(); GL11.glTranslatef((float)d + 0.5F, (float)d1 + 1.5F, (float)d2 + 0.5F); GL11.glScalef(1.0F, -1F, -1F); GL11.glRotatef(rotation*90, 0.0F, 1.0F, 0.0F); model.renderAll(); GL11.glPopMatrix(); //end } private ModelLeadPipe model; @Override public void renderTileEntityAt(TileEntity tileentity, double d0, double d1, double d2, float f) { this.renderAModelAt((TileEntityLeadPipe)tileentity, d0, d1, d2, f); } } Quote
Bugsy6 Posted May 13, 2013 Author Posted May 13, 2013 So I think it is to do with the getRenderType function. I guess it isn't changing the render type to match the correct renderer. I'm trying to work on this next. Quote
Bugsy6 Posted May 20, 2013 Author Posted May 20, 2013 Ok so I had a little break did some other bits and now I'm back to being lost on this again. I want to place a block and have it render the correct model depending on its surrounding blocks. Here is my onBlockPlacedBy code which sets the blocks metadata depending on its surroundings: int g = par1World.getBlockId(par2, par3, par4); int i = par1World.getBlockId(par2, par3, par4 - 1); int j = par1World.getBlockId(par2 + 1, par3, par4); int k = par1World.getBlockId(par2, par3, par4 + 1); int l = par1World.getBlockId(par2-1, par3, par4); int m = par1World.getBlockId(par2, par3 + 1, par4); int n = par1World.getBlockId(par2, par3 - 1, par4); if(i == g && j != g && k != g && l != g) { int o = 0; par1World.setBlockMetadata(par2, par3, par4, o); this.createTileEntity(par1World, o); } if(j == g && i != g && k != g && l != g) { int o = 0; par1World.setBlockMetadata(par2, par3, par4, 0); this.createTileEntity(par1World, o); } if(k == g && j != g && i != g && l != g) { int o = 0; par1World.setBlockMetadata(par2, par3, par4, 0); this.createTileEntity(par1World, o); } if(l == g && j != g && k != g && i != g) { int o = 0; par1World.setBlockMetadata(par2, par3, par4, 0); this.createTileEntity(par1World, o); } if(i == g && j == g) { int o = 1; par1World.setBlockMetadata(par2, par3, par4, 1); this.createTileEntity(par1World, o); } if(i == g && l == g) { int o = 1; par1World.setBlockMetadata(par2, par3, par4, 1); this.createTileEntity(par1World, o); } if(k == g && j == g) { int o = 1; par1World.setBlockMetadata(par2, par3, par4, 1); this.createTileEntity(par1World, o); } if(k == g && l == g) { int o = 1; par1World.setBlockMetadata(par2, par3, par4, 1); this.createTileEntity(par1World, o); } Then I have this code to set the TileEntity: @Override public TileEntity createTileEntity(World world, int metadata) { if(metadata == 0) { renderID = -1; return new TileEntityLeadPipe(); } else if(metadata == 1) { renderID = -2; return new TileEntityLeadPipeCorner(); } return null; } It also sets the variable renderID which is then called in the getRenderType function: @Override public int getRenderType() { System.out.println(renderID); return renderID; } Though the block doesn't render at all just the block bounds lines, so any ideas what I'm missing here. Thanks. Quote
Draco18s Posted May 20, 2013 Posted May 20, 2013 @Override public int getRenderType() { System.out.println(renderID); return renderID; } And that variable is equal to..? 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.
Bugsy6 Posted May 20, 2013 Author Posted May 20, 2013 Ok the good news is that I've got the blocks to render and I have got them to partial change depending on their surrounding blocks. Though they aren't changing as I want them to, of course lol. So I changed the code when the block is added to simply set a value to a variable: int g = SteamPower.LeadPipe.blockID; int i = par1World.getBlockId(par2, par3, par4 - 1); int j = par1World.getBlockId(par2 + 1, par3, par4); int k = par1World.getBlockId(par2, par3, par4 + 1); int l = par1World.getBlockId(par2-1, par3, par4); int m = par1World.getBlockId(par2, par3 + 1, par4); int n = par1World.getBlockId(par2, par3 - 1, par4); if(i == g && j != g && k != g && l != g) { MetaData = 0; } if(j == g && i != g && k != g && l != g) { MetaData = 0; } if(k == g && j != g && i != g && l != g) { MetaData = 0; } if(l == g && j != g && k != g && i != g) { MetaData = 0; } if(i == g && j == g && k != g && l != g) { MetaData = 1; } if(i == g && l == g && k != g && j != g) { MetaData = 1; } if(k == g && j == g && i != g && l != g) { MetaData = 1; } if(k == g && l == g && i != g && j != g) { MetaData = 1; } Then this variable is called in the createTileEnitity function and used to determine what Entity to use and sets a renderID, which is then used in the getRenderType function: @Override public TileEntity createNewTileEntity(World world) { if(MetaData == 0) { renderID = -1; return new TileEntityLeadPipe(); } else if(MetaData == 1) { renderID = -2; return new TileEntityLeadPipeCorner(); } return null; } So my issue now is that it seems to be a bit random to what block is place and seems to hold the last placed block model, so when I place another block anywhere if it was the corner pipe it will place that one again, I want it to revert to straight pipe after being used. Quote
Bugsy6 Posted May 20, 2013 Author Posted May 20, 2013 So I narrowed the error down to when I place a corner piece it lays a straight piece, but then if I remove it and lay it again this time it will be a corner piece. It seems to take the first placed block to change the model then the second time its placed it actually renders the right block. Any ides what is going on? Quote
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.