mirror of
https://github.com/GTNewHorizons/TinkersConstruct.git
synced 2026-11-13 00:47:32 +00:00
551 lines
19 KiB
Java
551 lines
19 KiB
Java
package tconstruct.tools.gui;
|
|
|
|
import java.awt.Rectangle;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
import net.minecraft.client.gui.GuiButton;
|
|
import net.minecraft.client.gui.GuiTextField;
|
|
import net.minecraft.client.gui.inventory.GuiContainer;
|
|
import net.minecraft.entity.player.InventoryPlayer;
|
|
import net.minecraft.inventory.IInventory;
|
|
import net.minecraft.inventory.Slot;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.tileentity.TileEntity;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraft.util.StatCollector;
|
|
import net.minecraft.world.World;
|
|
|
|
import org.lwjgl.opengl.GL11;
|
|
|
|
import codechicken.nei.VisiblityData;
|
|
import codechicken.nei.api.INEIGuiHandler;
|
|
import codechicken.nei.api.TaggedInventoryArea;
|
|
import cpw.mods.fml.common.Optional;
|
|
import tconstruct.TConstruct;
|
|
import tconstruct.library.TConstructRegistry;
|
|
import tconstruct.library.crafting.PatternBuilder;
|
|
import tconstruct.library.modifier.IModifyable;
|
|
import tconstruct.library.tools.ToolMaterial;
|
|
import tconstruct.library.util.HarvestLevels;
|
|
import tconstruct.tools.logic.CraftingStationLogic;
|
|
import tconstruct.util.network.CraftingStationDumpPacket;
|
|
|
|
@Optional.Interface(iface = "codechicken.nei.api.INEIGuiHandler", modid = "NotEnoughItems")
|
|
public class CraftingStationGui extends GuiContainer implements INEIGuiHandler {
|
|
|
|
/*
|
|
* Slider/slots related. Taken & adapted from Tinkers Construct 1.12 under the MIT License
|
|
*/
|
|
private static final ResourceLocation gui_inventory = new ResourceLocation("tinker", "textures/gui/generic.png");
|
|
|
|
public static final GuiElementScalable slotElement = new GuiElementScalable(7, 7, 18, 18, 64, 64);
|
|
public static final GuiElementScalable slotEmptyElement = new GuiElementScalable(7 + 18, 7, 18, 18, 64, 64);
|
|
|
|
private static final GuiElementDuex sliderNormal = new GuiElementDuex(7, 25, 10, 15, 64, 64);
|
|
private static final GuiElementDuex sliderLow = new GuiElementDuex(17, 25, 10, 15, 64, 64);
|
|
private static final GuiElementDuex sliderHigh = new GuiElementDuex(27, 25, 10, 15, 64, 64);
|
|
private static final GuiElementDuex sliderTop = new GuiElementDuex(43, 7, 12, 1, 64, 64);
|
|
private static final GuiElementDuex sliderBottom = new GuiElementDuex(43, 38, 12, 1, 64, 64);
|
|
private static final GuiElementScalable sliderBackground = new GuiElementScalable(43, 8, 12, 30, 64, 64);
|
|
private static final GuiElementScalable textBackground = new GuiElementScalable(7 + 18, 7, 18, 10, 64, 64);
|
|
|
|
private final GuiSliderWidget slider = new GuiSliderWidget(
|
|
sliderNormal,
|
|
sliderHigh,
|
|
sliderLow,
|
|
sliderTop,
|
|
sliderBottom,
|
|
sliderBackground);
|
|
private final GuiBorderWidget border = new GuiBorderWidget();
|
|
|
|
private int firstSlotId;
|
|
private int lastSlotId;
|
|
private int chestSlotCount;
|
|
|
|
/* end slider/slots */
|
|
|
|
private static final ResourceLocation background = new ResourceLocation("tinker", "textures/gui/tinkertable.png");
|
|
private static final ResourceLocation description = new ResourceLocation("tinker", "textures/gui/description.png");
|
|
private static final ResourceLocation icons = new ResourceLocation("tinker", "textures/gui/icons.png");
|
|
|
|
public boolean active;
|
|
|
|
// Panel positions
|
|
public String toolName;
|
|
public GuiTextField text;
|
|
public String title, body;
|
|
CraftingStationLogic logic;
|
|
|
|
private int craftingLeft = 0;
|
|
private int craftingTop = 0;
|
|
private int craftingTextLeft = 0;
|
|
private int descLeft = 0;
|
|
private int descTop = 0;
|
|
private int descTextLeft = 0;
|
|
|
|
private int chestLeft = 0;
|
|
private int chestTop = 0;
|
|
private int chestWidth = 0;
|
|
private int chestHeight = 0;
|
|
|
|
public CraftingStationGui(InventoryPlayer inventory, CraftingStationLogic logic, World world, int x, int y, int z) {
|
|
super(logic.getGuiContainer(inventory, world, x, y, z));
|
|
this.logic = logic;
|
|
|
|
title = "\u00A7n" + StatCollector.translateToLocal("gui.toolforge1");
|
|
body = StatCollector.translateToLocal("gui.toolforge2");
|
|
toolName = "";
|
|
}
|
|
|
|
@Override
|
|
public void initGui() {
|
|
super.initGui();
|
|
|
|
this.xSize = 176;
|
|
this.ySize = 166;
|
|
|
|
this.guiLeft = (this.width - this.xSize) / 2;
|
|
this.guiTop = (this.height - this.ySize) / 2;
|
|
|
|
this.craftingLeft = this.guiLeft;
|
|
this.craftingTop = this.guiTop;
|
|
|
|
if (logic.tinkerTable) {
|
|
this.descLeft = this.guiLeft + 176;
|
|
this.descTop = this.craftingTop;
|
|
}
|
|
|
|
if (logic.chest != null) {
|
|
updateChest();
|
|
} else {
|
|
slider.hide();
|
|
}
|
|
|
|
this.craftingTextLeft = this.craftingLeft - this.guiLeft;
|
|
this.descTextLeft = this.descLeft - this.guiLeft;
|
|
|
|
// Add dump button if chest is connected
|
|
this.buttonList.clear();
|
|
if (logic.chest != null) {
|
|
int bothOffset = 0;
|
|
if (logic.slotCount > 54) bothOffset += 12;
|
|
bothOffset += 122;
|
|
this.buttonList.add(new GuiButtonDump(0, this.guiLeft + bothOffset + 159, this.guiTop + 5));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void actionPerformed(GuiButton button) {
|
|
if (button.id == 0 && logic.chest != null) {
|
|
TConstruct.packetPipeline.sendToServer(new CraftingStationDumpPacket());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void drawGuiContainerForegroundLayer(int par1, int par2) {
|
|
if (logic.chest != null) {
|
|
if (logic.chest.get() instanceof TileEntity te) {
|
|
if (te.getWorldObj().getTileEntity(te.xCoord, te.yCoord, te.zCoord) == null
|
|
&& te.getWorldObj().isRemote) {
|
|
mc.thePlayer.closeScreen();
|
|
return;
|
|
}
|
|
}
|
|
this.fontRendererObj
|
|
.drawString(StatCollector.translateToLocal(logic.chest.get().getInventoryName()), 8, 6, 0x202020);
|
|
}
|
|
|
|
this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal(logic.tinkerTable ? "crafters.TinkerTable" : logic.getInvName()),
|
|
craftingTextLeft + 8,
|
|
6,
|
|
0x202020);
|
|
this.fontRendererObj
|
|
.drawString(StatCollector.translateToLocal("container.inventory"), craftingTextLeft + 8, 72, 0x202020);
|
|
|
|
if (logic.tinkerTable) {
|
|
if (logic.isStackInSlot(0)) // output slot = modified item
|
|
drawToolStats(logic.getStackInSlot(0));
|
|
else if (logic.isStackInSlot(5)) { // center slot if no output item
|
|
// other slots empty?
|
|
if (!logic.isStackInSlot(1) && !logic.isStackInSlot(2)
|
|
&& !logic.isStackInSlot(3)
|
|
&& !logic.isStackInSlot(4)
|
|
&& !logic.isStackInSlot(6)
|
|
&& !logic.isStackInSlot(7)
|
|
&& !logic.isStackInSlot(8)
|
|
&& !logic.isStackInSlot(9))
|
|
drawToolStats(logic.getStackInSlot(5));
|
|
else drawToolInformation();
|
|
} else drawToolInformation();
|
|
}
|
|
}
|
|
|
|
void drawToolStats(ItemStack stack) {
|
|
if (stack == null) return;
|
|
|
|
if (stack.getItem() instanceof IModifyable) ToolStationGuiHelper.drawToolStats(stack, descTextLeft + 10, 0);
|
|
|
|
int matID = PatternBuilder.instance.getPartID(stack);
|
|
|
|
if (matID != Short.MAX_VALUE && matID > 0) {
|
|
ToolMaterial material = TConstructRegistry.getMaterial(matID);
|
|
|
|
if (material != null) drawMaterialStats(material);
|
|
}
|
|
}
|
|
|
|
void drawToolInformation() {
|
|
int offsetX = descTextLeft + 63;
|
|
|
|
this.drawCenteredString(fontRendererObj, title, offsetX, 8, 0xffffff);
|
|
fontRendererObj.drawSplitString(body, offsetX - 56, 24, 115, 0xffffff);
|
|
}
|
|
|
|
protected void drawMaterialStats(ToolMaterial materialEnum) {
|
|
final int baseX = descTextLeft + 8;
|
|
final int baseY = 8;
|
|
|
|
String centerTitle = "\u00A7n" + materialEnum.localizedName();
|
|
|
|
drawCenteredString(this.fontRendererObj, centerTitle, baseX + 55, baseY, 16777215);
|
|
|
|
this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter4") + materialEnum.durability(),
|
|
baseX,
|
|
baseY + 16,
|
|
16777215);
|
|
this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter5") + materialEnum.handleDurability() + "x",
|
|
baseX,
|
|
baseY + 27,
|
|
16777215);
|
|
this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter6") + materialEnum.toolSpeed() / 100f,
|
|
baseX,
|
|
baseY + 38,
|
|
16777215);
|
|
this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter7")
|
|
+ HarvestLevels.getHarvestLevelName(materialEnum.harvestLevel()),
|
|
baseX,
|
|
baseY + 49,
|
|
16777215);
|
|
|
|
int attack = materialEnum.attack();
|
|
String heart = attack == 2 ? StatCollector.translateToLocal("gui.partcrafter8")
|
|
: StatCollector.translateToLocal("gui.partcrafter9");
|
|
if (attack % 2 == 0) this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter10") + attack / 2 + heart,
|
|
baseX,
|
|
baseY + 60,
|
|
0xffffff);
|
|
else this.fontRendererObj.drawString(
|
|
StatCollector.translateToLocal("gui.partcrafter10") + attack / 2f + heart,
|
|
baseX,
|
|
baseY + 60,
|
|
0xffffff);
|
|
}
|
|
|
|
@Override
|
|
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
|
|
|
|
// Draw the background
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
this.mc.getTextureManager().bindTexture(background);
|
|
this.drawTexturedModalRect(this.craftingLeft, this.craftingTop, 0, 0, 176, 166);
|
|
|
|
if (active) {
|
|
this.drawTexturedModalRect(this.craftingLeft + 62, this.craftingTop, 0, 166, 112, 22);
|
|
}
|
|
|
|
this.mc.getTextureManager().bindTexture(icons);
|
|
|
|
// Draw the slots
|
|
if (logic.tinkerTable && !logic.isStackInSlot(5))
|
|
this.drawTexturedModalRect(this.craftingLeft + 47, this.craftingTop + 33, 0, 233, 18, 18);
|
|
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
|
|
this.mc.getTextureManager().bindTexture(gui_inventory);
|
|
if (hasChest()) {
|
|
chestLeft += border.w;
|
|
chestTop += border.h;
|
|
|
|
border.draw();
|
|
|
|
int x = chestLeft;
|
|
int y = chestTop;
|
|
final int midW = chestWidth - border.w * 2;
|
|
|
|
if (shouldDrawName()) {
|
|
textBackground.drawScaledX(chestLeft, chestTop, midW);
|
|
y += textBackground.h;
|
|
}
|
|
|
|
drawChestSlots(x, y);
|
|
|
|
// slider
|
|
if (slider.isEnabled()) {
|
|
slider.update(mouseX, mouseY, !isMouseOverFullSlot(mouseX, mouseY) && isMouseInChest(mouseX, mouseY));
|
|
slider.draw();
|
|
|
|
updateChestSlots();
|
|
}
|
|
|
|
chestLeft -= border.w;
|
|
chestTop -= border.h;
|
|
}
|
|
// Draw description
|
|
if (logic.tinkerTable) {
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
this.mc.getTextureManager().bindTexture(description);
|
|
this.drawTexturedModalRect(this.descLeft, this.descTop, 0, 0, 126, 172);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) {
|
|
currentVisibility.showWidgets = width - xSize >= 107;
|
|
|
|
if (guiLeft < 58) {
|
|
currentVisibility.showStateButtons = false;
|
|
}
|
|
|
|
return currentVisibility;
|
|
}
|
|
|
|
@Override
|
|
public Iterable<Integer> getItemSpawnSlots(GuiContainer gui, ItemStack item) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
|
final int cw = (logic.chest != null ? chestWidth : 0);
|
|
if (logic.chest != null) {
|
|
final Rectangle blah = new Rectangle(x, y, w, h);
|
|
final Rectangle chestRectangle = new Rectangle(
|
|
chestLeft,
|
|
chestTop,
|
|
chestWidth,
|
|
chestHeight + (shouldDrawName() ? textBackground.y : 0) + (border.h * 2));
|
|
|
|
if (chestRectangle.intersects(blah)) return true;
|
|
}
|
|
|
|
if (y + h - 4 < guiTop || y + 4 > guiTop + ySize) return false;
|
|
|
|
return x - w - 4 >= guiLeft + cw && x + 4 <= guiLeft + xSize + cw + (logic.tinkerTable ? 126 : 0);
|
|
}
|
|
|
|
public boolean hasChest() {
|
|
return logic.chest != null;
|
|
}
|
|
|
|
public boolean isMouseInChest(int mouseX, int mouseY) {
|
|
final int xMod = (slider.isEnabled() ? slider.width : 0) + border.w;
|
|
final int yMod = (shouldDrawName() ? textBackground.y : 0) + (border.h * 2);
|
|
|
|
return mouseX >= (this.chestLeft - xMod) && mouseX < (chestLeft + chestWidth + xMod)
|
|
&& mouseY >= (this.chestTop - yMod)
|
|
&& mouseY < (chestTop + chestHeight + yMod);
|
|
}
|
|
|
|
public boolean isMouseOverFullSlot(int mouseX, int mouseY) {
|
|
for (final Slot slot : inventorySlots.inventorySlots) {
|
|
if (isMouseOverSlot(slot, mouseX, mouseY) && slot.getHasStack()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected boolean shouldDrawName() {
|
|
return this.logic.chest != null && this.logic.chest.get().getInventoryName() != null
|
|
&& !this.logic.chest.get().getInventoryName().isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public void func_146977_a /* drawSlot */(Slot slot) {
|
|
if (!slot.func_111238_b /* isEnabled */()) return;
|
|
|
|
super.func_146977_a(slot);
|
|
}
|
|
|
|
public boolean shouldDrawSlot(Slot slot) {
|
|
if (!(slot instanceof ChestSlot chestSlot)) return true;
|
|
|
|
// all visible
|
|
if (!slider.isEnabled()) return true;
|
|
|
|
return firstSlotId <= chestSlot.getVisualIndex() && lastSlotId > chestSlot.getVisualIndex();
|
|
}
|
|
|
|
@Override
|
|
public boolean isMouseOverSlot(Slot slotIn, int mouseX, int mouseY) {
|
|
return super.isMouseOverSlot(slotIn, mouseX, mouseY) && shouldDrawSlot(slotIn);
|
|
}
|
|
|
|
private int getDisplayedRows() {
|
|
return chestHeight / slotElement.h;
|
|
}
|
|
|
|
private int calcCappedYSize(int max) {
|
|
int h = slotElement.h * logic.invRows;
|
|
|
|
// not higher than the max
|
|
while (h > max) {
|
|
h -= slotElement.h;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
public int getChestWidth() {
|
|
return chestWidth;
|
|
}
|
|
|
|
// updatePosition
|
|
public void updateChest() {
|
|
chestHeight = calcCappedYSize(CraftingStationGui.slotElement.h * 10);
|
|
chestSlotCount = logic.slotCount;
|
|
|
|
// slider needed?
|
|
if (getDisplayedRows() < logic.invRows) {
|
|
slider.enable();
|
|
} else {
|
|
slider.disable();
|
|
}
|
|
|
|
chestWidth = logic.invColumns * CraftingStationGui.slotElement.w + 2 * border.w
|
|
+ (slider.isEnabled() ? slider.width : 0);
|
|
|
|
chestLeft = guiLeft - chestWidth;
|
|
chestTop = guiTop;
|
|
|
|
// Leaving out the xSize increase by chestSize and adjusting where it's used, because otherwise it shifts both
|
|
// the bookmarks and item panel
|
|
// way too far out. If anything (mouseClick, for example) relies on xSize, you'll need to hack it like below.
|
|
// xSize += guiLeft - chestLeft;
|
|
guiLeft = chestLeft;
|
|
|
|
border.setPosition(chestLeft, chestTop);
|
|
border.setSize(chestWidth, chestHeight + (shouldDrawName() ? textBackground.h : 0) + 2 * border.h);
|
|
|
|
slider.show();
|
|
slider.setPosition(
|
|
chestLeft + logic.invColumns * slotElement.w + border.w,
|
|
chestTop + (shouldDrawName() ? textBackground.h : 0) + border.h);
|
|
slider.setSize(chestHeight);
|
|
slider.setSliderParameters(0, logic.invRows - getDisplayedRows(), 1);
|
|
|
|
updateChestSlots();
|
|
}
|
|
|
|
@Override
|
|
protected void mouseClicked(int x, int y, int button) {
|
|
// Hacks
|
|
final int height = ySize;
|
|
|
|
if (logic.chest != null && x >= guiLeft && x <= guiLeft + chestWidth) {
|
|
ySize = border.height;
|
|
}
|
|
|
|
xSize += chestWidth;
|
|
super.mouseClicked(x, y, button);
|
|
xSize -= chestWidth;
|
|
ySize = height;
|
|
}
|
|
|
|
@Override
|
|
protected void mouseMovedOrUp(int x, int y, int button) {
|
|
// Hacks
|
|
final int height = ySize;
|
|
|
|
if (logic.chest != null && x >= guiLeft && x <= guiLeft + chestWidth) {
|
|
ySize = border.height;
|
|
}
|
|
|
|
xSize += chestWidth;
|
|
super.mouseMovedOrUp(x, y, button);
|
|
xSize -= chestWidth;
|
|
ySize = height;
|
|
}
|
|
|
|
// updates slot visibility
|
|
protected void updateChestSlots() {
|
|
if (!hasChest()) return;
|
|
|
|
final IInventory secondInventory = logic.getSecondInventory();
|
|
|
|
int xOffset = border.w;
|
|
int yOffset = border.h;
|
|
|
|
if (shouldDrawName()) {
|
|
yOffset += textBackground.h;
|
|
}
|
|
|
|
firstSlotId = slider.getValue() * logic.invColumns;
|
|
lastSlotId = Math.min(chestSlotCount, firstSlotId + getDisplayedRows() * logic.invColumns);
|
|
|
|
for (Object o : inventorySlots.inventorySlots) {
|
|
if (!(o instanceof ChestSlot slot)) continue;
|
|
|
|
if (shouldDrawSlot(slot)) {
|
|
slot.enable();
|
|
// calc position of the slot
|
|
final int offset = slot.getVisualIndex() - firstSlotId;
|
|
final int x = (offset % logic.invColumns) * CraftingStationGui.slotElement.w;
|
|
final int y = (offset / logic.invColumns) * CraftingStationGui.slotElement.h;
|
|
|
|
slot.xDisplayPosition = x + xOffset + 1 /*- this.chestWidth*/;
|
|
slot.yDisplayPosition = y + yOffset + 1;
|
|
} else {
|
|
slot.disable();
|
|
slot.xDisplayPosition = 0;
|
|
slot.yDisplayPosition = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// drawSlots
|
|
protected void drawChestSlots(int xPos, int yPos) {
|
|
if (!hasChest()) return;
|
|
|
|
int width = logic.invColumns * slotElement.w;
|
|
int height = chestHeight - border.h * 2;
|
|
|
|
int fullRows = (lastSlotId - firstSlotId) / logic.invColumns;
|
|
int slotsLeft = (lastSlotId - firstSlotId) % logic.invColumns;
|
|
|
|
int y; // We use it after the loop
|
|
for (y = 0; y < fullRows * slotElement.h && y < height; y += slotElement.h) {
|
|
slotElement.drawScaledX(xPos, yPos + y, width);
|
|
}
|
|
|
|
// draw partial row and unused slots
|
|
if (slotsLeft > 0) {
|
|
slotElement.drawScaledX(xPos, yPos + y, slotsLeft * slotElement.w);
|
|
// empty slots that don't exist
|
|
slotEmptyElement.drawScaledX(xPos + slotsLeft * slotElement.w, yPos + y, width - slotsLeft * slotElement.w);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Hide the deprecated stuff at the bottom
|
|
*/
|
|
@Deprecated
|
|
public static final int CHEST_WIDTH = 116;
|
|
}
|