package net.minecraftforge.fluids; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderBlocks; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.MathHelper; import net.minecraft.world.IBlockAccess; import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler; /** * Default renderer for Forge fluid blocks. * * @author King Lemming * */ public class RenderBlockFluid implements ISimpleBlockRenderingHandler { public static RenderBlockFluid instance = new RenderBlockFluid(); static final float LIGHT_Y_NEG = 0.5F; static final float LIGHT_Y_POS = 1.0F; static final float LIGHT_XZ_NEG = 0.8F; static final float LIGHT_XZ_POS = 0.6F; static final double RENDER_OFFSET = 0.0010000000474974513D; public float getFluidHeightAverage(float[] flow) { float total = 0; int count = 0; float end = 0; for (int i = 0; i < flow.length; i++) { if (flow[i] >= 0.875F && end != 1F) { end = flow[i]; } if (flow[i] >= 0) { total += flow[i]; count++; } } if (end == 0) end = total / count; return end; } public float getFluidHeightForRender(IBlockAccess world, int x, int y, int z, BlockFluidBase block) { if (world.getBlock(x, y, z) == block) { Block verticalOrigin = world.getBlock(x, y - block.densityDir, z); if (verticalOrigin.getMaterial().isLiquid() || verticalOrigin instanceof IFluidBlock) { return 1; } if (world.getBlockMetadata(x, y, z) == block.getMaxRenderHeightMeta()) { return 0.875F; } } return !world.getBlock(x, y, z).getMaterial().isSolid() && world.getBlock(x, y - block.densityDir, z) == block ? 1 : block.getQuantaPercentage(world, x, y, z) * 0.875F; } /* ISimpleBlockRenderingHandler */ @Override public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer){} @Override public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) { if (!(block instanceof BlockFluidBase)) { return false; } Tessellator tessellator = Tessellator.instance; int color = block.colorMultiplier(world, x, y, z); float red = (color >> 16 & 255) / 255.0F; float green = (color >> 8 & 255) / 255.0F; float blue = (color & 255) / 255.0F; BlockFluidBase theFluid = (BlockFluidBase) block; int bMeta = world.getBlockMetadata(x, y, z); boolean renderTop = world.getBlock(x, y - theFluid.densityDir, z) != theFluid; boolean renderBottom = block.shouldSideBeRendered(world, x, y + theFluid.densityDir, z, 0) && world.getBlock(x, y + theFluid.densityDir, z) != theFluid; boolean[] renderSides = new boolean[] { block.shouldSideBeRendered(world, x, y, z - 1, 2), block.shouldSideBeRendered(world, x, y, z + 1, 3), block.shouldSideBeRendered(world, x - 1, y, z, 4), block.shouldSideBeRendered(world, x + 1, y, z, 5) }; if (!renderTop && !renderBottom && !renderSides[0] && !renderSides[1] && !renderSides[2] && !renderSides[3]) { return false; } else { boolean rendered = false; double heightNW, heightSW, heightSE, heightNE; float flow11 = getFluidHeightForRender(world, x, y, z, theFluid); if (flow11 != 1) { float flow00 = getFluidHeightForRender(world, x - 1, y, z - 1, theFluid); float flow01 = getFluidHeightForRender(world, x - 1, y, z, theFluid); float flow02 = getFluidHeightForRender(world, x - 1, y, z + 1, theFluid); float flow10 = getFluidHeightForRender(world, x, y, z - 1, theFluid); float flow12 = getFluidHeightForRender(world, x, y, z + 1, theFluid); float flow20 = getFluidHeightForRender(world, x + 1, y, z - 1, theFluid); float flow21 = getFluidHeightForRender(world, x + 1, y, z, theFluid); float flow22 = getFluidHeightForRender(world, x + 1, y, z + 1, theFluid); heightNW = getFluidHeightAverage(new float[]{ flow00, flow01, flow10, flow11 }); heightSW = getFluidHeightAverage(new float[]{ flow01, flow02, flow12, flow11 }); heightSE = getFluidHeightAverage(new float[]{ flow12, flow21, flow22, flow11 }); heightNE = getFluidHeightAverage(new float[]{ flow10, flow20, flow21, flow11 }); } else { heightNW = flow11; heightSW = flow11; heightSE = flow11; heightNE = flow11; } boolean rises = theFluid.densityDir == 1; if (renderer.renderAllFaces || renderTop) { rendered = true; IIcon iconStill = getIcon(block.getIcon(1, bMeta)); float flowDir = (float) BlockFluidBase.getFlowDirection(world, x, y, z); if (flowDir > -999.0F) { iconStill = getIcon(block.getIcon(2, bMeta)); } heightNW -= RENDER_OFFSET; heightSW -= RENDER_OFFSET; heightSE -= RENDER_OFFSET; heightNE -= RENDER_OFFSET; double u1, u2, u3, u4, v1, v2, v3, v4; if (flowDir < -999.0F) { u2 = iconStill.getInterpolatedU(0.0D); v2 = iconStill.getInterpolatedV(0.0D); u1 = u2; v1 = iconStill.getInterpolatedV(16.0D); u4 = iconStill.getInterpolatedU(16.0D); v4 = v1; u3 = u4; v3 = v2; } else { float xFlow = MathHelper.sin(flowDir) * 0.25F; float zFlow = MathHelper.cos(flowDir) * 0.25F; u2 = iconStill.getInterpolatedU(8.0F + (-zFlow - xFlow) * 16.0F); v2 = iconStill.getInterpolatedV(8.0F + (-zFlow + xFlow) * 16.0F); u1 = iconStill.getInterpolatedU(8.0F + (-zFlow + xFlow) * 16.0F); v1 = iconStill.getInterpolatedV(8.0F + (zFlow + xFlow) * 16.0F); u4 = iconStill.getInterpolatedU(8.0F + (zFlow + xFlow) * 16.0F); v4 = iconStill.getInterpolatedV(8.0F + (zFlow - xFlow) * 16.0F); u3 = iconStill.getInterpolatedU(8.0F + (zFlow - xFlow) * 16.0F); v3 = iconStill.getInterpolatedV(8.0F + (-zFlow - xFlow) * 16.0F); } tessellator.setBrightness(block.getMixedBrightnessForBlock(world, x, y, z)); tessellator.setColorOpaque_F(LIGHT_Y_POS * red, LIGHT_Y_POS * green, LIGHT_Y_POS * blue); if (!rises) { tessellator.addVertexWithUV(x + 0, y + heightNW, z + 0, u2, v2); tessellator.addVertexWithUV(x + 0, y + heightSW, z + 1, u1, v1); tessellator.addVertexWithUV(x + 1, y + heightSE, z + 1, u4, v4); tessellator.addVertexWithUV(x + 1, y + heightNE, z + 0, u3, v3); tessellator.addVertexWithUV(x + 0, y + heightNW, z + 0, u2, v2); tessellator.addVertexWithUV(x + 1, y + heightNE, z + 0, u3, v3); tessellator.addVertexWithUV(x + 1, y + heightSE, z + 1, u4, v4); tessellator.addVertexWithUV(x + 0, y + heightSW, z + 1, u1, v1); } else { tessellator.addVertexWithUV(x + 1, y + 1 - heightNE, z + 0, u3, v3); tessellator.addVertexWithUV(x + 1, y + 1 - heightSE, z + 1, u4, v4); tessellator.addVertexWithUV(x + 0, y + 1 - heightSW, z + 1, u1, v1); tessellator.addVertexWithUV(x + 0, y + 1 - heightNW, z + 0, u2, v2); tessellator.addVertexWithUV(x + 1, y + 1 - heightNE, z + 0, u3, v3); tessellator.addVertexWithUV(x + 0, y + 1 - heightNW, z + 0, u2, v2); tessellator.addVertexWithUV(x + 0, y + 1 - heightSW, z + 1, u1, v1); tessellator.addVertexWithUV(x + 1, y + 1 - heightSE, z + 1, u4, v4); } } if (renderer.renderAllFaces || renderBottom) { rendered = true; tessellator.setBrightness(block.getMixedBrightnessForBlock(world, x, y - 1, z)); if (!rises) { tessellator.setColorOpaque_F(LIGHT_Y_NEG * red, LIGHT_Y_NEG * green, LIGHT_Y_NEG * blue); renderer.renderFaceYNeg(block, x, y + RENDER_OFFSET, z, getIcon(block.getIcon(0, bMeta))); } else { tessellator.setColorOpaque_F(LIGHT_Y_POS * red, LIGHT_Y_POS * green, LIGHT_Y_POS * blue); renderer.renderFaceYPos(block, x, y + RENDER_OFFSET, z, getIcon(block.getIcon(1, bMeta))); } } for (int side = 0; side < 4; ++side) { int x2 = x; int z2 = z; switch (side) { case 0: --z2; break; case 1: ++z2; break; case 2: --x2; break; case 3: ++x2; break; } IIcon iconFlow = getIcon(block.getIcon(side + 2, bMeta)); if (renderer.renderAllFaces || renderSides[side]) { rendered = true; double ty1; double tx1; double ty2; double tx2; double tz1; double tz2; if (side == 0) { ty1 = heightNW; ty2 = heightNE; tx1 = x; tx2 = x + 1; tz1 = z + RENDER_OFFSET; tz2 = z + RENDER_OFFSET; } else if (side == 1) { ty1 = heightSE; ty2 = heightSW; tx1 = x + 1; tx2 = x; tz1 = z + 1 - RENDER_OFFSET; tz2 = z + 1 - RENDER_OFFSET; } else if (side == 2) { ty1 = heightSW; ty2 = heightNW; tx1 = x + RENDER_OFFSET; tx2 = x + RENDER_OFFSET; tz1 = z + 1; tz2 = z; } else { ty1 = heightNE; ty2 = heightSE; tx1 = x + 1 - RENDER_OFFSET; tx2 = x + 1 - RENDER_OFFSET; tz1 = z; tz2 = z + 1; } float u1Flow = iconFlow.getInterpolatedU(0.0D); float u2Flow = iconFlow.getInterpolatedU(8.0D); float v1Flow = iconFlow.getInterpolatedV((1.0D - ty1) * 16.0D * 0.5D); float v2Flow = iconFlow.getInterpolatedV((1.0D - ty2) * 16.0D * 0.5D); float v3Flow = iconFlow.getInterpolatedV(8.0D); tessellator.setBrightness(block.getMixedBrightnessForBlock(world, x2, y, z2)); float sideLighting = 1.0F; if (side < 2) { sideLighting = LIGHT_XZ_NEG; } else { sideLighting = LIGHT_XZ_POS; } tessellator.setColorOpaque_F(LIGHT_Y_POS * sideLighting * red, LIGHT_Y_POS * sideLighting * green, LIGHT_Y_POS * sideLighting * blue); if (!rises) { tessellator.addVertexWithUV(tx1, y + ty1, tz1, u1Flow, v1Flow); tessellator.addVertexWithUV(tx2, y + ty2, tz2, u2Flow, v2Flow); tessellator.addVertexWithUV(tx2, y + 0, tz2, u2Flow, v3Flow); tessellator.addVertexWithUV(tx1, y + 0, tz1, u1Flow, v3Flow); tessellator.addVertexWithUV(tx1, y + ty1, tz1, u1Flow, v1Flow); tessellator.addVertexWithUV(tx1, y + 0, tz1, u1Flow, v3Flow); tessellator.addVertexWithUV(tx2, y + 0, tz2, u2Flow, v3Flow); tessellator.addVertexWithUV(tx2, y + ty2, tz2, u2Flow, v2Flow); } else { tessellator.addVertexWithUV(tx1, y + 1 - 0, tz1, u1Flow, v3Flow); tessellator.addVertexWithUV(tx2, y + 1 - 0, tz2, u2Flow, v3Flow); tessellator.addVertexWithUV(tx2, y + 1 - ty2, tz2, u2Flow, v2Flow); tessellator.addVertexWithUV(tx1, y + 1 - ty1, tz1, u1Flow, v1Flow); tessellator.addVertexWithUV(tx1, y + 1 - 0, tz1, u1Flow, v3Flow); tessellator.addVertexWithUV(tx1, y + 1 - ty1, tz1, u1Flow, v1Flow); tessellator.addVertexWithUV(tx2, y + 1 - ty2, tz2, u2Flow, v2Flow); tessellator.addVertexWithUV(tx2, y + 1 - 0, tz2, u2Flow, v3Flow); } } } renderer.renderMinY = 0; renderer.renderMaxY = 1; return rendered; } } @Override public boolean shouldRender3DInInventory(int modelId){ return false; } @Override public int getRenderId() { return FluidRegistry.renderIdFluid; } private IIcon getIcon(IIcon icon) { if (icon != null) return icon; return ((TextureMap)Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture)).getAtlasSprite("missingno"); } }