Posted January 18, 201510 yr Hi, I'm trying to make my block with a TileEntitySpecialRenderer face the player when he places it. I've looked into the furnace and anvil code to try to replicate it. At the moment, I'm not sure if it's the actual block not facing the correct direction or the model. I think it is probably the model, because the bounding box seems to change the correct orientation even when the model does not. My Block Class: public class BlockPoweredAnvil extends BlockContainer implements ITileEntityProvider { private Random rand = new Random(); public IIcon[] icons = new IIcon[2]; public BlockPoweredAnvil() { super(Material.rock); this.setCreativeTab(CreativeTabPandM.PANDM_TAB); this.setBlockName(Names.POWERED_ANVIL); this.setBlockTextureName(this.getUnwrappedUnlocalizedName(this.getUnlocalizedName())); } @Override public boolean renderAsNormalBlock() { return false; } @Override public boolean isOpaqueCube() { return false; } @Override public int getRenderType() { return -1; } @Override public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase entityLivingBase, ItemStack itemStack) { LogHelper.info("Block Placed"); int l = MathHelper.floor_double((double)(entityLivingBase.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; int i1 = world.getBlockMetadata(x, y, z) >> 2; ++l; l %= 4; if (l == 0) { LogHelper.info("0"); world.setBlockMetadataWithNotify(x, y, z, 2 | i1 << 2, 2); } if (l == 1) { LogHelper.info("1"); world.setBlockMetadataWithNotify(x, y, z, 3 | i1 << 2, 2); } if (l == 2) { LogHelper.info("2"); world.setBlockMetadataWithNotify(x, y, z, 0 | i1 << 2, 2); } if (l == 3) { LogHelper.info("3"); world.setBlockMetadataWithNotify(x, y, z, 1 | i1 << 2, 2); } } public void setBlockBoundsBasedOnState(IBlockAccess iBlockAccess, int x, int y, int z) { int l = iBlockAccess.getBlockMetadata(x, y, z) & 3; if (l != 3 && l != 1) { this.setBlockBounds(0.125F, 0.0F, 0.0F, 0.875F, 1.0F, 1.0F); } else { this.setBlockBounds(0.0F, 0.0F, 0.125F, 1.0F, 1.0F, 0.875F); } } @Override public void registerBlockIcons(IIconRegister iconRegister) { for (int i = 0; i < 2; i ++) { this.icons[i] = iconRegister.registerIcon(this.textureName + i); } } @Override public IIcon getIcon(int side, int meta) { if (side == 1) { return icons[0]; } return icons[1]; } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int meta, float hitX, float hitY, float hitZ) { if (!world.isRemote && world.getTileEntity(x, y, z) instanceof TileEntityPoweredAnvil) { entityPlayer.openGui(PandM.instance, GUIs.POWERED_ANVIL.ordinal(), world, x, y, z); } return true; } @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { TileEntityPoweredAnvil poweredAnvil = (TileEntityPoweredAnvil) world.getTileEntity(x, y, z); if (poweredAnvil != null) { for (int i = 0; i < poweredAnvil.getSizeInventory(); i++) { ItemStack itemStack = poweredAnvil.getStackInSlot(i); if (itemStack != null) { float f = this.rand.nextFloat() * 0.8F + 0.1F; float f1 = this.rand.nextFloat() * 0.8F + 0.1F; float f2 = this.rand.nextFloat() * 0.8F + 0.1F; while (itemStack.stackSize > 0) { int j = this.rand.nextInt(21) + 10; if (j > itemStack.stackSize) { j = itemStack.stackSize; } itemStack.stackSize -= j; EntityItem entityitem = new EntityItem(world, (double) ((float) x + f), (double) ((float) y + f1), (double) ((float) z + f2), new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage())); if (itemStack.hasTagCompound()) { entityitem.getEntityItem().setTagCompound((NBTTagCompound) itemStack.getTagCompound().copy()); } float f3 = 0.05F; entityitem.motionX = (double) ((float) this.rand.nextGaussian() * f3); entityitem.motionY = (double) ((float) this.rand.nextGaussian() * f3 + 0.2F); entityitem.motionZ = (double) ((float) this.rand.nextGaussian() * f3); world.spawnEntityInWorld(entityitem); } } } world.func_147453_f(x, y, z, block); } super.breakBlock(world, x, y, z, block, meta); } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityPoweredAnvil(); } @Override public String getUnlocalizedName() { return String.format("tile.%s%s", Reference.MOD_ID.toLowerCase() + ":", getUnwrappedUnlocalizedName(super.getUnlocalizedName())); } protected String getUnwrappedUnlocalizedName(String unlocalizedName) { return unlocalizedName.substring(unlocalizedName.indexOf(".") + 1); } } Some screenshots to hopefully better explain what I'm talking about: http://puu.sh/eI4Zr/e42a09109e.jpg http://puu.sh/eI52X/7306221137.jpg The models on both are facing the same direction, however the bounding box is different depending on which direction I was facing when I placed it. If you need to see any other classes, I can provide the code for them. Any help is appreciated! Thanks!
January 19, 201510 yr This is probably not the most efficient way to do it, but I have managed to get my models to rotate depending on the placed direction. Block code : https://github.com/Sudwood/AdvancedUtilities/blob/master/java/com/sudwood/advancedutilities/blocks/BlockSteamMachine.java#L151-190 Render code: https://github.com/Sudwood/AdvancedUtilities/blob/master/java/com/sudwood/advancedutilities/client/renders/RenderSteamSmeltry.java Hope that helps!
January 19, 201510 yr Block public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) { //This gets the direction the player is facing as an int from 0 to 3 int dir = MathHelper.floor_double((player.rotationYaw * 4F) / 360F + 0.5D) & 3; //You can use the block metadata to save the direction world.setBlockMetadataWithNotify(x, y, z, dir, 3); //Or you can save it in a tile entity if you are using one createNewTileEntity(world, world.getBlockMetadata(x, y, z)); } Custom Renderer //Stuff to get the dir int, from the block metadata or the tile or whatever //Check the dir and apply rotations if (dir == 0) { GL11.glRotatef(-180F, 0.0F, 1.0F, 0.0F); } if (dir % 2 != 0) { GL11.glRotatef(dir * (-90F), 0.0F, 1.0F, 0.0F); } if (dir % 2 == 0) { GL11.glRotatef(dir * (-180F), 0.0F, 1.0F, 0.0F); } This probably can be optimized a bit more, but this way its readable This is so commonly asked that it should be stickied somewhere ._.
January 19, 201510 yr Author Thanks for your reply! I tried this, but I think I either implemented it incorrectly or I need extra code for it to work with my ItemRenderer for the block. My game crashes with the following report: http://pastebin.com/b1V6yaU8 This is that class: package com.darichey.PandM.item.itemRenderer; import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.client.IItemRenderer; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; public class ItemRendererPoweredAnvil implements IItemRenderer { private TileEntity tileEntity; private TileEntitySpecialRenderer renderer; public ItemRendererPoweredAnvil(TileEntitySpecialRenderer renderer, TileEntity tileEntity) { this.tileEntity = tileEntity; this.renderer = renderer; } @Override public boolean handleRenderType(ItemStack item, ItemRenderType type) { return true; } @Override public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) { return true; } @Override public void renderItem(ItemRenderType type, ItemStack item, Object... data) { if (type == IItemRenderer.ItemRenderType.ENTITY) { GL11.glTranslatef(-0.5F, 0.0F, -0.5F); } this.tileEntity.blockMetadata = 0; this.renderer.renderTileEntityAt(this.tileEntity, 0.0D, 0.0D, 0.0D, 0.0F); } } package com.darichey.PandM.tileEntity.specialRenderer; import com.darichey.PandM.model.ModelPoweredAnvil; import com.darichey.PandM.reference.ResourceLocations; import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; public class RenderPoweredAnvil extends TileEntitySpecialRenderer { private ModelPoweredAnvil modelPoweredAnvil; public RenderPoweredAnvil() { this.modelPoweredAnvil = new ModelPoweredAnvil(); } private void RotateModelBasedOnMeta(World world, int x, int y, int z) { int meta = world.getBlockMetadata(x, y, z); if (meta == 0) { GL11.glRotatef(-180F, 0.0F, 1.0F, 0.0F); } if (meta % 2 != 0) { GL11.glRotatef(meta * (-90F), 0.0F, 1.0F, 0.0F); } if (meta % 2 == 0) { GL11.glRotatef(meta * (-180F), 0.0F, 1.0F, 0.0F); } } @Override public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) { GL11.glPushMatrix(); GL11.glTranslatef((float) x + 0.5F, (float) y - 0.5F, (float) z + 0.5F); RotateModelBasedOnMeta(tileEntity.getWorldObj(), tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord); this.bindTexture(ResourceLocations.PoweredAnvilModelTexture); GL11.glPushMatrix(); this.modelPoweredAnvil.renderModel(0.0625F); GL11.glPopMatrix(); GL11.glPopMatrix(); } }
January 19, 201510 yr You are using it wrong. You should override the whole render code in IItemRenderer to render in the inventory, not use the tile entity renderer. Somewheree in your initialization you should have something like this: ClientRegistry.bindTileEntitySpecialRenderer(MyTileEntity.class, new MyTileEntityRenderer()); http://www.minecraftforge.net/wiki/Custom_Tile_Entity_Renderer
January 19, 201510 yr Author Um no, I have both. The TileEntitySpecialRenderer is used to render the block in the world and ItemRender is used to render it in an inventory, right? I've included that second class in my previous reply if you need to look at it. EDIT: What do you mean by overriding the whole render code in IItemRenderer?
January 19, 201510 yr Yeah, my bad, i didn't see the second one. It appears to me that the tileentityrenderer won't work for the inventory you have to do the rendering yerself. You are looking for something along these lines. This is not actual code, you need to adapt it for your personal circumstances. public void renderItem(IItemRenderer.ItemRenderType type, ItemStack stack, Object... data) { ///blahblahblah get the texture get the model etc case INVENTORY: Minecraft.getMinecraft().renderEngine.bindTexture(modelTexture); { GL11.glPushMatrix(); GL11.glColor4f(1, 1, 1, 128); GL11.glPushMatrix(); GL11.glTranslatef(-0.5f, 0f, -0.5f); //This one is important because the model renders upside down because of reasons GL11.glPushMatrix(); GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F); GL11.glPushMatrix(); GL11.glScalef(1.9f, 1.9f, 1.9f); model.render(null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.05F, other arguments, whatevers); GL11.glPopMatrix(); GL11.glPopMatrix(); GL11.glPopMatrix(); GL11.glPopMatrix(); } and for entity items case ENTITY: Minecraft.getMinecraft().renderEngine.bindTexture(modelTexture); { GL11.glPushMatrix(); GL11.glColor4f(1, 1, 1, 128); GL11.glPushMatrix(); GL11.glTranslatef(0f, 1f, 0f); GL11.glPushMatrix(); GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F); GL11.glPushMatrix(); GL11.glScalef(1.2f, 1.2f, 1.2f); model.render(null, 0.0F, 0.0F, -0.1F, 0.0F, 0.0F, 0.05F, again some extra stuff if you want); GL11.glPopMatrix(); GL11.glPopMatrix(); GL11.glPopMatrix(); GL11.glPopMatrix(); }
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.