diff --git a/src/main/java/codechicken/nei/PositionedStack.java b/src/main/java/codechicken/nei/PositionedStack.java index c892b424..5cbd657b 100644 --- a/src/main/java/codechicken/nei/PositionedStack.java +++ b/src/main/java/codechicken/nei/PositionedStack.java @@ -6,22 +6,18 @@ import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IIcon; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.oredict.OreDictionary; -import org.lwjgl.opengl.GL11; - import codechicken.nei.api.ItemFilter; import codechicken.nei.api.ItemInfo; import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.item.FluidDrawer; +import codechicken.nei.item.FluidDrawer.FillDirection; import codechicken.nei.recipe.Badge; import codechicken.nei.recipe.GuiRecipe; import codechicken.nei.recipe.StackInfo; @@ -255,7 +251,9 @@ public class PositionedStack implements Cloneable { public static class Fluid extends PositionedStack { /** The tank size the fill level is measured against, in mB. 0 means "always render full". */ - public int capacity = 0; + protected int capacity = 0; + protected boolean flowingTexture = false; + protected FillDirection fillDirection = FillDirection.AUTO; private ItemStack cachedFluidItem; private FluidStack cachedFluidStack; @@ -272,7 +270,34 @@ public class PositionedStack implements Cloneable { super(object, x, y, false); this.width = width; this.height = height; - this.capacity = capacity; + setCapacity(capacity); + } + + public int getCapacity() { + return this.capacity; + } + + public Fluid setCapacity(int capacity) { + this.capacity = Math.max(capacity, 0); + return this; + } + + public boolean hasFlowingTexture() { + return this.flowingTexture; + } + + public Fluid setFlowingTexture(boolean flowingTexture) { + this.flowingTexture = flowingTexture; + return this; + } + + public FillDirection getFillDirection() { + return this.fillDirection; + } + + public Fluid setFillDirection(FillDirection fillDirection) { + this.fillDirection = fillDirection == null ? FillDirection.AUTO : fillDirection; + return this; } protected FluidStack getFluidStack() { @@ -313,62 +338,15 @@ public class PositionedStack implements Cloneable { return; } - final int tankCapacity = this.capacity > 0 ? this.capacity : fluidStack.amount; - int fillHeight = tankCapacity > 0 - ? (int) ((long) this.height * Math.min(fluidStack.amount, tankCapacity) / tankCapacity) - : 0; - - if (fluidStack.amount > 0 && fillHeight <= 0) { - fillHeight = 1; - } - - if (fillHeight > 0) { - drawFluid(this.relx, this.rely, this.width, this.height, fillHeight, fluidStack); - } - } - - private static void drawFluid(int x, int y, int width, int height, int fillHeight, FluidStack fluidStack) { - final IIcon icon = fluidStack.getFluid().getIcon(fluidStack); - - if (icon == null) { - return; - } - - final int color = fluidStack.getFluid().getColor(fluidStack); - final float red = (color >> 16 & 0xFF) / 255F; - final float green = (color >> 8 & 0xFF) / 255F; - final float blue = (color & 0xFF) / 255F; - - Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - GL11.glColor4f(red, green, blue, 1F); - GL11.glEnable(GL11.GL_BLEND); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glDisable(GL11.GL_LIGHTING); - - final Tessellator tessellator = Tessellator.instance; - - tessellator.startDrawingQuads(); - for (int tx = 0; tx < width; tx += 16) { - final int tileWidth = Math.min(16, width - tx); - final double u2 = icon.getMinU() + (icon.getMaxU() - icon.getMinU()) * tileWidth / 16D; - - for (int ty = 0; ty < fillHeight; ty += 16) { - final int tileHeight = Math.min(16, fillHeight - ty); - final double v2 = icon.getMinV() + (icon.getMaxV() - icon.getMinV()) * tileHeight / 16D; - final int bottomY = y + height - ty; - final int topY = bottomY - tileHeight; - - tessellator.addVertexWithUV(x + tx, bottomY, 0, icon.getMinU(), v2); - tessellator.addVertexWithUV(x + tx + tileWidth, bottomY, 0, u2, v2); - tessellator.addVertexWithUV(x + tx + tileWidth, topY, 0, u2, icon.getMinV()); - tessellator.addVertexWithUV(x + tx, topY, 0, icon.getMinU(), icon.getMinV()); - } - } - tessellator.draw(); - - GL11.glDisable(GL11.GL_BLEND); - GL11.glEnable(GL11.GL_LIGHTING); - GL11.glColor4f(1F, 1F, 1F, 1F); + FluidDrawer.drawFluid( + this.relx, + this.rely, + this.width, + this.height, + this.capacity, + fluidStack, + this.flowingTexture, + this.fillDirection); } } } diff --git a/src/main/java/codechicken/nei/item/FluidDrawer.java b/src/main/java/codechicken/nei/item/FluidDrawer.java new file mode 100644 index 00000000..78886959 --- /dev/null +++ b/src/main/java/codechicken/nei/item/FluidDrawer.java @@ -0,0 +1,108 @@ +package codechicken.nei.item; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.IIcon; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; + +import org.lwjgl.opengl.GL11; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public class FluidDrawer { + + public enum FillDirection { + + AUTO, + UP, + DOWN, + LEFT, + RIGHT; + + public boolean isHorizontal() { + return this == LEFT || this == RIGHT; + } + + public FillDirection resolve(FluidStack fluidStack) { + if (this != AUTO) return this; + return fluidStack.getFluid().isGaseous(fluidStack) ? DOWN : UP; + } + } + + private FluidDrawer() {} + + public static void drawFluid(int x, int y, int width, int height, int capacity, FluidStack fluidStack, + boolean flowing, FillDirection direction) { + final Fluid fluid = fluidStack.getFluid(); + IIcon icon = flowing ? fluid.getFlowingIcon() : null; + + if (icon == null) { + icon = fluid.getIcon(fluidStack); + } + + if (icon == null || fluidStack.amount <= 0) { + return; + } + + direction = direction.resolve(fluidStack); + + final int tankSize = direction.isHorizontal() ? width : height; + final int tankCapacity = capacity > 0 ? capacity : fluidStack.amount; + final int fillSize = Math + .max(1, (int) ((long) tankSize * Math.min(fluidStack.amount, tankCapacity) / tankCapacity)); + + final int fillWidth = direction.isHorizontal() ? Math.min(fillSize, width) : width; + final int fillHeight = direction.isHorizontal() ? height : Math.min(fillSize, height); + final int fillX = direction == FillDirection.LEFT ? x + width - fillWidth : x; + final int fillY = direction == FillDirection.DOWN ? y : y + height - fillHeight; + final boolean anchorRight = direction == FillDirection.LEFT; + final boolean anchorBottom = direction != FillDirection.DOWN; + + final int color = fluid.getColor(fluidStack); + final float red = (color >> 16 & 0xFF) / 255F; + final float green = (color >> 8 & 0xFF) / 255F; + final float blue = (color & 0xFF) / 255F; + + Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + GL11.glColor3f(red, green, blue); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_LIGHTING); + + final Tessellator tessellator = Tessellator.instance; + + tessellator.startDrawingQuads(); + for (int tx = 0; tx < fillWidth; tx += 16) { + final int tileWidth = Math.min(16, fillWidth - tx); + // a cropped tile keeps the texture edge that stays seamless against the neighbouring tile + final double uSize = (icon.getMaxU() - icon.getMinU()) * tileWidth / 16D; + final double uMin = anchorRight ? icon.getMaxU() - uSize : icon.getMinU(); + final double uMax = anchorRight ? icon.getMaxU() : icon.getMinU() + uSize; + final int leftX = anchorRight ? fillX + fillWidth - tx - tileWidth : fillX + tx; + final int rightX = leftX + tileWidth; + + for (int ty = 0; ty < fillHeight; ty += 16) { + final int tileHeight = Math.min(16, fillHeight - ty); + final double vSize = (icon.getMaxV() - icon.getMinV()) * tileHeight / 16D; + final double vMin = anchorBottom ? icon.getMaxV() - vSize : icon.getMinV(); + final double vMax = anchorBottom ? icon.getMaxV() : icon.getMinV() + vSize; + final int bottomY = anchorBottom ? fillY + fillHeight - ty : fillY + ty + tileHeight; + final int topY = bottomY - tileHeight; + + tessellator.addVertexWithUV(leftX, bottomY, 0, uMin, vMax); + tessellator.addVertexWithUV(rightX, bottomY, 0, uMax, vMax); + tessellator.addVertexWithUV(rightX, topY, 0, uMax, vMin); + tessellator.addVertexWithUV(leftX, topY, 0, uMin, vMin); + } + } + tessellator.draw(); + + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glColor4f(1F, 1F, 1F, 1F); + } +} diff --git a/src/main/resources/assets/nei/csv/handlers.csv b/src/main/resources/assets/nei/csv/handlers.csv index 3595981e..ae04ae67 100644 --- a/src/main/resources/assets/nei/csv/handlers.csv +++ b/src/main/resources/assets/nei/csv/handlers.csv @@ -228,11 +228,11 @@ com.djgiannuzz.thaumcraftneiplugin.nei.recipehandler.InfusionRecipeHandler,Thaum ru.timeconqueror.tcneiadditions.nei.arcaneworkbench.ArcaneCraftingShapedHandler,Thaumcraft,Thaumcraft:blockTable:15,,Thaumcraft,TRUE,,4,138,,2,,,,,,, ru.timeconqueror.tcneiadditions.nei.AspectCombinationHandler,Thaumcraft,Thaumcraft:ItemResearchNotes,,Thaumcraft,TRUE,,,130,,2,,,,,,In sets of 5. Each one is ~30 height, ru.timeconqueror.tcneiadditions.nei.AspectFromItemStackHandler,Thaumcraft,Thaumcraft:ItemResearchNotes,,Thaumcraft,TRUE,,,140,,2,,,,,,, -tconstruct.plugins.nei.RecipeHandlerAlloying,Tinker's Construct,TConstruct:Smeltery,,TConstruct,TRUE,,,65,,5,,,,,,, -tconstruct.plugins.nei.RecipeHandlerCastingBasin,Tinker's Construct,TConstruct:SearedBlock:2,,TConstruct,TRUE,,,65,,5,,,,,,, -tconstruct.plugins.nei.RecipeHandlerCastingTable,Tinker's Construct,TConstruct:SearedBlock,,TConstruct,TRUE,,,65,,5,,,,,,, +tconstruct.plugins.nei.RecipeHandlerAlloying,Tinker's Construct,TConstruct:Smeltery,,TConstruct,TRUE,,3,63,,5,,,,,,, +tconstruct.plugins.nei.RecipeHandlerCastingBasin,Tinker's Construct,TConstruct:SearedBlock:2,,TConstruct,TRUE,,2,57,,5,,,,,,, +tconstruct.plugins.nei.RecipeHandlerCastingTable,Tinker's Construct,TConstruct:SearedBlock,,TConstruct,TRUE,,2,57,,5,,,,,,, tconstruct.plugins.nei.RecipeHandlerDryingRack,Tinker's Construct,TConstruct:Armor.DryingRack,,TConstruct,TRUE,,,55,,5,,,,,,, -tconstruct.plugins.nei.RecipeHandlerMelting,Tinker's Construct,TConstruct:LavaTank:2,,TConstruct,TRUE,,,65,,5,,,,,,, +tconstruct.plugins.nei.RecipeHandlerMelting,Tinker's Construct,TConstruct:LavaTank:2,,TConstruct,TRUE,,-1,60,,5,,,,,,, tconstruct.plugins.nei.RecipeHandlerToolMaterials,Tinker's Construct,TConstruct:ToolStationBlock,,TConstruct,TRUE,,,110,,3,,,,,,"Longer if more modifiers, I went through the whole list", net.p455w0rd.wirelesscraftingterminal.integration.modules.NEIHelpers.NEIAEShapedRecipeHandler,Wireless Crafting Terminal,ae2wct:wirelessCraftingTerminal,,ae2wct,TRUE,,,,,,,,,,,, alkalus.main.nei.NEI_Handler_Cauldron,Witchery,witchery:cauldron,,WitcheryExtras,TRUE,,,65,,5,,,,,,,