package slimeknights.tconstruct.smeltery.client;
import java.util.List;
import javax.annotation.Nonnull;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fluids.FluidStack;
import slimeknights.tconstruct.library.client.RenderUtil;
import slimeknights.tconstruct.library.smeltery.ISmelteryTankHandler;
import slimeknights.tconstruct.library.smeltery.SmelteryTank;
public class SmelteryTankRenderer<T extends TileEntity & ISmelteryTankHandler> extends TileEntitySpecialRenderer<T> {
public void renderFluids(SmelteryTank tank, @Nonnull BlockPos pos, @Nonnull BlockPos tankMinPos, @Nonnull BlockPos tankMaxPos, double x, double y, double z) {
// minpos as lightingPos instead of smeltery.pos because we want to use the lighting inside the smeltery
renderFluids(tank, pos, tankMinPos, tankMaxPos, x, y, z, RenderUtil.FLUID_OFFSET, tankMinPos);
}
public void renderFluids(SmelteryTank tank, @Nonnull BlockPos pos, @Nonnull BlockPos tankMinPos, @Nonnull BlockPos tankMaxPos, double x, double y, double z, float offsetToBlockEdge, @Nonnull BlockPos lightingPos) {
if(tank == null) {
return;
}
List<FluidStack> fluids = tank.getFluids();
// calculate x/z parameters. they'll be the same for all liquids
double x1 = tankMinPos.getX() - pos.getX();
double y1 = tankMinPos.getY() - pos.getY();
double z1 = tankMinPos.getZ() - pos.getZ();
double x2 = tankMaxPos.getX() - pos.getX();
double z2 = tankMaxPos.getZ() - pos.getZ();
// empty smeltery :(
if(!fluids.isEmpty()) {
BlockPos minPos = new BlockPos(x1, y1, z1);
BlockPos maxPos = new BlockPos(x2, y1, z2);
// calc heights, we use mB capacities and then convert it over to blockheights during rendering
int yd = 1 + Math.max(0, tankMaxPos.getY() - tankMinPos.getY());
// one block height = 1000 mb
int[] heights = calcLiquidHeights(fluids, tank.getCapacity(), yd * 1000 - (int) (RenderUtil.FLUID_OFFSET * 2000d), 100);
double curY = RenderUtil.FLUID_OFFSET;
// rendering time
for(int i = 0; i < fluids.size(); i++) {
double h = (double) heights[i] / 1000d;
RenderUtil.renderStackedFluidCuboid(fluids.get(i), x, y, z, lightingPos, minPos, maxPos, curY, curY + h, offsetToBlockEdge);
curY += h;
}
}
}
/**
* calculate the rendering heights for all the liquids
*
* @param liquids The liquids
* @param capacity Max capacity of smeltery, to calculate how much height one liquid takes up
* @param height Maximum height, basically represents how much height full capacity is
* @param min Minimum amount of height for a fluid. A fluid can never have less than this value height returned
* @return Array with heights corresponding to input-list liquids
*/
public static int[] calcLiquidHeights(List<FluidStack> liquids, int capacity, int height, int min) {
int fluidHeights[] = new int[liquids.size()];
if(liquids.size() > 0) {
for(int i = 0; i < liquids.size(); i++) {
FluidStack liquid = liquids.get(i);
float h = (float) liquid.amount / (float) capacity;
fluidHeights[i] = Math.max(min, (int) Math.ceil(h * (float) height));
}
// check if we have enough height to render everything, if not remove pixels from the tallest liquid
int sum = 0;
do {
sum = 0;
int biggest = -1;
int m = 0;
for(int i = 0; i < fluidHeights.length; i++) {
sum += fluidHeights[i];
if(fluidHeights[i] > biggest) {
biggest = fluidHeights[i];
m = i;
}
}
// we can't get a result without going negative
if(fluidHeights[m] == 0) {
break;
}
// remove a pixel from the biggest one
if(sum > height) {
fluidHeights[m]--;
}
} while(sum > height);
}
return fluidHeights;
}
}