package com.carpentersblocks.renderer; import net.minecraft.block.Block; import net.minecraft.block.BlockGrass; import net.minecraft.block.BlockRailBase; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.world.IBlockAccess; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.util.ForgeDirection; import org.lwjgl.opengl.GL11; import com.carpentersblocks.block.BlockCoverable; import com.carpentersblocks.data.Slope; import com.carpentersblocks.renderer.helper.LightingHelper; import com.carpentersblocks.renderer.helper.RenderHelper; import com.carpentersblocks.renderer.helper.RoutableFluidsHelper; import com.carpentersblocks.renderer.helper.VertexHelper; import com.carpentersblocks.tileentity.TEBase; import com.carpentersblocks.util.BlockProperties; import com.carpentersblocks.util.handler.DesignHandler; import com.carpentersblocks.util.handler.DyeHandler; import com.carpentersblocks.util.handler.OptifineHandler; import com.carpentersblocks.util.handler.OverlayHandler; import com.carpentersblocks.util.handler.OverlayHandler.Overlay; import com.carpentersblocks.util.registry.FeatureRegistry; import com.carpentersblocks.util.registry.IconRegistry; import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class BlockHandlerBase implements ISimpleBlockRenderingHandler { public static final int PASS_OPAQUE = 0; public static final int PASS_ALPHA = 1; public static final int DOWN = 0; public static final int UP = 1; public static final int NORTH = 2; public static final int SOUTH = 3; public static final int WEST = 4; public static final int EAST = 5; public Tessellator tessellator = Tessellator.instance; public RenderBlocks renderBlocks; public LightingHelper lightingHelper; public Block srcBlock; public TEBase TE; public boolean suppressOverlay; public boolean suppressChiselDesign; public boolean suppressDyeColor; public boolean disableAO; public boolean hasDyeOverride; public int dyeOverride; public boolean[] hasIconOverride = new boolean[6]; public IIcon[] iconOverride = new IIcon[6]; public int renderPass; /** 0-5 are side covers, with 6 being the block itself. */ public int coverRendering = 6; @Override public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderBlocks) { Tessellator tessellator = Tessellator.instance; GL11.glRotatef(90.0F, 0.0F, 1.0F, 0.0F); GL11.glTranslatef(-0.5F, -0.5F, -0.5F); tessellator.startDrawingQuads(); if (block instanceof BlockCoverable) { IIcon icon = renderBlocks.getIconSafe(((BlockCoverable)block).getIcon()); tessellator.setNormal(0.0F, -1.0F, 0.0F); renderBlocks.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, icon); tessellator.setNormal(0.0F, 1.0F, 0.0F); renderBlocks.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, icon); tessellator.setNormal(0.0F, 0.0F, -1.0F); renderBlocks.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, icon); tessellator.setNormal(0.0F, 0.0F, 1.0F); renderBlocks.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, icon); tessellator.setNormal(-1.0F, 0.0F, 0.0F); renderBlocks.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, icon); tessellator.setNormal(1.0F, 0.0F, 0.0F); renderBlocks.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, icon); } else { tessellator.setNormal(0.0F, -1.0F, 0.0F); renderBlocks.renderFaceYNeg(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(0, metadata))); tessellator.setNormal(0.0F, 1.0F, 0.0F); renderBlocks.renderFaceYPos(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(1, metadata))); tessellator.setNormal(0.0F, 0.0F, -1.0F); renderBlocks.renderFaceZNeg(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(2, metadata))); tessellator.setNormal(0.0F, 0.0F, 1.0F); renderBlocks.renderFaceZPos(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(3, metadata))); tessellator.setNormal(-1.0F, 0.0F, 0.0F); renderBlocks.renderFaceXNeg(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(4, metadata))); tessellator.setNormal(1.0F, 0.0F, 0.0F); renderBlocks.renderFaceXPos(block, 0.0D, 0.0D, 0.0D, renderBlocks.getIconSafe(block.getIcon(5, metadata))); } tessellator.draw(); GL11.glTranslatef(0.5F, 0.5F, 0.5F); GL11.glRotatef(90.0F, 0.0F, -1.0F, 0.0F); } @Override public boolean renderWorldBlock(IBlockAccess blockAccess, int x, int y, int z, Block block, int modelID, RenderBlocks renderBlocks) { VertexHelper.vertexCount = 0; renderPass = MinecraftForgeClient.getRenderPass(); TileEntity TE_default = blockAccess.getTileEntity(x, y, z); if (TE_default != null && TE_default instanceof TEBase) { TE = (TEBase) TE_default; srcBlock = block; this.renderBlocks = renderBlocks; lightingHelper = new LightingHelper(renderBlocks); renderCarpentersBlock(x, y, z); renderSideBlocks(x, y, z); if (FeatureRegistry.enableRoutableFluids) { VertexHelper.vertexCount += RoutableFluidsHelper.render(TE, renderBlocks, x, y, z) ? 4 : 0; } if (FeatureRegistry.enableRailSlopes) { Block blockYP = blockAccess.getBlock(x, y + 1, z); if (blockAccess.isSideSolid(x, y, z, ForgeDirection.UP, false) && blockYP instanceof BlockRailBase) { int metadata = ((BlockRailBase)blockYP).getBasicRailMetadata(blockAccess, null, x, y + 1, z); BlockHandlerCarpentersSlope slopeHandler = new BlockHandlerCarpentersSlope(); slopeHandler.renderBlocks = this.renderBlocks; slopeHandler.TE = TE; slopeHandler.lightingHelper = lightingHelper; slopeHandler.srcBlock = srcBlock; slopeHandler.suppressOverlay = true; switch (metadata) { case 2: // Sloping down -X (West) slopeHandler.renderSlope(getCoverForRendering(TE), Slope.WEDGE_POS_W, x, y + 1, z, true); break; case 3: // Sloping down +X (East) slopeHandler.renderSlope(getCoverForRendering(TE), Slope.WEDGE_POS_E, x, y + 1, z, true); break; case 4: // Sloping down +Z (South) slopeHandler.renderSlope(getCoverForRendering(TE), Slope.WEDGE_POS_S, x, y + 1, z, true); break; case 5: // Sloping down -Z (North) slopeHandler.renderSlope(getCoverForRendering(TE), Slope.WEDGE_POS_N, x, y + 1, z, true); break; default: {} } } } } return VertexHelper.vertexCount > 0; } @Override public boolean shouldRender3DInInventory(int modelId) { return true; } @Override public int getRenderId() { return 0; } /** * For South-facing block, sets render bounds, rotates them and renders. */ protected void renderBlockWithRotation(ItemStack itemStack, int x, int y, int z, double xMin, double yMin, double zMin, double xMax, double yMax, double zMax, ForgeDirection ... dir) { renderBlocks.setRenderBounds(xMin, yMin, zMin, xMax, yMax, zMax); for (ForgeDirection rot : dir) { rotateBounds(renderBlocks, rot); } renderBlock(itemStack, x, y, z); } /** * For South-facing blocks, rotates bounds for a single directional input. */ protected void rotateBounds(RenderBlocks renderBlocks, ForgeDirection dir) { switch (dir) { case DOWN: renderBlocks.setRenderBounds( renderBlocks.renderMinX, 1.0D - renderBlocks.renderMaxZ, renderBlocks.renderMinY, renderBlocks.renderMaxX, 1.0D - renderBlocks.renderMinZ, renderBlocks.renderMaxY ); break; case UP: renderBlocks.setRenderBounds( renderBlocks.renderMinX, renderBlocks.renderMinZ, renderBlocks.renderMinY, renderBlocks.renderMaxX, renderBlocks.renderMaxZ, renderBlocks.renderMaxY ); break; case NORTH: renderBlocks.setRenderBounds( 1.0D - renderBlocks.renderMaxX, renderBlocks.renderMinY, 1.0D - renderBlocks.renderMaxZ, 1.0D - renderBlocks.renderMinX, renderBlocks.renderMaxY, 1.0D - renderBlocks.renderMinZ ); break; case EAST: renderBlocks.setRenderBounds( renderBlocks.renderMinZ, renderBlocks.renderMinY, 1.0D - renderBlocks.renderMaxX, renderBlocks.renderMaxZ, renderBlocks.renderMaxY, 1.0D - renderBlocks.renderMinX ); break; case WEST: renderBlocks.setRenderBounds( 1.0D - renderBlocks.renderMaxZ, renderBlocks.renderMinY, renderBlocks.renderMinX, 1.0D - renderBlocks.renderMinZ, renderBlocks.renderMaxY, renderBlocks.renderMaxX ); break; default: {} } } /** * Gets cover {@link ItemStack} suitable for pulling block textures * from, regardless if it has an {@link NBTTagCompound}. * * @param TE [optional] the {@link TEBase}, if not {@link #srcBlock} * @return the {@link ItemStack} */ protected ItemStack getCoverForRendering(TEBase ... TE) { TEBase temp = TE.length == 0 ? this.TE : TE[0]; return BlockProperties.getCoverSafe(temp, coverRendering); } /** * Sets texture rotation for side. */ protected void setTextureRotation(int side, int rotation) { switch (side) { case DOWN: renderBlocks.uvRotateBottom = rotation; break; case UP: renderBlocks.uvRotateTop = rotation; break; case NORTH: renderBlocks.uvRotateNorth = rotation; break; case SOUTH: renderBlocks.uvRotateSouth = rotation; break; case WEST: renderBlocks.uvRotateWest = rotation; break; default: renderBlocks.uvRotateEast = rotation; break; } } /** * Sets directional block side rotation in RenderBlocks for * directional blocks like pillars and logs. */ protected void setTextureRotationForDirectionalBlock(int side) { int metadata = getCoverForRendering().getItemDamage(); int dir = metadata & 12; switch (side) { case DOWN: if (metadata == 3 || dir == 4) { renderBlocks.uvRotateBottom = 1; } break; case UP: if (metadata == 3 || dir == 4) { renderBlocks.uvRotateTop = 1; } break; case NORTH: if (metadata == 3 || dir == 4) { renderBlocks.uvRotateNorth = 1; } break; case SOUTH: if (metadata == 3 || dir == 4) { renderBlocks.uvRotateSouth = 1; } break; case WEST: if (metadata == 3 || dir == 8) { renderBlocks.uvRotateWest = 1; } break; case EAST: if (metadata == 3 || dir == 8) { renderBlocks.uvRotateEast = 1; } break; } } /** * Resets side rotation in RenderBlocks back to default values. */ protected void resetTextureRotation(int side) { switch (side) { case DOWN: renderBlocks.uvRotateBottom = 0; break; case UP: renderBlocks.uvRotateTop = 0; break; case NORTH: renderBlocks.uvRotateNorth = 0; break; case SOUTH: renderBlocks.uvRotateSouth = 0; break; case WEST: renderBlocks.uvRotateWest = 0; break; case EAST: renderBlocks.uvRotateEast = 0; break; } } /** * Returns texture rotation for side. */ protected int getTextureRotation(int side) { int[] rotations = { renderBlocks.uvRotateBottom, renderBlocks.uvRotateTop, renderBlocks.uvRotateNorth, renderBlocks.uvRotateSouth, renderBlocks.uvRotateWest, renderBlocks.uvRotateEast }; return rotations[side]; } /** * Sets dye override. */ protected void setDyeOverride(int color) { hasDyeOverride = true; dyeOverride = color; } /** * Clears dye override. */ protected void clearDyeOverride() { hasDyeOverride = false; } /** * Sets icon override. * Using side 6 overrides all sides. * RenderBlocks' icon override will override this one * when breaking animation is played. */ protected void setIconOverride(int side, IIcon icon) { if (side == 6) { for (int count = 0; count < 6; ++count) { hasIconOverride[count] = true; iconOverride[count] = icon; } } else { hasIconOverride[side] = true; iconOverride[side] = icon; } } /** * Clears icon override. */ protected void clearIconOverride(int side) { if (side == 6) { for (int count = 0; count < 6; ++count) { hasIconOverride[count] = false; } } else { hasIconOverride[side] = false; } } /** * Sets up side cover rendering bounds. * Will return block location where side cover should be rendered. */ protected int[] getSideCoverRenderBounds(int x, int y, int z, int side) { double offset = 1.0D / 16.0D; /* * Make snow match vanilla snow depth for continuity. */ if (side == UP) { Block block = BlockProperties.toBlock(getCoverForRendering()); if (block.equals(Blocks.snow) || block.equals(Blocks.snow_layer)) { offset = 1.0D / 8.0D; } } /* * Adjust bounds of side cover to accommodate * partial rendered blocks (slabs, stair steps) */ switch (side) { case DOWN: if (renderBlocks.renderMinY > 0.0D) { renderBlocks.renderMaxY = renderBlocks.renderMinY; renderBlocks.renderMinY -= offset; } else { renderBlocks.renderMaxY = 1.0D; renderBlocks.renderMinY = renderBlocks.renderMaxY - offset; y -= 1; } break; case UP: if (renderBlocks.renderMaxY < 1.0D) { renderBlocks.renderMinY = renderBlocks.renderMaxY; renderBlocks.renderMaxY += offset; } else { renderBlocks.renderMaxY = offset; renderBlocks.renderMinY = 0.0D; y += 1; } break; case NORTH: if (renderBlocks.renderMinZ > 0.0D) { renderBlocks.renderMaxZ = renderBlocks.renderMinZ; renderBlocks.renderMinZ -= offset; } else { renderBlocks.renderMaxZ = 1.0D; renderBlocks.renderMinZ = renderBlocks.renderMaxZ - offset; z -= 1; } break; case SOUTH: if (renderBlocks.renderMaxZ < 1.0D) { renderBlocks.renderMinZ = renderBlocks.renderMaxZ; renderBlocks.renderMaxZ += offset; } else { renderBlocks.renderMaxZ = offset; renderBlocks.renderMinZ = 0.0D; z += 1; } break; case WEST: if (renderBlocks.renderMinX > 0.0D) { renderBlocks.renderMaxX = renderBlocks.renderMinX; renderBlocks.renderMinX -= offset; } else { renderBlocks.renderMaxX = 1.0D; renderBlocks.renderMinX = renderBlocks.renderMaxX - offset; x -= 1; } break; case EAST: if (renderBlocks.renderMaxX < 1.0D) { renderBlocks.renderMinX = renderBlocks.renderMaxX; renderBlocks.renderMaxX += offset; } else { renderBlocks.renderMaxX = offset; renderBlocks.renderMinX = 0.0D; x += 1; } break; } return new int[] { x, y, z }; } /** * Renders side covers. */ protected void renderSideBlocks(int x, int y, int z) { renderBlocks.renderAllFaces = true; srcBlock.setBlockBoundsBasedOnState(renderBlocks.blockAccess, x, y, z); for (int side = 0; side < 6; ++side) { if (TE.hasAttribute(TE.ATTR_COVER[side])) { coverRendering = side; int[] renderOffset = getSideCoverRenderBounds(x, y, z, side); renderBlock(getCoverForRendering(), renderOffset[0], renderOffset[1], renderOffset[2]); renderBlocks.setRenderBoundsFromBlock(srcBlock); } } renderBlocks.renderAllFaces = false; coverRendering = 6; } /** * Override to provide custom icons. */ protected IIcon getUniqueIcon(ItemStack itemStack, int side, IIcon icon) { return icon; } /** * Returns icon for face. */ protected IIcon getIcon(ItemStack itemStack, int side) { BlockProperties.prepareItemStackForRendering(itemStack); IIcon icon = renderBlocks.getIconSafe(getUniqueIcon(itemStack, side, BlockProperties.toBlock(itemStack).getIcon(side, itemStack.getItemDamage()))); if (hasIconOverride[side]) { icon = renderBlocks.getIconSafe(iconOverride[side]); } return icon; } /** * Renders multiple textures to side. */ protected void renderMultiTexturedSide(ItemStack itemStack, int x, int y, int z, int side) { Block block = BlockProperties.toBlock(itemStack); boolean renderCover = (block instanceof BlockCoverable ? renderPass == 0 : block.canRenderInPass(renderPass)); boolean hasDesign = TE.hasChiselDesign(coverRendering); boolean hasOverlay = TE.hasAttribute(TE.ATTR_OVERLAY[coverRendering]); double overlayOffset = 0.0D; if (hasOverlay) { if (hasDesign) { overlayOffset = RenderHelper.OFFSET_MAX; } else if (renderPass == PASS_OPAQUE && block.getRenderBlockPass() == PASS_ALPHA && !(block instanceof BlockCoverable)) { overlayOffset = RenderHelper.OFFSET_MIN; } } /* Render side */ if (renderCover) { int tempRotation = getTextureRotation(side); if (BlockProperties.blockRotates(itemStack)) { setTextureRotationForDirectionalBlock(side); } setColorAndRender(itemStack, x, y, z, side, getIcon(itemStack, side)); setTextureRotation(side, tempRotation); } /* Render BlockGrass side overlay here, if needed. */ if (renderPass == PASS_OPAQUE && block.equals(Blocks.grass) && side > 0 && !isPositiveFace(side)) { if (Minecraft.isFancyGraphicsEnabled()) { setColorAndRender(new ItemStack(Blocks.grass), x, y, z, side, BlockGrass.getIconSideOverlay()); } else { setColorAndRender(new ItemStack(Blocks.dirt), x, y, z, side, IconRegistry.icon_overlay_fast_grass_side); } } boolean temp_dye_state = suppressDyeColor; suppressDyeColor = true; if (hasDesign && !suppressChiselDesign && renderPass == PASS_ALPHA) { RenderHelper.setOffset(RenderHelper.OFFSET_MIN); renderChiselDesign(x, y, z, side); RenderHelper.clearOffset(); } if (hasOverlay && !suppressOverlay && renderPass == PASS_OPAQUE) { RenderHelper.setOffset(overlayOffset); renderOverlay(x, y, z, side); RenderHelper.clearOffset(); } suppressDyeColor = temp_dye_state; } /** * Sets side icon, draws any attributes needed, and hands to appropriate render method. * This will bypass typical draw behavior if breaking animation is being drawn. */ protected void delegateSideRender(ItemStack itemStack, int x, int y, int z, int side) { /* * A texture override in the context of this mod indicates the breaking * animation is being drawn. If this is the case, draw side without * decorations. Can also check icon name for beginsWith("destroy_stage_"). */ if (renderBlocks.hasOverrideBlockTexture()) { setColorAndRender(itemStack, x, y, z, side, renderBlocks.overrideBlockTexture); } else { renderMultiTexturedSide(itemStack, x, y, z, side); } } /** * Renders overlay on side. */ protected void renderOverlay(int x, int y, int z, int side) { side = isPositiveFace(side) ? 1 : side; Overlay overlay = OverlayHandler.getOverlayType(TE.getAttribute(TE.ATTR_OVERLAY[coverRendering])); IIcon icon = OverlayHandler.getOverlayIcon(overlay, side); if (icon != null) { setColorAndRender(overlay.getItemStack(), x, y, z, side, icon); } } /** * Renders chisel design on side. */ protected void renderChiselDesign(int x, int y, int z, int side) { String design = TE.getChiselDesign(coverRendering); IIcon icon = renderBlocks.getIconSafe(IconRegistry.icon_design_chisel.get(DesignHandler.listChisel.indexOf(design))); setColorAndRender(new ItemStack(Blocks.glass), x, y, z, side, icon); } /** * Sets color, lightness, and brightness in {@link LightingHelper} and * renders side. * <p> * Also calls {@link VertexHelper#postRender} and thus cannot be overridden. * * @param itemStack the cover ItemStack * @param block the block inside the ItemStack * @param x the x coordinate * @param y the y coordinate * @param z the z coordinate * @param side the side currently being worked on * @param icon the icon for the side * @return nothing */ public final void setColorAndRender(ItemStack itemStack, int x, int y, int z, int side, IIcon icon) { int color = getBlockColor(BlockProperties.toBlock(itemStack), itemStack.getItemDamage(), x, y, z, side, icon); if (!suppressDyeColor && (TE.hasAttribute(TE.ATTR_DYE[coverRendering]) || hasDyeOverride)) { color = hasDyeOverride ? dyeOverride : DyeHandler.getColor(TE.getAttribute(TE.ATTR_DYE[coverRendering])); } lightingHelper.setupColor(x, y, z, side, color, icon); render(x, y, z, side, icon); VertexHelper.postRender(); } /** * Returns a integer with hex for 0xrrggbb for block. Color is most * commonly different for {@link Blocks#grass} * <p> * If using our custom render helpers, be sure to use {@link #applyAnaglyph(float[])}. * * @param itemStack the cover {@link ItemStack} * @param block the {@link Block} inside the {@link ItemStack} * @param x the x coordinate * @param y the y coordinate * @param z the z coordinate * @return a integer with hex for 0xrrggbb */ public int getBlockColor(Block block, int metadata, int x, int y, int z, int side, IIcon icon) { if (block.hasTileEntity(metadata)) { block = Blocks.dirt; } TE.setMetadata(metadata); int color = OptifineHandler.enableOptifineIntegration ? OptifineHandler.getColorMultiplier(block, TE.getWorldObj(), x, y, z) : block.colorMultiplier(TE.getWorldObj(), x, y, z); TE.restoreMetadata(); if (block.equals(Blocks.grass) && !isPositiveFace(side) && !icon.equals(BlockGrass.getIconSideOverlay())) { color = 16777215; } return color; } /** * Returns whether side is considered a top face. * * @param TE the {@link TEBase} * @param block the {@link Block} * @param side the side * @param icon the {@link IIcon} * @return true if positive y face */ protected boolean isPositiveFace(int side) { return side == 1; } /** * Renders a side. * * @param x the x coordinate * @param y the y coordinate * @param z the z coordinate * @param side the side currently being worked on * @param icon the icon for the side * @return nothing */ protected void render(int x, int y, int z, int side, IIcon icon) { switch (side) { case DOWN: RenderHelper.renderFaceYNeg(renderBlocks, x, y, z, icon); break; case UP: RenderHelper.renderFaceYPos(renderBlocks, x, y, z, icon); break; case NORTH: RenderHelper.renderFaceZNeg(renderBlocks, x, y, z, icon); break; case SOUTH: RenderHelper.renderFaceZPos(renderBlocks, x, y, z, icon); break; case WEST: RenderHelper.renderFaceXNeg(renderBlocks, x, y, z, icon); break; case EAST: RenderHelper.renderFaceXPos(renderBlocks, x, y, z, icon); break; } } /** * Renders single-sided face using current render bounds. * <p> * This is needed for panes and screens, and will render if current * render pass and {@link FeatureRegistry#enableAlphaPanes} are compatible. */ protected void renderPane(IIcon icon, int x, int y, int z, ForgeDirection facing, boolean enableAO, boolean flipped) { if (renderPass == PASS_OPAQUE ? !FeatureRegistry.enableAlphaPanes : FeatureRegistry.enableAlphaPanes) { doLightAndRenderSide(icon, x, y, z, facing, enableAO); if (flipped) { doLightAndRenderSide(icon, x, y, z, facing.getOpposite(), enableAO); } } } /** * Lights and renders a side. * <p> * Used primarily for rendering panes to help cut down on code. * * @param icon * @param x * @param y * @param z * @param facing */ private void doLightAndRenderSide(IIcon icon, int x, int y, int z, ForgeDirection facing, boolean enableAO) { ItemStack itemStack = new ItemStack(Blocks.glass); int blockColor = getBlockColor(Blocks.glass, 0, x, y, z, facing.ordinal(), null); boolean hasAO = renderBlocks.enableAO; renderBlocks.enableAO = enableAO; switch (facing) { case DOWN: lightingHelper.setupLightingYNeg(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceYNeg(renderBlocks, x, y, z, icon); break; case UP: lightingHelper.setupLightingYPos(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceYPos(renderBlocks, x, y, z, icon); break; case NORTH: lightingHelper.setupLightingZNeg(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceZNeg(renderBlocks, x, y, z, icon); break; case SOUTH: lightingHelper.setupLightingZPos(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceZPos(renderBlocks, x, y, z, icon); break; case WEST: lightingHelper.setupLightingXNeg(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceXNeg(renderBlocks, x, y, z, icon); break; case EAST: lightingHelper.setupLightingXPos(itemStack, x, y, z); lightingHelper.setupColor(x, y, z, facing.ordinal(), blockColor, null); RenderHelper.renderFaceXPos(renderBlocks, x, y, z, icon); break; default: {} } renderBlocks.enableAO = hasAO; } /** * Blocks override this in order to render everything they need. */ protected void renderCarpentersBlock(int x, int y, int z) { renderBlock(getCoverForRendering(), x, y, z); } /** * Sets renderBlocks enableAO state to true depending on * rendering environment and block requirements. */ public boolean getEnableAO(ItemStack itemStack) { Block block = BlockProperties.toBlock(itemStack); return Minecraft.isAmbientOcclusionEnabled() && !disableAO && block.getLightValue() == 0; } /** * Renders block. * Coordinates may change since side covers render here. */ protected void renderBlock(ItemStack itemStack, int x, int y, int z) { if (BlockProperties.toBlock(itemStack) == null) { return; } renderBlocks.enableAO = getEnableAO(itemStack); if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x, y - 1, z, DOWN) || renderBlocks.renderMinY > 0.0D) { lightingHelper.setupLightingYNeg(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, DOWN); } if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x, y + 1, z, UP) || renderBlocks.renderMaxY < 1.0D) { lightingHelper.setupLightingYPos(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, UP); } if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x, y, z - 1, NORTH) || renderBlocks.renderMinZ > 0.0D) { lightingHelper.setupLightingZNeg(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, NORTH); } if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x, y, z + 1, SOUTH) || renderBlocks.renderMaxZ < 1.0D) { lightingHelper.setupLightingZPos(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, SOUTH); } if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x - 1, y, z, WEST) || renderBlocks.renderMinX > 0.0D) { lightingHelper.setupLightingXNeg(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, WEST); } if (renderBlocks.renderAllFaces || srcBlock.shouldSideBeRendered(TE.getWorldObj(), x + 1, y, z, EAST) || renderBlocks.renderMaxX < 1.0D) { lightingHelper.setupLightingXPos(itemStack, x, y, z); delegateSideRender(itemStack, x, y, z, EAST); } renderBlocks.enableAO = false; } }