Java tutorial
package buildcraftAdditions.compat.nei; import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.List; import org.lwjgl.opengl.GL11; import net.minecraft.block.Block; import net.minecraft.client.renderer.Tessellator; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; import net.minecraftforge.fluids.FluidContainerRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.fluids.IFluidContainerItem; import buildcraftAdditions.utils.RenderUtils; import codechicken.lib.gui.GuiDraw; import codechicken.nei.NEIClientConfig; import codechicken.nei.PositionedStack; import codechicken.nei.guihook.GuiContainerManager; import codechicken.nei.recipe.GuiCraftingRecipe; import codechicken.nei.recipe.GuiRecipe; import codechicken.nei.recipe.GuiUsageRecipe; import codechicken.nei.recipe.ICraftingHandler; import codechicken.nei.recipe.IUsageHandler; import codechicken.nei.recipe.TemplateRecipeHandler; /** * Copyright (c) 2014-2015, AEnterprise * http://buildcraftadditions.wordpress.com/ * Buildcraft Additions is distributed under the terms of GNU GPL v3.0 * Please check the contents of the license located in * http://buildcraftadditions.wordpress.com/wiki/licensing-stuff/ */ public abstract class RecipeHandlerBase extends TemplateRecipeHandler implements ICraftingHandler, IUsageHandler { public abstract String getRecipeID(); public String getRecipeSubName() { return null; } public void changeToGuiTexture() { GuiDraw.changeTexture(this.getGuiTexture()); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); } public void addTransferRect(int x, int y, int width, int height) { this.transferRects.add(new RecipeTransferRect(new Rectangle(x, y, width, height), this.getRecipeID())); } @Override public void drawForeground(int recipe) { super.drawForeground(recipe); this.drawFluidTanks(recipe); if (recipe % this.recipiesPerPage() == 0 && this.getRecipeSubName() != null) { GuiDraw.drawStringC(this.getRecipeSubName(), 83, -2, 0x404040, false); } this.changeToGuiTexture(); } @Override public void loadCraftingRecipes(String outputId, Object... results) { if (outputId.equals("liquid")) this.loadCraftingRecipes((FluidStack) results[0]); else if (outputId.equals(this.getRecipeID())) this.loadAllRecipes(); else super.loadCraftingRecipes(outputId, results); } public void loadAllRecipes() { } @Override public void loadCraftingRecipes(ItemStack result) { FluidStack fluid = getFluidStackFromItemStack(result); if (fluid != null) this.loadCraftingRecipes(fluid); } public void loadCraftingRecipes(FluidStack result) { } @Override public void loadUsageRecipes(String inputId, Object... ingredients) { if (inputId.equals("liquid")) this.loadUsageRecipes((FluidStack) ingredients[0]); else super.loadUsageRecipes(inputId, ingredients); } @Override public void loadUsageRecipes(ItemStack ingred) { FluidStack fluid = getFluidStackFromItemStack(ingred); if (fluid != null) this.loadUsageRecipes(fluid); } public void loadUsageRecipes(FluidStack ingredient) { } protected boolean transferFluidTank(GuiRecipe guiRecipe, int recipe, boolean usage) { CachedBaseRecipe crecipe = (CachedBaseRecipe) this.arecipes.get(recipe); Point mousepos = GuiDraw.getMousePosition(); Point offset = guiRecipe.getRecipePosition(recipe); Point relMouse = new Point(mousepos.x - (guiRecipe.width - 176) / 2 - offset.x, mousepos.y - (guiRecipe.height - 166) / 2 - offset.y); if (crecipe.getFluidTanks() != null) { for (PositionedFluidTank tank : crecipe.getFluidTanks()) { if (tank.position.contains(relMouse)) return tank.transfer(usage); } } return false; } public void drawFluidTanks(int recipe) { CachedBaseRecipe crecipe = (CachedBaseRecipe) this.arecipes.get(recipe); if (crecipe.getFluidTanks() != null) { crecipe.drawUpdate(); for (PositionedFluidTank fluidTank : crecipe.getFluidTanks()) fluidTank.draw(); } } @Override public List<String> handleTooltip(GuiRecipe guiRecipe, List<String> currenttip, int recipe) { super.handleTooltip(guiRecipe, currenttip, recipe); CachedBaseRecipe crecipe = (CachedBaseRecipe) this.arecipes.get(recipe); if (GuiContainerManager.shouldShowTooltip(guiRecipe)) { Point mouse = GuiDraw.getMousePosition(); Point offset = guiRecipe.getRecipePosition(recipe); Point relMouse = new Point(mouse.x - (guiRecipe.width - 176) / 2 - offset.x, mouse.y - (guiRecipe.height - 166) / 2 - offset.y); currenttip = this.provideTooltip(guiRecipe, currenttip, crecipe, relMouse); } return currenttip; } @Override public List<String> handleItemTooltip(GuiRecipe guiRecipe, ItemStack itemStack, List<String> currenttip, int recipe) { super.handleItemTooltip(guiRecipe, itemStack, currenttip, recipe); CachedBaseRecipe crecipe = (CachedBaseRecipe) this.arecipes.get(recipe); Point mouse = GuiDraw.getMousePosition(); Point offset = guiRecipe.getRecipePosition(recipe); Point relMouse = new Point(mouse.x - (guiRecipe.width - 176) / 2 - offset.x, mouse.y - (guiRecipe.height - 166) / 2 - offset.y); currenttip = this.provideItemTooltip(guiRecipe, itemStack, currenttip, crecipe, relMouse); return currenttip; } public List<String> provideTooltip(GuiRecipe guiRecipe, List<String> currenttip, CachedBaseRecipe crecipe, Point relMouse) { if (crecipe.getFluidTanks() != null) { for (PositionedFluidTank tank : crecipe.getFluidTanks()) { if (tank.position.contains(relMouse)) { tank.handleTooltip(currenttip); } } } return currenttip; } public List<String> provideItemTooltip(GuiRecipe guiRecipe, ItemStack itemStack, List<String> currenttip, CachedBaseRecipe crecipe, Point relMouse) { for (PositionedStack stack : crecipe.getIngredients()) { if (stack instanceof PositionedStackAdv && ((PositionedStackAdv) stack).getRect().contains(relMouse)) currenttip = ((PositionedStackAdv) stack).handleTooltip(guiRecipe, currenttip); } for (PositionedStack stack : crecipe.getOtherStacks()) { if (stack instanceof PositionedStackAdv && ((PositionedStackAdv) stack).getRect().contains(relMouse)) currenttip = ((PositionedStackAdv) stack).handleTooltip(guiRecipe, currenttip); } PositionedStack stack = crecipe.getResult(); if (stack instanceof PositionedStackAdv && ((PositionedStackAdv) stack).getRect().contains(relMouse)) currenttip = ((PositionedStackAdv) stack).handleTooltip(guiRecipe, currenttip); return currenttip; } @Override public boolean keyTyped(GuiRecipe gui, char keyChar, int keyCode, int recipe) { if (keyCode == NEIClientConfig.getKeyBinding("gui.recipe")) { if (this.transferFluidTank(gui, recipe, false)) return true; } else if (keyCode == NEIClientConfig.getKeyBinding("gui.usage")) { if (this.transferFluidTank(gui, recipe, true)) return true; } return super.keyTyped(gui, keyChar, keyCode, recipe); } @Override public boolean mouseClicked(GuiRecipe gui, int button, int recipe) { if (button == 0) { if (this.transferFluidTank(gui, recipe, false)) return true; } else if (button == 1) { if (this.transferFluidTank(gui, recipe, true)) return true; } return super.mouseClicked(gui, button, recipe); } public static FluidStack getFluidStackFromItemStack(ItemStack stack) { if (stack != null) { if (stack.getItem() instanceof IFluidContainerItem) { IFluidContainerItem ctr = (IFluidContainerItem) stack.getItem(); return ctr.getFluid(stack); } else if (FluidContainerRegistry.isFilledContainer(stack)) return FluidContainerRegistry.getFluidForFilledItem(stack); else if (stack.getItem() instanceof ItemBlock) { Block b = Block.getBlockFromItem(stack.getItem()); if (b != null && b instanceof IFluidBlock && ((IFluidBlock) b).getFluid() != null) return new FluidStack(((IFluidBlock) b).getFluid(), 1000); } } return null; } public abstract class CachedBaseRecipe extends CachedRecipe { public List<PositionedFluidTank> getFluidTanks() { List<PositionedFluidTank> tanks = new ArrayList<PositionedFluidTank>(); PositionedFluidTank tank = this.getFluidTank(); if (tank != null) tanks.add(tank); return tanks; } public PositionedFluidTank getFluidTank() { return null; } public void drawUpdate() { } } public class PositionedStackAdv extends PositionedStack { private List<String> tooltip = new ArrayList<String>(); public PositionedStackAdv(Object object, int x, int y) { super(object, x, y); } public PositionedStackAdv(Object object, int x, int y, List<String> tooltip) { super(object, x, y); this.addToTooltip(tooltip); } public Rectangle getRect() { return new Rectangle(this.relx - 1, this.rely - 1, 18, 18); } public List<String> handleTooltip(GuiRecipe guiRecipe, List<String> currenttip) { if (!this.tooltip.isEmpty()) { for (String tip : this.tooltip) currenttip.add(tip); } return currenttip; } public PositionedStackAdv addToTooltip(List<String> lines) { for (String tip : lines) this.tooltip.add(tip); return this; } public PositionedStackAdv addToTooltip(String line) { this.tooltip.add(line); return this; } } public class PositionedFluidTank { public FluidTank tank; public Rectangle position; public String overlayTexture; public Point overlayTexturePos; public boolean flowingTexture = false; public boolean showAmount = false; public boolean perTick = false; public PositionedFluidTank(FluidTank tank, Rectangle position, String overlayTexture, Point overlayTexturePos) { this.position = position; this.tank = tank; this.overlayTexture = overlayTexture; this.overlayTexturePos = overlayTexturePos; } public PositionedFluidTank(FluidTank tank, Rectangle position) { this(tank, position, null, null); } public PositionedFluidTank(FluidStack fluid, int capacity, Rectangle position, String overlayTexture, Point overlayTexturePos) { this(new FluidTank(fluid != null ? fluid.copy() : null, capacity), position, overlayTexture, overlayTexturePos); } public PositionedFluidTank(FluidStack fluid, int capacity, Rectangle position) { this(fluid, capacity, position, null, null); } public PositionedFluidTank setUseFlowingTexture(boolean useFlowingTexture) { this.flowingTexture = useFlowingTexture; return this; } public PositionedFluidTank setShowAmount(boolean showAmount) { this.showAmount = showAmount; return this; } public PositionedFluidTank setPerTick(boolean perTick) { this.perTick = perTick; return this; } public List<String> handleTooltip(List<String> currenttip) { if (this.tank == null || this.tank.getFluid() == null || this.tank.getFluid().getFluid() == null || this.tank.getFluid().amount <= 0) return currenttip; currenttip.add(this.tank.getFluid().getLocalizedName()); if (this.showAmount) currenttip.add(EnumChatFormatting.GRAY.toString() + this.tank.getFluid().amount + (this.perTick ? " mB/t" : " mB")); return currenttip; } public boolean transfer(boolean usage) { if (this.tank.getFluid() != null && this.tank.getFluid().amount > 0) { if (usage) { if (!GuiUsageRecipe.openRecipeGui("liquid", new Object[] { this.tank.getFluid() })) return false; } else { if (!GuiCraftingRecipe.openRecipeGui("liquid", new Object[] { this.tank.getFluid() })) return false; } return true; } return false; } public void draw() { if (this.tank == null || this.tank.getFluid() == null || this.tank.getFluid().getFluid() == null || this.tank.getFluid().amount <= 0) return; IIcon fluidIcon = null; if (this.flowingTexture && this.tank.getFluid().getFluid().getFlowingIcon() != null) fluidIcon = this.tank.getFluid().getFluid().getFlowingIcon(); else if (this.tank.getFluid().getFluid().getStillIcon() != null) fluidIcon = this.tank.getFluid().getFluid().getStillIcon(); else return; GuiDraw.changeTexture(RenderUtils.MC_BLOCK_SHEET); int color = this.tank.getFluid().getFluid().getColor(this.tank.getFluid()); GL11.glColor3ub((byte) (color >> 16 & 0xFF), (byte) (color >> 8 & 0xFF), (byte) (color & 0xFF)); GL11.glDisable(GL11.GL_BLEND); int amount = Math.max(Math.min(this.position.height, this.tank.getFluid().amount * this.position.height / this.tank.getCapacity()), 1); int posY = this.position.y + this.position.height - amount; for (int i = 0; i < this.position.width; i += 16) { for (int j = 0; j < amount; j += 16) { int drawWidth = Math.min(this.position.width - i, 16); int drawHeight = Math.min(amount - j, 16); int drawX = this.position.x + i; int drawY = posY + j; double minU = fluidIcon.getMinU(); double maxU = fluidIcon.getMaxU(); double minV = fluidIcon.getMinV(); double maxV = fluidIcon.getMaxV(); Tessellator tessellator = Tessellator.instance; tessellator.startDrawingQuads(); tessellator.addVertexWithUV(drawX, drawY + drawHeight, 0, minU, minV + (maxV - minV) * drawHeight / 16F); tessellator.addVertexWithUV(drawX + drawWidth, drawY + drawHeight, 0, minU + (maxU - minU) * drawWidth / 16F, minV + (maxV - minV) * drawHeight / 16F); tessellator.addVertexWithUV(drawX + drawWidth, drawY, 0, minU + (maxU - minU) * drawWidth / 16F, minV); tessellator.addVertexWithUV(drawX, drawY, 0, minU, minV); tessellator.draw(); } } GL11.glEnable(GL11.GL_BLEND); if (this.overlayTexture != null && this.overlayTexturePos != null) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); GuiDraw.changeTexture(this.overlayTexture); GuiDraw.drawTexturedModalRect(this.position.x, this.position.y, this.overlayTexturePos.x, this.overlayTexturePos.y, this.position.width, this.position.height); } } } }