package com.flansmod.apocalypse.client; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.vecmath.Vector3f; import com.flansmod.apocalypse.common.blocks.BlockSulphuricAcid; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.resources.model.IBakedModel; import net.minecraft.client.resources.model.SimpleBakedModel; import net.minecraft.util.EnumFacing; import net.minecraft.util.MathHelper; import net.minecraftforge.client.model.ISmartBlockModel; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class FluidBlockModel implements ISmartBlockModel { static final float RENDER_OFFSET = 0.001F; //Copied from old forge fluid renderer @Override public List getFaceQuads(EnumFacing facing) { return null; } @Override public List getGeneralQuads() { return null; } @Override public boolean isAmbientOcclusion() { return false; } @Override public boolean isGui3d() { return false; } @Override public boolean isBuiltInRenderer() { return false; } @Override public ItemCameraTransforms getItemCameraTransforms() { return null; } private final Map<List<Float>, SimpleBakedModel> models = new HashMap<List<Float>, SimpleBakedModel>(); @Override public IBakedModel handleBlockState(IBlockState state) { IExtendedBlockState extState = (IExtendedBlockState) state; float heightNW = extState.getValue(BlockSulphuricAcid.HEIGHT_NW); float heightSW = extState.getValue(BlockSulphuricAcid.HEIGHT_SW); float heightSE = extState.getValue(BlockSulphuricAcid.HEIGHT_SE); float heightNE = extState.getValue(BlockSulphuricAcid.HEIGHT_NE); float flow = extState.getValue(BlockSulphuricAcid.FLOW_DIRECTION); return getModel((BlockSulphuricAcid) state.getBlock(), Arrays.asList(heightSE, heightSW, heightNW, heightNE, flow)); } private SimpleBakedModel getModel(BlockSulphuricAcid block, List<Float> param) { SimpleBakedModel model = models.get(param); if(model == null) { model = this.buildModel(block, param); models.put(param, model); } return model; } private SimpleBakedModel buildModel(BlockSulphuricAcid block, List<Float> param) { TextureMap textureMap = Minecraft.getMinecraft().getTextureMapBlocks(); // TODO : 1.8.9 mess TextureAtlasSprite still = textureMap.getAtlasSprite("flansmodapocalypse:blocks/SulphuricAcidStill"); TextureAtlasSprite flowing = textureMap.getAtlasSprite("flansmodapocalypse:blocks/SulphuricAcidFlowing"); List<List<BakedQuad>> faceQuads = new ArrayList<List<BakedQuad>>(); for(int i = 0; i < 6; i++) { if(i == EnumFacing.DOWN.ordinal()) faceQuads.add(Arrays.asList(createQuad(new Vector3f(0, 0, 0), new Vector3f(1, 0, 0), new Vector3f(1, 0, 1), new Vector3f(0, 0, 1), still, EnumFacing.DOWN))); else if(i == EnumFacing.UP.ordinal()) { TextureAtlasSprite sprite = param.get(4) < -999F ? still : flowing; BakedQuad quad1 = createQuad(new Vector3f(0, param.get(2), 0), new Vector3f(0, param.get(1), 1), new Vector3f(1, param.get(0), 1), new Vector3f(1, param.get(3), 0), sprite, EnumFacing.UP, param.get(4)); BakedQuad quad2 = createQuad(new Vector3f(0, param.get(2) - RENDER_OFFSET, 0), new Vector3f(1, param.get(3) - RENDER_OFFSET, 0), new Vector3f(1, param.get(0) - RENDER_OFFSET, 1), new Vector3f(0, param.get(1) - RENDER_OFFSET, 1), sprite, EnumFacing.DOWN, param.get(4)); faceQuads.add(Arrays.asList(quad1, quad2)); } else { EnumFacing facing = EnumFacing.values()[i]; float height1 = param.get(facing.getHorizontalIndex()); float height2 = param.get((facing.getHorizontalIndex() + 1) % 4); int p = facing.getAxisDirection() == EnumFacing.AxisDirection.POSITIVE ? 1 : 0; float offset = facing.getAxisDirection().getOffset()*RENDER_OFFSET; if(facing.getAxis() == EnumFacing.Axis.X) { BakedQuad quad1 = createQuad(new Vector3f(p, 0, p), new Vector3f(p, 0, 1-p), new Vector3f(p, height1, 1-p), new Vector3f(p, height2, p), flowing, facing); BakedQuad quad2 = createQuad(new Vector3f(p - offset, 0, p), new Vector3f(p - offset, height2, p), new Vector3f(p - offset, height1, 1-p), new Vector3f(p - offset, 0, 1-p), flowing, facing.getOpposite()); faceQuads.add(Arrays.asList(quad1, quad2)); } else { BakedQuad quad1 = createQuad(new Vector3f(1-p, 0, p), new Vector3f(p, 0, p), new Vector3f(p, height1, p), new Vector3f(1-p, height2, p), flowing, facing); BakedQuad quad2 = createQuad(new Vector3f(1-p, 0, p - offset), new Vector3f(1-p, height2, p - offset), new Vector3f(p, height1, p - offset), new Vector3f(p, 0, p - offset), flowing, facing.getOpposite()); faceQuads.add(Arrays.asList(quad1, quad2)); } } } return new SimpleBakedModel(new ArrayList<BakedQuad>(), faceQuads, false, false, still, ItemCameraTransforms.DEFAULT); } private BakedQuad createQuad(Vector3f vec1, Vector3f vec2, Vector3f vec3, Vector3f vec4, TextureAtlasSprite sprite, EnumFacing facing) { return createQuad(vec1, vec2, vec3, vec4, sprite, facing, -1000F); } private BakedQuad createQuad(Vector3f vec1, Vector3f vec2, Vector3f vec3, Vector3f vec4, TextureAtlasSprite sprite, EnumFacing facing, float flowDir) { int[] data = new int[28]; int shade = getShade(facing); float xFlow = -1, zFlow = -1; if(flowDir > -999F) { xFlow = MathHelper.sin(flowDir) * 0.25F; zFlow = MathHelper.cos(flowDir) * 0.25F; } Vector3f[] vectors = {vec1, vec2, vec3, vec4}; for(int i = 0; i < 4; i++) { Vector3f vec = vectors[i]; int index = i*7; data[index] = Float.floatToRawIntBits(vec.x); data[index + 1] = Float.floatToRawIntBits(vec.y); data[index + 2] = Float.floatToRawIntBits(vec.z); data[index + 3] = shade; float u = sprite.getMaxU() - sprite.getMinU(); float v = sprite.getMaxV() - sprite.getMinV(); if(facing.getAxis() == EnumFacing.Axis.X) { data[index + 4] = Float.floatToRawIntBits(sprite.getInterpolatedU(vec.z*16F)); data[index + 5] = Float.floatToRawIntBits(sprite.getInterpolatedV(16F - vec.y*16F)); } else if(facing.getAxis() == EnumFacing.Axis.Y) { if(flowDir < -999F) { data[index + 4] = Float.floatToRawIntBits(sprite.getInterpolatedU(vec.x*16F)); data[index + 5] = Float.floatToRawIntBits(sprite.getInterpolatedV(vec.z*16F)); } else { data[index + 4] = Float.floatToRawIntBits(sprite.getInterpolatedU(8F + ((vec.z*2-1)*xFlow + (vec.x*2-1)*zFlow)*16F)); //The x and z values here are only expected to be 0 or 1. data[index + 5] = Float.floatToRawIntBits(sprite.getInterpolatedV(8F + ((1-2*vec.x)*xFlow + (vec.z*2-1)*zFlow)*16F)); } } else { data[index + 4] = Float.floatToRawIntBits(sprite.getInterpolatedU(vec.x*16F)); data[index + 5] = Float.floatToRawIntBits(sprite.getInterpolatedV(16F - vec.y*16F)); } } return new BakedQuad(data, -1, facing); } private int getShade(EnumFacing facing) //Copied from FaceBakery (Only the end result, and not the process) { if(facing == EnumFacing.DOWN) return -8421505; if(facing == EnumFacing.SOUTH || facing == EnumFacing.NORTH) return -3355444; if(facing == EnumFacing.WEST || facing == EnumFacing.EAST) return -6710887; else return -1; } @Override public TextureAtlasSprite getParticleTexture() { return null; } }