aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api/gui')
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container.java740
-rw-r--r--src/main/java/gregtech/api/gui/GT_ContainerMetaTile_Machine.java244
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_1by1.java30
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_2by2.java33
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_3by3.java38
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_4by4.java45
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_BasicTank.java138
-rw-r--r--src/main/java/gregtech/api/gui/GT_Container_MultiMachine.java39
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIColorOverride.java92
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer.java99
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainerMetaTile_Machine.java271
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_1by1.java42
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_2by2.java42
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_3by3.java42
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_4by4.java42
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_BasicTank.java47
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIContainer_MultiMachine.java173
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUICover.java55
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIDialogSelectItem.java229
-rw-r--r--src/main/java/gregtech/api/gui/GT_GUIScreen.java327
-rw-r--r--src/main/java/gregtech/api/gui/GT_Slot_Armor.java30
-rw-r--r--src/main/java/gregtech/api/gui/GT_Slot_DataOrb.java19
-rw-r--r--src/main/java/gregtech/api/gui/GT_Slot_Holo.java77
-rw-r--r--src/main/java/gregtech/api/gui/GT_Slot_Output.java17
-rw-r--r--src/main/java/gregtech/api/gui/GT_Slot_Render.java24
-rw-r--r--src/main/java/gregtech/api/gui/GUIHost.java56
-rw-r--r--src/main/java/gregtech/api/gui/GUIProvider.java38
-rw-r--r--src/main/java/gregtech/api/gui/modularui/FallbackableSteamTexture.java89
-rw-r--r--src/main/java/gregtech/api/gui/modularui/GT_CoverUIBuildContext.java74
-rw-r--r--src/main/java/gregtech/api/gui/modularui/GT_UIInfos.java188
-rw-r--r--src/main/java/gregtech/api/gui/modularui/GT_UITextures.java488
-rw-r--r--src/main/java/gregtech/api/gui/modularui/GUITextureSet.java156
-rw-r--r--src/main/java/gregtech/api/gui/modularui/IDataFollowerWidget.java50
-rw-r--r--src/main/java/gregtech/api/gui/modularui/SteamTexture.java62
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_CoverTickRateButton.java82
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiCoverTabLine.java179
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiFakeItemButton.java162
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiIcon.java157
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiIconButton.java114
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java43
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiIntegerTextBox.java73
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiSlotTooltip.java24
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiSmartTooltip.java27
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiTab.java174
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiTabLine.java274
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiTooltip.java121
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_GuiTooltipManager.java80
-rw-r--r--src/main/java/gregtech/api/gui/widgets/GT_LockedWhileActiveButton.java90
48 files changed, 5736 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/gui/GT_Container.java b/src/main/java/gregtech/api/gui/GT_Container.java
new file mode 100644
index 0000000000..851e1f6461
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container.java
@@ -0,0 +1,740 @@
+package gregtech.api.gui;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.ICrafting;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.IFluidContainerItem;
+
+import gregtech.api.interfaces.IFluidAccess;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * The main Container class. It is used for all GregTech GUIs.
+ * <p>
+ * Never include this file in your mod - it will break your modpack.
+ */
+public class GT_Container extends Container {
+
+ public IGregTechTileEntity mTileEntity;
+ public InventoryPlayer mPlayerInventory;
+
+ public GT_Container(InventoryPlayer aPlayerInventory, IGregTechTileEntity aTileEntityInventory) {
+
+ mTileEntity = aTileEntityInventory;
+ mPlayerInventory = aPlayerInventory;
+ mTileEntity.openInventory();
+ }
+
+ /**
+ * To add the Slots to your GUI
+ */
+ public void addSlots(InventoryPlayer aPlayerInventory) {
+ //
+ }
+
+ /**
+ * Amount of regular Slots in the GUI (so, non-HoloSlots)
+ */
+ public int getSlotCount() {
+ return 0;
+ }
+
+ /**
+ * Amount of ALL Slots in the GUI including HoloSlots and ArmorSlots, but excluding regular Player Slots
+ */
+ protected final int getAllSlotCount() {
+ if (inventorySlots != null) {
+ if (doesBindPlayerInventory()) return inventorySlots.size() - 36;
+ return inventorySlots.size();
+ }
+ return getSlotCount();
+ }
+
+ /**
+ * Start-Index of the usable Slots (the first non-HoloSlot)
+ */
+ public int getSlotStartIndex() {
+ return 0;
+ }
+
+ public int getShiftClickStartIndex() {
+ return getSlotStartIndex();
+ }
+
+ /**
+ * Amount of Slots in the GUI the player can Shift-Click into. Uses also getSlotStartIndex
+ */
+ public int getShiftClickSlotCount() {
+ return 0;
+ }
+
+ /**
+ * Is Player-Inventory visible?
+ */
+ public boolean doesBindPlayerInventory() {
+ return true;
+ }
+
+ /**
+ * Override this Function with something like "return mTileEntity.isUseableByPlayer(aPlayer);"
+ */
+ @Override
+ public boolean canInteractWith(EntityPlayer aPlayer) {
+ return false;
+ }
+
+ protected void bindPlayerInventory(InventoryPlayer aInventoryPlayer) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 9; j++) {
+ addSlotToContainer(new Slot(aInventoryPlayer, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
+ }
+ }
+
+ for (int i = 0; i < 9; i++) {
+ addSlotToContainer(new Slot(aInventoryPlayer, i, 8 + i * 18, 142));
+ }
+ }
+
+ @Override
+ public ItemStack slotClick(int aSlotIndex, int aMouseclick, int aShifthold, EntityPlayer aPlayer) {
+ mTileEntity.markDirty();
+
+ if (aSlotIndex >= 0) {
+ if (inventorySlots.get(aSlotIndex) == null || inventorySlots.get(aSlotIndex) instanceof GT_Slot_Holo)
+ return null;
+ if (!(inventorySlots.get(aSlotIndex) instanceof GT_Slot_Armor)) if (aSlotIndex < getAllSlotCount())
+ if (aSlotIndex < getSlotStartIndex() || aSlotIndex >= getSlotStartIndex() + getSlotCount()) return null;
+ }
+
+ try {
+ return super.slotClick(aSlotIndex, aMouseclick, aShifthold, aPlayer);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+
+ // It looks like the rest of this code should ideally never be
+ // called, and might in fact never be called.
+
+ ItemStack rStack = null;
+ InventoryPlayer aPlayerInventory = aPlayer.inventory;
+ Slot aSlot;
+ ItemStack tTempStack;
+ int tTempStackSize;
+ ItemStack aHoldStack;
+
+ if ((aShifthold == 0 || aShifthold == 1) && (aMouseclick == 0 || aMouseclick == 1)) {
+ if (aSlotIndex == -999) {
+ if (aPlayerInventory.getItemStack() != null) {
+ if (aMouseclick == 0) {
+ aPlayer.dropPlayerItemWithRandomChoice(aPlayerInventory.getItemStack(), true);
+ aPlayerInventory.setItemStack(null);
+ }
+ if (aMouseclick == 1) {
+ aPlayer.dropPlayerItemWithRandomChoice(
+ aPlayerInventory.getItemStack()
+ .splitStack(1),
+ true);
+ if (aPlayerInventory.getItemStack().stackSize == 0) {
+ aPlayerInventory.setItemStack(null);
+ }
+ }
+ }
+ } else if (aShifthold == 1) {
+ aSlot = this.inventorySlots.get(aSlotIndex);
+ if (aSlot != null && aSlot.canTakeStack(aPlayer)) {
+ tTempStack = this.transferStackInSlot(aPlayer, aSlotIndex);
+ if (tTempStack != null) {
+ rStack = GT_Utility.copyOrNull(tTempStack);
+ if (aSlot.getStack() != null && aSlot.getStack()
+ .getItem() == tTempStack.getItem()) {
+ slotClick(aSlotIndex, aMouseclick, aShifthold, aPlayer);
+ }
+ }
+ }
+ } else {
+ if (aSlotIndex < 0) {
+ return null;
+ }
+ aSlot = this.inventorySlots.get(aSlotIndex);
+ if (aSlot != null) {
+ tTempStack = aSlot.getStack();
+ ItemStack mouseStack = aPlayerInventory.getItemStack();
+ if (tTempStack != null) {
+ rStack = GT_Utility.copyOrNull(tTempStack);
+ }
+ if (tTempStack == null) {
+ if (mouseStack != null && aSlot.isItemValid(mouseStack)) {
+ tTempStackSize = aMouseclick == 0 ? mouseStack.stackSize : 1;
+ if (tTempStackSize > aSlot.getSlotStackLimit()) {
+ tTempStackSize = aSlot.getSlotStackLimit();
+ }
+ aSlot.putStack(mouseStack.splitStack(tTempStackSize));
+
+ if (mouseStack.stackSize == 0) {
+ aPlayerInventory.setItemStack(null);
+ }
+ }
+ } else if (aSlot.canTakeStack(aPlayer)) {
+ if (mouseStack == null) {
+ tTempStackSize = aMouseclick == 0 ? tTempStack.stackSize : (tTempStack.stackSize + 1) / 2;
+ aHoldStack = aSlot.decrStackSize(tTempStackSize);
+ aPlayerInventory.setItemStack(aHoldStack);
+ if (tTempStack.stackSize == 0) {
+ aSlot.putStack(null);
+ }
+ aSlot.onPickupFromSlot(aPlayer, aPlayerInventory.getItemStack());
+ } else if (aSlot.isItemValid(mouseStack)) {
+ if (tTempStack.getItem() == mouseStack.getItem()
+ && tTempStack.getItemDamage() == mouseStack.getItemDamage()
+ && ItemStack.areItemStackTagsEqual(tTempStack, mouseStack)) {
+ tTempStackSize = aMouseclick == 0 ? mouseStack.stackSize : 1;
+ if (tTempStackSize > aSlot.getSlotStackLimit() - tTempStack.stackSize) {
+ tTempStackSize = aSlot.getSlotStackLimit() - tTempStack.stackSize;
+ }
+ if (tTempStackSize > mouseStack.getMaxStackSize() - tTempStack.stackSize) {
+ tTempStackSize = mouseStack.getMaxStackSize() - tTempStack.stackSize;
+ }
+ mouseStack.splitStack(tTempStackSize);
+ if (mouseStack.stackSize == 0) {
+ aPlayerInventory.setItemStack(null);
+ }
+ tTempStack.stackSize += tTempStackSize;
+ } else if (mouseStack.stackSize <= aSlot.getSlotStackLimit()) {
+ aSlot.putStack(mouseStack);
+ aPlayerInventory.setItemStack(tTempStack);
+ }
+ } else if (tTempStack.getItem() == mouseStack.getItem() && mouseStack.getMaxStackSize() > 1
+ && (!tTempStack.getHasSubtypes()
+ || tTempStack.getItemDamage() == mouseStack.getItemDamage())
+ && ItemStack.areItemStackTagsEqual(tTempStack, mouseStack)) {
+ tTempStackSize = tTempStack.stackSize;
+
+ if (tTempStackSize > 0
+ && tTempStackSize + mouseStack.stackSize <= mouseStack.getMaxStackSize()) {
+ mouseStack.stackSize += tTempStackSize;
+ tTempStack = aSlot.decrStackSize(tTempStackSize);
+
+ if (tTempStack.stackSize == 0) {
+ aSlot.putStack(null);
+ }
+
+ aSlot.onPickupFromSlot(aPlayer, aPlayerInventory.getItemStack());
+ }
+ }
+ }
+ aSlot.onSlotChanged();
+ }
+ }
+ // Did the player try to swap a slot with his hotbar using a
+ // number key from 1 to 9
+ // aMouseclick == 0 means number 1, aMouseclick == 8 means number 9
+ } else if (aShifthold == 2 && aMouseclick >= 0 && aMouseclick < 9) {
+ aSlot = this.inventorySlots.get(aSlotIndex);
+
+ if (aSlot.canTakeStack(aPlayer)) {
+ // get the stack at the specified hotbar slot.
+ tTempStack = aPlayerInventory.getStackInSlot(aMouseclick);
+ boolean canSwap = tTempStack == null
+ || aSlot.inventory == aPlayerInventory && aSlot.isItemValid(tTempStack);
+ tTempStackSize = -1;
+
+ if (!canSwap) {
+ tTempStackSize = aPlayerInventory.getFirstEmptyStack();
+ canSwap = tTempStackSize > -1;
+ }
+
+ if (canSwap && aSlot.getHasStack()) {
+ aHoldStack = aSlot.getStack();
+ aPlayerInventory.setInventorySlotContents(aMouseclick, aHoldStack);
+
+ if (tTempStack != null && (aSlot.inventory != aPlayerInventory || !aSlot.isItemValid(tTempStack))) {
+ if (tTempStackSize > -1) {
+ aPlayerInventory.addItemStackToInventory(tTempStack);
+ aSlot.decrStackSize(aHoldStack.stackSize);
+ aSlot.putStack(null);
+ aSlot.onPickupFromSlot(aPlayer, aHoldStack);
+ }
+ } else {
+ aSlot.decrStackSize(aHoldStack.stackSize);
+ aSlot.putStack(tTempStack);
+ aSlot.onPickupFromSlot(aPlayer, aHoldStack);
+ }
+ } else if (tTempStack != null && !aSlot.getHasStack() && aSlot.isItemValid(tTempStack)) {
+ aPlayerInventory.setInventorySlotContents(aMouseclick, null);
+ aSlot.putStack(tTempStack);
+ }
+ }
+ } else if (aShifthold == 3 && aPlayer.capabilities.isCreativeMode
+ && aPlayerInventory.getItemStack() == null
+ && aSlotIndex >= 0) {
+ aSlot = this.inventorySlots.get(aSlotIndex);
+ if (aSlot != null && aSlot.getHasStack()) {
+ tTempStack = GT_Utility.copyOrNull(aSlot.getStack());
+ tTempStack.stackSize = tTempStack.getMaxStackSize();
+ aPlayerInventory.setItemStack(tTempStack);
+ }
+ }
+ return rStack;
+ }
+
+ @Override
+ public ItemStack transferStackInSlot(EntityPlayer aPlayer, int aSlotIndex) {
+ ItemStack stack = null;
+ Slot slotObject = inventorySlots.get(aSlotIndex);
+
+ mTileEntity.markDirty();
+
+ // null checks and checks if the item can be stacked (maxStackSize > 1)
+ if (getSlotCount() > 0 && slotObject != null
+ && slotObject.getHasStack()
+ && !(slotObject instanceof GT_Slot_Holo)) {
+ ItemStack stackInSlot = slotObject.getStack();
+ stack = GT_Utility.copyOrNull(stackInSlot);
+
+ // TileEntity -> Player
+ if (aSlotIndex < getAllSlotCount()) {
+ if (doesBindPlayerInventory())
+ if (!mergeItemStack(stackInSlot, getAllSlotCount(), getAllSlotCount() + 36, true)) {
+ return null;
+ }
+ // Player -> TileEntity
+ } else if (!mergeItemStack(
+ stackInSlot,
+ getShiftClickStartIndex(),
+ getShiftClickStartIndex() + getShiftClickSlotCount(),
+ false)) {
+ return null;
+ }
+
+ if (stackInSlot.stackSize == 0) {
+ slotObject.putStack(null);
+ } else {
+ slotObject.onSlotChanged();
+ }
+ }
+ return stack;
+ }
+
+ /**
+ * merges provided ItemStack with the first avaliable one in the container/player inventory
+ */
+ @Override
+ protected boolean mergeItemStack(ItemStack aStack, int aStartIndex, int aSlotCount, boolean reverseOrder) {
+ boolean transferredStack = false;
+ int slotIndex = aStartIndex;
+
+ mTileEntity.markDirty();
+
+ if (reverseOrder) {
+ slotIndex = aSlotCount - 1;
+ }
+
+ Slot slot;
+ ItemStack itemStack;
+
+ if (aStack.isStackable()) {
+ while (aStack.stackSize > 0
+ && (!reverseOrder && slotIndex < aSlotCount || reverseOrder && slotIndex >= aStartIndex)) {
+ slot = this.inventorySlots.get(slotIndex);
+ itemStack = slot.getStack();
+ if (!(slot instanceof GT_Slot_Holo) && !(slot instanceof GT_Slot_Output)
+ && slot.isItemValid(aStack)
+ && itemStack != null
+ && itemStack.getItem() == aStack.getItem()
+ && (!aStack.getHasSubtypes() || aStack.getItemDamage() == itemStack.getItemDamage())
+ && ItemStack.areItemStackTagsEqual(aStack, itemStack)) {
+ int combinedStackSize = itemStack.stackSize + aStack.stackSize;
+ if (itemStack.stackSize < mTileEntity.getInventoryStackLimit()) {
+ if (combinedStackSize <= aStack.getMaxStackSize()) {
+ aStack.stackSize = 0;
+ itemStack.stackSize = combinedStackSize;
+ slot.onSlotChanged();
+ transferredStack = true;
+ } else if (itemStack.stackSize < aStack.getMaxStackSize()) {
+ aStack.stackSize -= aStack.getMaxStackSize() - itemStack.stackSize;
+ itemStack.stackSize = aStack.getMaxStackSize();
+ slot.onSlotChanged();
+ transferredStack = true;
+ }
+ }
+ }
+
+ if (reverseOrder) {
+ --slotIndex;
+ } else {
+ ++slotIndex;
+ }
+ }
+ }
+ if (aStack.stackSize > 0) {
+ if (reverseOrder) {
+ slotIndex = aSlotCount - 1;
+ } else {
+ slotIndex = aStartIndex;
+ }
+
+ while (!reverseOrder && slotIndex < aSlotCount || reverseOrder && slotIndex >= aStartIndex) {
+ slot = this.inventorySlots.get(slotIndex);
+ itemStack = slot.getStack();
+
+ if (slot.isItemValid(aStack) && itemStack == null) {
+ int quantityToTransfer = Math.min(aStack.stackSize, mTileEntity.getInventoryStackLimit());
+ slot.putStack(GT_Utility.copyAmount(quantityToTransfer, aStack));
+ slot.onSlotChanged();
+ aStack.stackSize -= quantityToTransfer;
+ transferredStack = true;
+ break;
+ }
+
+ if (reverseOrder) {
+ --slotIndex;
+ } else {
+ ++slotIndex;
+ }
+ }
+ }
+
+ return transferredStack;
+ }
+
+ @Override
+ protected Slot addSlotToContainer(Slot slot) {
+ try {
+ return super.addSlotToContainer(slot);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return slot;
+ }
+
+ @Override
+ public void addCraftingToCrafters(ICrafting player) {
+ try {
+ super.addCraftingToCrafters(player);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public List<ItemStack> getInventory() {
+ try {
+ return super.getInventory();
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return null;
+ }
+
+ @Override
+ public void removeCraftingFromCrafters(ICrafting player) {
+ try {
+ super.removeCraftingFromCrafters(player);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void detectAndSendChanges() {
+ try {
+ super.detectAndSendChanges();
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public boolean enchantItem(EntityPlayer player, int slotIndex) {
+ try {
+ return super.enchantItem(player, slotIndex);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return false;
+ }
+
+ @Override
+ public Slot getSlotFromInventory(IInventory inventory, int slotIndex) {
+ try {
+ return super.getSlotFromInventory(inventory, slotIndex);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return null;
+ }
+
+ @Override
+ public Slot getSlot(int slotIndex) {
+ try {
+ if (this.inventorySlots.size() > slotIndex) return super.getSlot(slotIndex);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean func_94530_a(ItemStack itemStack, Slot slot) {
+ try {
+ return super.func_94530_a(itemStack, slot);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return true;
+ }
+
+ @Override
+ protected void retrySlotClick(int slotIndex, int mouseButton, boolean aShifthold, EntityPlayer player) {
+ try {
+ super.retrySlotClick(slotIndex, mouseButton, aShifthold, player);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void onContainerClosed(EntityPlayer player) {
+ try {
+ super.onContainerClosed(player);
+ mTileEntity.closeInventory();
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void onCraftMatrixChanged(IInventory inventory) {
+ try {
+ super.onCraftMatrixChanged(inventory);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void putStackInSlot(int slotIndex, ItemStack itemStack) {
+ try {
+ super.putStackInSlot(slotIndex, itemStack);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void putStacksInSlots(ItemStack[] itemStacks) {
+ try {
+ super.putStacksInSlots(itemStacks);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public void updateProgressBar(int id, int value) {
+ try {
+ super.updateProgressBar(id, value);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public short getNextTransactionID(InventoryPlayer inventoryPlayer) {
+ try {
+ return super.getNextTransactionID(inventoryPlayer);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean isPlayerNotUsingContainer(EntityPlayer player) {
+ try {
+ return super.isPlayerNotUsingContainer(player);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return true;
+ }
+
+ @Override
+ public void setPlayerIsPresent(EntityPlayer player, boolean value) {
+ try {
+ super.setPlayerIsPresent(player, value);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ protected void func_94533_d() {
+ try {
+ super.func_94533_d();
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ @Override
+ public boolean canDragIntoSlot(Slot slot) {
+ try {
+ return super.canDragIntoSlot(slot);
+ } catch (Throwable e) {
+ e.printStackTrace(GT_Log.err);
+ }
+ return true;
+ }
+
+ protected static ItemStack handleFluidSlotClick(IFluidAccess aFluidAccess, EntityPlayer aPlayer,
+ boolean aProcessFullStack, boolean aCanDrain, boolean aCanFill) {
+ ItemStack tStackHeld = aPlayer.inventory.getItemStack();
+ ItemStack tStackSizedOne = GT_Utility.copyAmount(1, tStackHeld);
+ if (tStackSizedOne == null || tStackHeld.stackSize == 0) return null;
+ FluidStack tInputFluid = aFluidAccess.get();
+ FluidStack tFluidHeld = GT_Utility.getFluidForFilledItem(tStackSizedOne, true);
+ if (tFluidHeld != null && tFluidHeld.amount <= 0) tFluidHeld = null;
+ if (tInputFluid == null) {
+ // tank empty, consider fill only from now on
+ if (!aCanFill)
+ // cannot fill and nothing to take, bail out
+ return null;
+ if (tFluidHeld == null)
+ // no fluid to fill
+ return null;
+ return fillFluid(aFluidAccess, aPlayer, tFluidHeld, aProcessFullStack);
+ }
+ // tank not empty, both action possible
+ if (tFluidHeld != null && tInputFluid.amount < aFluidAccess.getCapacity()) {
+ // both nonnull and have space left for filling.
+ if (aCanFill)
+ // actually both pickup and fill is reasonable, but I'll go with fill here
+ return fillFluid(aFluidAccess, aPlayer, tFluidHeld, aProcessFullStack);
+ if (!aCanDrain)
+ // cannot take AND cannot fill, why make this call then?
+ return null;
+ // the slot does not allow filling, so try take some
+ return drainFluid(aFluidAccess, aPlayer, aProcessFullStack);
+ } else {
+ // cannot fill and there is something to take
+ if (!aCanDrain)
+ // but the slot does not allow taking, so bail out
+ return null;
+ return drainFluid(aFluidAccess, aPlayer, aProcessFullStack);
+ }
+ }
+
+ protected static ItemStack drainFluid(IFluidAccess aFluidAccess, EntityPlayer aPlayer, boolean aProcessFullStack) {
+ FluidStack tTankStack = aFluidAccess.get();
+ if (tTankStack == null) return null;
+ ItemStack tStackHeld = aPlayer.inventory.getItemStack();
+ ItemStack tStackSizedOne = GT_Utility.copyAmount(1, tStackHeld);
+ if (tStackSizedOne == null || tStackHeld.stackSize == 0) return null;
+ int tOriginalFluidAmount = tTankStack.amount;
+ ItemStack tFilledContainer = GT_Utility.fillFluidContainer(tTankStack, tStackSizedOne, true, false);
+ if (tFilledContainer == null && tStackSizedOne.getItem() instanceof IFluidContainerItem tContainerItem) {
+ int tFilledAmount = tContainerItem.fill(tStackSizedOne, tTankStack, true);
+ if (tFilledAmount > 0) {
+ tFilledContainer = tStackSizedOne;
+ tTankStack.amount -= tFilledAmount;
+ }
+ }
+ if (tFilledContainer != null) {
+ if (aProcessFullStack) {
+ int tFilledAmount = tOriginalFluidAmount - tTankStack.amount;
+ /*
+ * work out how many more items we can fill one cell is already used, so account for that the round down
+ * behavior will left over a fraction of a cell worth of fluid the user then get to decide what to do
+ * with it it will not be too fancy if it spills out partially filled cells
+ */
+ int tAdditionalParallel = Math.min(tStackHeld.stackSize - 1, tTankStack.amount / tFilledAmount);
+ tTankStack.amount -= tFilledAmount * tAdditionalParallel;
+ tFilledContainer.stackSize += tAdditionalParallel;
+ }
+ replaceCursorItemStack(aPlayer, tFilledContainer);
+ }
+ aFluidAccess.verifyFluidStack();
+ return tFilledContainer;
+ }
+
+ protected static ItemStack fillFluid(IFluidAccess aFluidAccess, EntityPlayer aPlayer, FluidStack aFluidHeld,
+ boolean aProcessFullStack) {
+ // we are not using aMachine.fill() here any more, so we need to check for fluid type here ourselves
+ if (aFluidAccess.get() != null && !aFluidAccess.get()
+ .isFluidEqual(aFluidHeld)) return null;
+ ItemStack tStackHeld = aPlayer.inventory.getItemStack();
+ ItemStack tStackSizedOne = GT_Utility.copyAmount(1, tStackHeld);
+ if (tStackSizedOne == null) return null;
+
+ int tFreeSpace = aFluidAccess.getCapacity() - (aFluidAccess.get() != null ? aFluidAccess.get().amount : 0);
+ if (tFreeSpace <= 0)
+ // no space left
+ return null;
+
+ // find out how much fluid can be taken
+ // some cells cannot be partially filled
+ ItemStack tStackEmptied = null;
+ int tAmountTaken = 0;
+ if (tFreeSpace >= aFluidHeld.amount) {
+ // fully accepted - try take it from item now
+ // IFluidContainerItem is intentionally not checked here. it will be checked later
+ tStackEmptied = GT_Utility.getContainerForFilledItem(tStackSizedOne, false);
+ tAmountTaken = aFluidHeld.amount;
+ }
+ if (tStackEmptied == null && tStackSizedOne.getItem() instanceof IFluidContainerItem container) {
+ // either partially accepted, or is IFluidContainerItem
+ FluidStack tDrained = container.drain(tStackSizedOne, tFreeSpace, true);
+ if (tDrained != null && tDrained.amount > 0) {
+ // something is actually drained - change the cell and drop it to player
+ tStackEmptied = tStackSizedOne;
+ tAmountTaken = tDrained.amount;
+ }
+ }
+ if (tStackEmptied == null)
+ // somehow the cell refuse to give out that amount of fluid, no op then
+ return null;
+
+ // find out how many fill can we do
+ // same round down behavior as above
+ // however here the fluid stack is not changed at all, so the exact code will slightly differ
+ int tParallel = aProcessFullStack ? Math.min(tFreeSpace / tAmountTaken, tStackHeld.stackSize) : 1;
+ if (aFluidAccess.get() == null) {
+ FluidStack tNewFillableStack = aFluidHeld.copy();
+ tNewFillableStack.amount = tAmountTaken * tParallel;
+ aFluidAccess.set(tNewFillableStack);
+ } else {
+ aFluidAccess.addAmount(tAmountTaken * tParallel);
+ }
+ tStackEmptied.stackSize = tParallel;
+ replaceCursorItemStack(aPlayer, tStackEmptied);
+ return tStackEmptied;
+ }
+
+ private static void replaceCursorItemStack(EntityPlayer aPlayer, ItemStack tStackResult) {
+ int tStackResultMaxStackSize = tStackResult.getMaxStackSize();
+ while (tStackResult.stackSize > tStackResultMaxStackSize) {
+ aPlayer.inventory.getItemStack().stackSize -= tStackResultMaxStackSize;
+ GT_Utility.addItemToPlayerInventory(aPlayer, tStackResult.splitStack(tStackResultMaxStackSize));
+ }
+ if (aPlayer.inventory.getItemStack().stackSize == tStackResult.stackSize) {
+ // every cell is mutated. it could just stay on the cursor.
+ aPlayer.inventory.setItemStack(tStackResult);
+ } else {
+ // some cells not mutated. The mutated cells must go into the inventory
+ // or drop into the world if there isn't enough space.
+ ItemStack tStackHeld = aPlayer.inventory.getItemStack();
+ tStackHeld.stackSize -= tStackResult.stackSize;
+ GT_Utility.addItemToPlayerInventory(aPlayer, tStackResult);
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_ContainerMetaTile_Machine.java b/src/main/java/gregtech/api/gui/GT_ContainerMetaTile_Machine.java
new file mode 100644
index 0000000000..a77f376e00
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_ContainerMetaTile_Machine.java
@@ -0,0 +1,244 @@
+package gregtech.api.gui;
+
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.ICrafting;
+import net.minecraft.item.ItemStack;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.interfaces.IConfigurationCircuitSupport;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * The Container I use for all my MetaTileEntities
+ */
+public class GT_ContainerMetaTile_Machine extends GT_Container {
+
+ public int mActive = 0, mMaxProgressTime = 0, mProgressTime = 0, mEnergy = 0, mSteam = 0, mSteamStorage = 0,
+ mStorage = 0, mOutput = 0, mInput = 0, mID = 0, mDisplayErrorCode = 0;
+ public long mEnergyLong = 0, mStorageLong = 0;
+ private int oActive = 0, oMaxProgressTime = 0, oProgressTime = 0, oEnergy = 0, oSteam = 0, oSteamStorage = 0,
+ oStorage = 0, oOutput = 0, oInput = 0, oID = 0, oDisplayErrorCode = 0;
+ private long oEnergyLong = 0, oStorageLong = 0;
+ protected int mTimer = 0;
+ protected Runnable circuitSlotClickCallback;
+
+ public GT_ContainerMetaTile_Machine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+
+ mTileEntity = aTileEntity;
+
+ if (mTileEntity != null && mTileEntity.getMetaTileEntity() != null) {
+ addSlots(aInventoryPlayer);
+ if (doesBindPlayerInventory()) bindPlayerInventory(aInventoryPlayer);
+ detectAndSendChanges();
+ } else {
+ aInventoryPlayer.player.openContainer = aInventoryPlayer.player.inventoryContainer;
+ }
+ }
+
+ public GT_ContainerMetaTile_Machine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity,
+ boolean doesBindInventory) {
+ super(aInventoryPlayer, aTileEntity);
+ mTileEntity = aTileEntity;
+
+ if (mTileEntity != null && mTileEntity.getMetaTileEntity() != null) {
+ addSlots(aInventoryPlayer);
+ if (doesBindPlayerInventory() && doesBindInventory) bindPlayerInventory(aInventoryPlayer);
+ detectAndSendChanges();
+ } else {
+ aInventoryPlayer.player.openContainer = aInventoryPlayer.player.inventoryContainer;
+ }
+ }
+
+ protected void addCircuitSlot() {
+ if (mTileEntity.getMetaTileEntity() instanceof IConfigurationCircuitSupport ccs) {
+ GT_Slot_Render slotCircuit = new GT_Slot_Render(
+ mTileEntity,
+ ccs.getCircuitSlot(),
+ ccs.getCircuitSlotX(),
+ ccs.getCircuitSlotY());
+ addSlotToContainer(slotCircuit);
+ slotCircuit.setEnabled(ccs.allowSelectCircuit());
+ }
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addCircuitSlot();
+ }
+
+ @Override
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+ if (mTileEntity.isClientSide() || mTileEntity.getMetaTileEntity() == null) return;
+ mStorage = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getEUCapacity());
+ mStorageLong = mTileEntity.getEUCapacity();
+ mEnergy = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getStoredEU());
+ mEnergyLong = mTileEntity.getStoredEU();
+ mSteamStorage = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getSteamCapacity());
+ mSteam = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getStoredSteam());
+ mOutput = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getOutputVoltage());
+ mInput = (int) Math.min(Integer.MAX_VALUE, mTileEntity.getInputVoltage());
+ mDisplayErrorCode = mTileEntity.getErrorDisplayID();
+ mProgressTime = mTileEntity.getProgress();
+ mMaxProgressTime = mTileEntity.getMaxProgress();
+ mActive = mTileEntity.isActive() ? 1 : 0;
+ mTimer++;
+
+ for (ICrafting player : this.crafters) {
+ if (mTimer % 500 == 10 || oEnergy != mEnergy) {
+ player.sendProgressBarUpdate(this, 0, mEnergy & 65535);
+ player.sendProgressBarUpdate(this, 1, mEnergy >>> 16);
+ }
+ if (mTimer % 500 == 10 || oStorage != mStorage) {
+ player.sendProgressBarUpdate(this, 2, mStorage & 65535);
+ player.sendProgressBarUpdate(this, 3, mStorage >>> 16);
+ }
+ if (mTimer % 500 == 10 || oOutput != mOutput) {
+ player.sendProgressBarUpdate(this, 4, mOutput);
+ }
+ if (mTimer % 500 == 10 || oInput != mInput) {
+ player.sendProgressBarUpdate(this, 5, mInput);
+ }
+ if (mTimer % 500 == 10 || oDisplayErrorCode != mDisplayErrorCode) {
+ player.sendProgressBarUpdate(this, 6, mDisplayErrorCode);
+ }
+ if (mTimer % 500 == 10 || oProgressTime != mProgressTime) {
+ player.sendProgressBarUpdate(this, 11, mProgressTime & 65535);
+ player.sendProgressBarUpdate(this, 12, mProgressTime >>> 16);
+ }
+ if (mTimer % 500 == 10 || oMaxProgressTime != mMaxProgressTime) {
+ player.sendProgressBarUpdate(this, 13, mMaxProgressTime & 65535);
+ player.sendProgressBarUpdate(this, 14, mMaxProgressTime >>> 16);
+ }
+ if (mTimer % 500 == 10 || oID != mID) {
+ player.sendProgressBarUpdate(this, 15, mID);
+ }
+ if (mTimer % 500 == 10 || oActive != mActive) {
+ player.sendProgressBarUpdate(this, 16, mActive);
+ }
+ if (mTimer % 500 == 10 || oSteam != mSteam) {
+ player.sendProgressBarUpdate(this, 17, mSteam & 65535);
+ player.sendProgressBarUpdate(this, 18, mSteam >>> 16);
+ }
+ if (mTimer % 500 == 10 || oSteamStorage != mSteamStorage) {
+ player.sendProgressBarUpdate(this, 19, mSteamStorage & 65535);
+ player.sendProgressBarUpdate(this, 20, mSteamStorage >>> 16);
+ }
+ if (mTimer % 500 == 10 || oEnergyLong != mEnergyLong) {
+ player.sendProgressBarUpdate(this, 21, (int) mEnergyLong);
+ player.sendProgressBarUpdate(this, 22, (int) (mEnergyLong >>> 32));
+ }
+ if (mTimer % 500 == 10 || oStorageLong != mStorageLong) {
+ player.sendProgressBarUpdate(this, 23, (int) mStorageLong);
+ player.sendProgressBarUpdate(this, 24, (int) (mStorageLong >>> 32));
+ }
+ }
+
+ oID = mID;
+ oSteam = mSteam;
+ oInput = mInput;
+ oActive = mActive;
+ oOutput = mOutput;
+ oEnergy = mEnergy;
+ oEnergyLong = mEnergyLong;
+ oStorage = mStorage;
+ oStorageLong = mStorageLong;
+ oSteamStorage = mSteamStorage;
+ oProgressTime = mProgressTime;
+ oMaxProgressTime = mMaxProgressTime;
+ oDisplayErrorCode = mDisplayErrorCode;
+ }
+
+ @SideOnly(Side.CLIENT)
+ @Override
+ public void updateProgressBar(int id, int value) {
+ super.updateProgressBar(id, value);
+ switch (id) {
+ case 0 -> mEnergy = mEnergy & 0xffff0000 | value & 0x0000ffff;
+ case 1 -> mEnergy = mEnergy & 0x0000ffff | value << 16;
+ case 2 -> mStorage = mStorage & 0xffff0000 | value & 0x0000ffff;
+ case 3 -> mStorage = mStorage & 0x0000ffff | value << 16;
+ case 4 -> mOutput = value;
+ case 5 -> mInput = value;
+ case 6 -> mDisplayErrorCode = value;
+ case 11 -> mProgressTime = mProgressTime & 0xffff0000 | value;
+ case 12 -> mProgressTime = mProgressTime & 0x0000ffff | value << 16;
+ case 13 -> mMaxProgressTime = mMaxProgressTime & 0xffff0000 | value & 0x0000ffff;
+ case 14 -> mMaxProgressTime = mMaxProgressTime & 0x0000ffff | value << 16;
+ case 15 -> mID = value;
+ case 16 -> mActive = value;
+ case 17 -> mSteam = mSteam & 0xffff0000 | value & 0x0000ffff;
+ case 18 -> mSteam = mSteam & 0x0000ffff | value << 16;
+ case 19 -> mSteamStorage = mSteamStorage & 0xffff0000 | value & 0x0000ffff;
+ case 20 -> mSteamStorage = mSteamStorage & 0x0000ffff | value << 16;
+ case 21 -> mEnergyLong = mEnergyLong & 0xffffffff00000000L | value & 0x00000000ffffffffL;
+ case 22 -> mEnergyLong = mEnergyLong & 0x00000000ffffffffL | (long) value << 32;
+ case 23 -> mStorageLong = mStorageLong & 0xffffffff00000000L | value & 0x00000000ffffffffL;
+ case 24 -> mStorageLong = mStorageLong & 0x00000000ffffffffL | (long) value << 32;
+ }
+ }
+
+ @Override
+ public boolean canInteractWith(EntityPlayer player) {
+ return mTileEntity.isUseableByPlayer(player);
+ }
+
+ @Deprecated
+ public String trans(String aKey, String aEnglish) {
+ return GT_Utility.trans(aKey, aEnglish);
+ }
+
+ public void setCircuitSlotClickCallback(Runnable circuitSlotClickCallback) {
+ this.circuitSlotClickCallback = circuitSlotClickCallback;
+ }
+
+ @Override
+ public ItemStack slotClick(int aSlotNumber, int aMouseclick, int aShifthold, EntityPlayer aPlayer) {
+ if (mTileEntity.getMetaTileEntity() instanceof IConfigurationCircuitSupport) {
+ IMetaTileEntity machine = mTileEntity.getMetaTileEntity();
+ IConfigurationCircuitSupport ccs = (IConfigurationCircuitSupport) machine;
+ if (ccs.allowSelectCircuit() && aSlotNumber == ccs.getCircuitGUISlot() && aMouseclick < 2) {
+ ItemStack newCircuit;
+ if (aShifthold == 1) {
+ if (aMouseclick == 0) {
+ if (circuitSlotClickCallback != null) circuitSlotClickCallback.run();
+ return null;
+ } else {
+ // clear
+ newCircuit = null;
+ }
+ } else {
+ ItemStack cursorStack = aPlayer.inventory.getItemStack();
+ List<ItemStack> tCircuits = ccs.getConfigurationCircuits();
+ int index = GT_Utility.findMatchingStackInList(tCircuits, cursorStack);
+ if (index < 0) {
+ int curIndex = GT_Utility
+ .findMatchingStackInList(tCircuits, machine.getStackInSlot(ccs.getCircuitSlot())) + 1;
+ if (aMouseclick == 0) {
+ curIndex += 1;
+ } else {
+ curIndex -= 1;
+ }
+ curIndex = Math.floorMod(curIndex, tCircuits.size() + 1) - 1;
+ newCircuit = curIndex < 0 ? null : tCircuits.get(curIndex);
+ } else {
+ // set to whatever it is
+ newCircuit = tCircuits.get(index);
+ }
+ }
+ mTileEntity.setInventorySlotContents(ccs.getCircuitSlot(), newCircuit);
+ return newCircuit;
+ }
+ }
+ return super.slotClick(aSlotNumber, aMouseclick, aShifthold, aPlayer);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_1by1.java b/src/main/java/gregtech/api/gui/GT_Container_1by1.java
new file mode 100644
index 0000000000..06efaee5ef
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_1by1.java
@@ -0,0 +1,30 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_Container_1by1 extends GT_ContainerMetaTile_Machine {
+
+ public GT_Container_1by1(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 0, 80, 35));
+ super.addSlots(aInventoryPlayer);
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 1;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_2by2.java b/src/main/java/gregtech/api/gui/GT_Container_2by2.java
new file mode 100644
index 0000000000..4e3584a0a6
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_2by2.java
@@ -0,0 +1,33 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_Container_2by2 extends GT_ContainerMetaTile_Machine {
+
+ public GT_Container_2by2(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 0, 71, 26));
+ addSlotToContainer(new Slot(mTileEntity, 1, 89, 26));
+ addSlotToContainer(new Slot(mTileEntity, 2, 71, 44));
+ addSlotToContainer(new Slot(mTileEntity, 3, 89, 44));
+ super.addSlots(aInventoryPlayer);
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 4;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 4;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_3by3.java b/src/main/java/gregtech/api/gui/GT_Container_3by3.java
new file mode 100644
index 0000000000..4c0f7f946b
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_3by3.java
@@ -0,0 +1,38 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_Container_3by3 extends GT_ContainerMetaTile_Machine {
+
+ public GT_Container_3by3(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 0, 62, 17));
+ addSlotToContainer(new Slot(mTileEntity, 1, 80, 17));
+ addSlotToContainer(new Slot(mTileEntity, 2, 98, 17));
+ addSlotToContainer(new Slot(mTileEntity, 3, 62, 35));
+ addSlotToContainer(new Slot(mTileEntity, 4, 80, 35));
+ addSlotToContainer(new Slot(mTileEntity, 5, 98, 35));
+ addSlotToContainer(new Slot(mTileEntity, 6, 62, 53));
+ addSlotToContainer(new Slot(mTileEntity, 7, 80, 53));
+ addSlotToContainer(new Slot(mTileEntity, 8, 98, 53));
+ super.addSlots(aInventoryPlayer);
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 9;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 9;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_4by4.java b/src/main/java/gregtech/api/gui/GT_Container_4by4.java
new file mode 100644
index 0000000000..db5cde4cfe
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_4by4.java
@@ -0,0 +1,45 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_Container_4by4 extends GT_ContainerMetaTile_Machine {
+
+ public GT_Container_4by4(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 0, 53, 8));
+ addSlotToContainer(new Slot(mTileEntity, 1, 71, 8));
+ addSlotToContainer(new Slot(mTileEntity, 2, 89, 8));
+ addSlotToContainer(new Slot(mTileEntity, 3, 107, 8));
+ addSlotToContainer(new Slot(mTileEntity, 4, 53, 26));
+ addSlotToContainer(new Slot(mTileEntity, 5, 71, 26));
+ addSlotToContainer(new Slot(mTileEntity, 6, 89, 26));
+ addSlotToContainer(new Slot(mTileEntity, 7, 107, 26));
+ addSlotToContainer(new Slot(mTileEntity, 8, 53, 44));
+ addSlotToContainer(new Slot(mTileEntity, 9, 71, 44));
+ addSlotToContainer(new Slot(mTileEntity, 10, 89, 44));
+ addSlotToContainer(new Slot(mTileEntity, 11, 107, 44));
+ addSlotToContainer(new Slot(mTileEntity, 12, 53, 62));
+ addSlotToContainer(new Slot(mTileEntity, 13, 71, 62));
+ addSlotToContainer(new Slot(mTileEntity, 14, 89, 62));
+ addSlotToContainer(new Slot(mTileEntity, 15, 107, 62));
+ super.addSlots(aInventoryPlayer);
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 16;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 16;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_BasicTank.java b/src/main/java/gregtech/api/gui/GT_Container_BasicTank.java
new file mode 100644
index 0000000000..403de4bab5
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_BasicTank.java
@@ -0,0 +1,138 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.ICrafting;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.interfaces.IFluidAccess;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * The Container I use for all my Basic Tanks
+ */
+public class GT_Container_BasicTank extends GT_ContainerMetaTile_Machine {
+
+ public int mContent = 0;
+ protected int oContent = 0;
+
+ public GT_Container_BasicTank(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ /**
+ * Subclasses must ensure third slot (aSlotIndex==2) is drainable fluid display item slot. Otherwise, subclasses
+ * must intercept the appropriate the slotClick event and call super.slotClick(2, xxx) if necessary
+ */
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 0, 80, 17));
+ addSlotToContainer(new GT_Slot_Output(mTileEntity, 1, 80, 53));
+ addSlotToContainer(new GT_Slot_Render(mTileEntity, 2, 59, 42));
+ }
+
+ @Override
+ public ItemStack slotClick(int aSlotIndex, int aMouseclick, int aShifthold, EntityPlayer aPlayer) {
+ if (aSlotIndex == 2 && aMouseclick < 2) {
+ GT_MetaTileEntity_BasicTank tTank = (GT_MetaTileEntity_BasicTank) mTileEntity.getMetaTileEntity();
+ if (mTileEntity.isClientSide()) {
+ /*
+ * While a logical client don't really need to process fluid cells upon click (it could have just wait
+ * for server side to send the result), doing so would result in every fluid interaction having a
+ * noticeable delay between clicking and changes happening even on single player. I'd imagine this lag
+ * to become only more severe when playing MP over ethernet, which would have much more latency than a
+ * memory connection
+ */
+ Slot slot = inventorySlots.get(aSlotIndex);
+ tTank.setDrainableStack(GT_Utility.getFluidFromDisplayStack(slot.getStack()));
+ }
+ IFluidAccess tDrainableAccess = constructFluidAccess(tTank, false);
+ return handleFluidSlotClick(
+ tDrainableAccess,
+ aPlayer,
+ aMouseclick == 0,
+ true,
+ !tTank.isDrainableStackSeparate());
+ }
+ return super.slotClick(aSlotIndex, aMouseclick, aShifthold, aPlayer);
+ }
+
+ @Override
+ public void detectAndSendChanges() {
+ super.detectAndSendChanges();
+ if (mTileEntity.isClientSide() || mTileEntity.getMetaTileEntity() == null) return;
+ if (((GT_MetaTileEntity_BasicTank) mTileEntity.getMetaTileEntity()).mFluid != null)
+ mContent = ((GT_MetaTileEntity_BasicTank) mTileEntity.getMetaTileEntity()).mFluid.amount;
+ else mContent = 0;
+ sendProgressBar();
+ oContent = mContent;
+ }
+
+ public void sendProgressBar() {
+ for (ICrafting player : this.crafters) {
+ if (mTimer % 500 == 0 || oContent != mContent) {
+ player.sendProgressBarUpdate(this, 100, mContent & 65535);
+ player.sendProgressBarUpdate(this, 101, mContent >>> 16);
+ }
+ }
+ }
+
+ @Override
+ @SideOnly(Side.CLIENT)
+ public void updateProgressBar(int id, int value) {
+ super.updateProgressBar(id, value);
+ switch (id) {
+ case 100 -> mContent = mContent & 0xffff0000 | value & 0x0000ffff;
+ case 101 -> mContent = mContent & 0xffff | value << 16;
+ }
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 2;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 1;
+ }
+
+ protected IFluidAccess constructFluidAccess(GT_MetaTileEntity_BasicTank aTank, boolean aIsFillableStack) {
+ return new BasicTankFluidAccess(aTank, aIsFillableStack);
+ }
+
+ static class BasicTankFluidAccess implements IFluidAccess {
+
+ protected final GT_MetaTileEntity_BasicTank mTank;
+ protected final boolean mIsFillableStack;
+
+ public BasicTankFluidAccess(GT_MetaTileEntity_BasicTank aTank, boolean aIsFillableStack) {
+ this.mTank = aTank;
+ this.mIsFillableStack = aIsFillableStack;
+ }
+
+ @Override
+ public void set(FluidStack stack) {
+ if (mIsFillableStack) mTank.setFillableStack(stack);
+ else mTank.setDrainableStack(stack);
+ }
+
+ @Override
+ public FluidStack get() {
+ return mIsFillableStack ? mTank.getFillableStack() : mTank.getDrainableStack();
+ }
+
+ @Override
+ public int getCapacity() {
+ return mTank.getCapacity();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Container_MultiMachine.java b/src/main/java/gregtech/api/gui/GT_Container_MultiMachine.java
new file mode 100644
index 0000000000..142b84e008
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Container_MultiMachine.java
@@ -0,0 +1,39 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * The Container I use for all my Basic Machines
+ */
+@Deprecated
+public class GT_Container_MultiMachine extends GT_ContainerMetaTile_Machine {
+
+ public GT_Container_MultiMachine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity) {
+ super(aInventoryPlayer, aTileEntity);
+ }
+
+ public GT_Container_MultiMachine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity,
+ boolean bindInventory) {
+ super(aInventoryPlayer, aTileEntity, bindInventory);
+ }
+
+ @Override
+ public void addSlots(InventoryPlayer aInventoryPlayer) {
+ addSlotToContainer(new Slot(mTileEntity, 1, 152, 5));
+ }
+
+ @Override
+ public int getSlotCount() {
+ return 1;
+ }
+
+ @Override
+ public int getShiftClickSlotCount() {
+ return 1;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIColorOverride.java b/src/main/java/gregtech/api/gui/GT_GUIColorOverride.java
new file mode 100644
index 0000000000..304e792a2a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIColorOverride.java
@@ -0,0 +1,92 @@
+package gregtech.api.gui;
+
+import java.util.concurrent.ExecutionException;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.resources.IResource;
+import net.minecraft.util.ResourceLocation;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+import cpw.mods.fml.relauncher.FMLLaunchHandler;
+import cpw.mods.fml.relauncher.Side;
+import gregtech.api.GregTech_API;
+import gregtech.api.util.ColorsMetadataSection;
+
+public class GT_GUIColorOverride {
+
+ private static final Object NOT_FOUND = new Object();
+ private static final LoadingCache<ResourceLocation, Object> cache = CacheBuilder.newBuilder()
+ .softValues()
+ .build(new CacheLoader<>() {
+
+ @Override
+ public Object load(@Nonnull ResourceLocation key) throws Exception {
+ IResource ir = Minecraft.getMinecraft()
+ .getResourceManager()
+ .getResource(key);
+ if (ir.hasMetadata()) return ir.getMetadata("colors");
+ // return a dummy
+ // object because
+ // LoadingCache
+ // doesn't like null
+ return NOT_FOUND;
+ }
+ });
+ private static final GT_GUIColorOverride FALLBACK = new GT_GUIColorOverride();
+ private ColorsMetadataSection cmSection;
+
+ public static GT_GUIColorOverride get(String fullLocation) {
+ // see other get for more info
+ if (FMLLaunchHandler.side() != Side.CLIENT) return FALLBACK;
+ return new GT_GUIColorOverride(new ResourceLocation(fullLocation));
+ }
+
+ public static GT_GUIColorOverride get(ResourceLocation path) {
+ // use dummy fallback if there isn't such thing as a resource pack.
+ // #side() usually has two possible return value, but since this might be called by test code, it might
+ // also return null when in test env. Using #isClient will cause a NPE. A plain inequality test won't.
+ // FMLCommonHandler's #getSide() might trigger a NPE when in test env, so no.
+ if (FMLLaunchHandler.side() != Side.CLIENT) return FALLBACK;
+ return new GT_GUIColorOverride(path);
+ }
+
+ private GT_GUIColorOverride() {
+ cmSection = null;
+ }
+
+ private GT_GUIColorOverride(ResourceLocation resourceLocation) {
+ try {
+ Object metadata = cache.get(resourceLocation);
+ if (metadata != NOT_FOUND) cmSection = (ColorsMetadataSection) metadata;
+ } catch (ExecutionException | UncheckedExecutionException ignore) {
+ // make sure it doesn't cache a failing entry
+ cache.invalidate(resourceLocation);
+ }
+ }
+
+ public int getTextColorOrDefault(String textType, int defaultColor) {
+ return sLoaded() ? cmSection.getTextColorOrDefault(textType, defaultColor) : defaultColor;
+ }
+
+ public int getGuiTintOrDefault(String key, int defaultColor) {
+ return sLoaded() ? cmSection.getGuiTintOrDefault(key, defaultColor) : defaultColor;
+ }
+
+ public boolean sGuiTintingEnabled() {
+ return sLoaded() ? cmSection.sGuiTintingEnabled() : GregTech_API.sColoredGUI;
+ }
+
+ public boolean sLoaded() {
+ return cmSection != null;
+ }
+
+ public static void onResourceManagerReload() {
+ cache.invalidateAll();
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer.java b/src/main/java/gregtech/api/gui/GT_GUIContainer.java
new file mode 100644
index 0000000000..639bd56162
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer.java
@@ -0,0 +1,99 @@
+package gregtech.api.gui;
+
+import static gregtech.GT_Mod.GT_FML_LOGGER;
+
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.Slot;
+import net.minecraft.util.ResourceLocation;
+
+import org.lwjgl.input.Mouse;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * Main GUI-Container-Class which basically contains the Code needed to prevent crashes from improperly Coded Items.
+ */
+public class GT_GUIContainer extends GuiContainer {
+
+ public boolean mCrashed = false;
+
+ public ResourceLocation mGUIbackground;
+
+ public GT_GUIColorOverride colorOverride;
+
+ public String mGUIbackgroundPath;
+
+ public GT_GUIContainer(Container aContainer, String aGUIbackground) {
+ super(aContainer);
+ mGUIbackground = new ResourceLocation(mGUIbackgroundPath = aGUIbackground);
+ colorOverride = GT_GUIColorOverride.get(aGUIbackground);
+ }
+
+ protected int getTextColorOrDefault(String textType, int defaultColor) {
+ return colorOverride.getTextColorOrDefault(textType, defaultColor);
+ }
+
+ public int getLeft() {
+ return guiLeft;
+ }
+
+ public int getTop() {
+ return guiTop;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ //
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ mc.renderEngine.bindTexture(mGUIbackground);
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float parTicks) {
+ try {
+ super.drawScreen(mouseX, mouseY, parTicks);
+ } catch (Throwable e) {
+ try {
+ Tessellator.instance.draw();
+ } catch (Throwable f) {
+ //
+ }
+ }
+ }
+
+ @Override
+ public void handleMouseInput() {
+ int delta = Mouse.getEventDWheel();
+ if (delta != 0) {
+ int i = Mouse.getEventX() * this.width / this.mc.displayWidth;
+ int j = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
+ onMouseWheel(i, j, delta);
+ }
+ super.handleMouseInput();
+ }
+
+ protected void onMouseWheel(int mx, int my, int delta) {}
+
+ public boolean isMouseOverSlot(int slotIndex, int mx, int my) {
+ int size = inventorySlots.inventorySlots.size();
+ if (slotIndex < 0 || slotIndex >= size) {
+ // slot does not exist somehow. log and carry on
+ GT_FML_LOGGER.error("Slot {} required where only {} is present", slotIndex, size);
+ return false;
+ }
+ Slot slot = inventorySlots.getSlot(slotIndex);
+ return this.func_146978_c(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mx, my);
+ }
+
+ /*
+ * @Override protected void drawSlotInventory(Slot slot) { try { super.drawSlotInventory(slot); } catch(Throwable e)
+ * { try { Tessellator.instance.draw(); } catch(Throwable f) {} if (!mCrashed) { GT_Log.out.
+ * println("Clientside Slot drawing Crash prevented. Seems one Itemstack causes Problems with negative Damage Values or the Wildcard Damage Value. This is absolutely NOT a Bug of the GregTech-Addon, so don't even think about reporting it to me, it's a Bug of the Mod, which belongs to the almost-crash-causing Item, so bug that Mods Author and not me! Did you hear it? NOT ME!!!"
+ * ); e.printStackTrace(); mCrashed = true; } } }
+ */
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainerMetaTile_Machine.java b/src/main/java/gregtech/api/gui/GT_GUIContainerMetaTile_Machine.java
new file mode 100644
index 0000000000..df395858a9
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainerMetaTile_Machine.java
@@ -0,0 +1,271 @@
+package gregtech.api.gui;
+
+import java.util.List;
+
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.GT_Mod;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.gui.widgets.GT_GuiCoverTabLine;
+import gregtech.api.gui.widgets.GT_GuiIcon;
+import gregtech.api.gui.widgets.GT_GuiSlotTooltip;
+import gregtech.api.gui.widgets.GT_GuiTabLine.DisplayStyle;
+import gregtech.api.gui.widgets.GT_GuiTabLine.GT_GuiTabIconSet;
+import gregtech.api.gui.widgets.GT_GuiTabLine.GT_ITabRenderer;
+import gregtech.api.gui.widgets.GT_GuiTooltip;
+import gregtech.api.gui.widgets.GT_GuiTooltipManager;
+import gregtech.api.gui.widgets.GT_GuiTooltipManager.GT_IToolTipRenderer;
+import gregtech.api.interfaces.IConfigurationCircuitSupport;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.net.GT_Packet_SetConfigurationCircuit;
+import gregtech.api.util.GT_TooltipDataCache;
+import gregtech.api.util.GT_Util;
+import gregtech.api.util.GT_Utility;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * The GUI-Container I use for all my MetaTileEntities
+ */
+public class GT_GUIContainerMetaTile_Machine extends GT_GUIContainer implements GT_IToolTipRenderer, GT_ITabRenderer {
+
+ public final GT_ContainerMetaTile_Machine mContainer;
+
+ protected final GT_GuiTooltipManager mTooltipManager = new GT_GuiTooltipManager();
+ protected final GT_TooltipDataCache mTooltipCache = new GT_TooltipDataCache();
+ private static final String GHOST_CIRCUIT_TOOLTIP = "GT5U.machines.select_circuit.tooltip";
+
+ private final int guiTint;
+
+ // Cover Tabs support. Subclasses can override display position, style and visuals by overriding setupCoverTabs
+ public GT_GuiCoverTabLine coverTabs;
+ private static final int COVER_TAB_LEFT = -16, COVER_TAB_TOP = 1, COVER_TAB_HEIGHT = 20, COVER_TAB_WIDTH = 18,
+ COVER_TAB_SPACING = 2;
+ private static final DisplayStyle COVER_TAB_X_DIR = DisplayStyle.NONE, COVER_TAB_Y_DIR = DisplayStyle.NORMAL;
+ private static final GT_GuiTabIconSet TAB_ICONSET = new GT_GuiTabIconSet(
+ GT_GuiIcon.TAB_NORMAL,
+ GT_GuiIcon.TAB_HIGHLIGHT,
+ GT_GuiIcon.TAB_DISABLED);
+
+ public GT_GUIContainerMetaTile_Machine(GT_ContainerMetaTile_Machine aContainer, String aGUIbackground) {
+ super(aContainer, aGUIbackground);
+ mContainer = aContainer;
+
+ DisplayStyle preferredDisplayStyle = GT_Mod.gregtechproxy.mCoverTabsVisible
+ ? (GT_Mod.gregtechproxy.mCoverTabsFlipped ? DisplayStyle.INVERSE : DisplayStyle.NORMAL)
+ : DisplayStyle.NONE;
+ setupCoverTabs(preferredDisplayStyle);
+
+ // Only setup tooltips if they're currently enabled.
+ if (GT_Mod.gregtechproxy.mTooltipVerbosity > 0 || GT_Mod.gregtechproxy.mTooltipShiftVerbosity > 0) {
+ setupTooltips();
+ }
+
+ guiTint = getColorization();
+ mContainer.setCircuitSlotClickCallback(this::openSelectCircuitDialog);
+ }
+
+ public GT_GUIContainerMetaTile_Machine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity,
+ String aGUIbackground) {
+ this(new GT_ContainerMetaTile_Machine(aInventoryPlayer, aTileEntity), aGUIbackground);
+ }
+
+ /**
+ * Initialize the coverTabs object according to client preferences
+ */
+ protected void setupCoverTabs(DisplayStyle preferredDisplayStyle) {
+ coverTabs = new GT_GuiCoverTabLine(
+ this,
+ COVER_TAB_LEFT,
+ COVER_TAB_TOP,
+ COVER_TAB_HEIGHT,
+ COVER_TAB_WIDTH,
+ COVER_TAB_SPACING,
+ COVER_TAB_X_DIR,
+ COVER_TAB_Y_DIR,
+ preferredDisplayStyle,
+ getTabBackground(),
+ getMachine().getBaseMetaTileEntity(),
+ getColorization());
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float parTicks) {
+ super.drawScreen(mouseX, mouseY, parTicks);
+ if (mc.thePlayer.inventory.getItemStack() == null) {
+ GL11.glPushMatrix();
+ GL11.glTranslatef(guiLeft, guiTop, 0.0F);
+ mTooltipManager.onTick(this, mouseX, mouseY);
+ GL11.glPopMatrix();
+ }
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ // Drawing tabs
+ coverTabs.drawTabs(parTicks, mouseX, mouseY);
+
+ // Applying machine coloration, which subclasses rely on
+ GL11.glColor3ub((byte) ((guiTint >> 16) & 0xFF), (byte) ((guiTint >> 8) & 0xFF), (byte) (guiTint & 0xFF));
+
+ // Binding machine's own texture, which subclasses rely on being set
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ }
+
+ /**
+ * @return The color used to render this machine's GUI
+ */
+ private int getColorization() {
+ Dyes dye = Dyes.dyeWhite;
+ if (this.colorOverride.sLoaded()) {
+ if (this.colorOverride.sGuiTintingEnabled()) {
+ dye = getDyeFromIndex(mContainer.mTileEntity.getColorization());
+ return this.colorOverride.getGuiTintOrDefault(dye.mName, GT_Util.getRGBInt(dye.getRGBA()));
+ }
+ } else if (GregTech_API.sColoredGUI) {
+ if (GregTech_API.sMachineMetalGUI) {
+ dye = Dyes.MACHINE_METAL;
+ } else if (mContainer != null && mContainer.mTileEntity != null) {
+ dye = getDyeFromIndex(mContainer.mTileEntity.getColorization());
+ }
+ }
+ return GT_Util.getRGBInt(dye.getRGBA());
+ }
+
+ private Dyes getDyeFromIndex(short index) {
+ return index != -1 ? Dyes.get(index) : Dyes.MACHINE_METAL;
+ }
+
+ /**
+ * @return This machine's MetaTileEntity
+ */
+ private MetaTileEntity getMachine() {
+ return (MetaTileEntity) mContainer.mTileEntity.getMetaTileEntity();
+ }
+
+ // Tabs support
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+ // Check for clicked tabs
+ coverTabs.onMouseClicked(mouseX, mouseY, mouseButton);
+ }
+
+ @Override
+ public void initGui() {
+ super.initGui();
+ // Perform layout of tabs
+ coverTabs.onInit();
+ }
+
+ /**
+ * @return the background textures used by this machine GUI's tabs
+ */
+ protected GT_GuiTabIconSet getTabBackground() {
+ return TAB_ICONSET;
+ }
+
+ // Tooltips support
+
+ /**
+ * Load data for and create appropriate tooltips for this machine. Only called when one of regular or shift tooltips
+ * are enabled.
+ */
+ protected void setupTooltips() {
+ if (mContainer.mTileEntity.getMetaTileEntity() instanceof IConfigurationCircuitSupport ccs) {
+ if (ccs.allowSelectCircuit()) addToolTip(
+ new GT_GuiSlotTooltip(
+ mContainer.getSlot(ccs.getCircuitGUISlot()),
+ mTooltipCache.getData(GHOST_CIRCUIT_TOOLTIP)));
+ }
+ }
+
+ // GT_IToolTipRenderer and GT_ITabRenderer implementations
+ @Override
+ public void drawHoveringText(List<String> text, int mouseX, int mouseY, FontRenderer font) {
+ super.drawHoveringText(text, mouseX, mouseY, font);
+ }
+
+ @Override
+ public int getGuiTop() {
+ return guiTop;
+ }
+
+ @Override
+ public int getGuiLeft() {
+ return guiLeft;
+ }
+
+ @Override
+ public int getXSize() {
+ return xSize;
+ }
+
+ @Override
+ public FontRenderer getFontRenderer() {
+ return fontRendererObj;
+ }
+
+ @Override
+ public RenderItem getItemRenderer() {
+ return itemRender;
+ }
+
+ @Override
+ public void addToolTip(GT_GuiTooltip toolTip) {
+ mTooltipManager.addToolTip(toolTip);
+ }
+
+ @Override
+ public boolean removeToolTip(GT_GuiTooltip toolTip) {
+ return mTooltipManager.removeToolTip(toolTip);
+ }
+
+ @Override
+ protected void onMouseWheel(int mx, int my, int delta) {
+ if (mContainer.mTileEntity.getMetaTileEntity() instanceof IConfigurationCircuitSupport ccs) {
+ Slot slotCircuit = mContainer.getSlot(ccs.getCircuitGUISlot());
+ if (slotCircuit != null
+ && func_146978_c(slotCircuit.xDisplayPosition, slotCircuit.yDisplayPosition, 16, 16, mx, my)) {
+ // emulate click
+ handleMouseClick(slotCircuit, -1, delta > 0 ? 1 : 0, 0);
+ return;
+ }
+ }
+ super.onMouseWheel(mx, my, delta);
+ }
+
+ private void openSelectCircuitDialog() {
+ IMetaTileEntity machine = mContainer.mTileEntity.getMetaTileEntity();
+ IConfigurationCircuitSupport ccs = (IConfigurationCircuitSupport) machine;
+ List<ItemStack> circuits = ccs.getConfigurationCircuits();
+ mc.displayGuiScreen(
+ new GT_GUIDialogSelectItem(
+ StatCollector.translateToLocal("GT5U.machines.select_circuit"),
+ machine.getStackForm(0),
+ this,
+ this::onCircuitSelected,
+ circuits,
+ GT_Utility.findMatchingStackInList(circuits, machine.getStackInSlot(ccs.getCircuitSlot()))));
+ }
+
+ private void onCircuitSelected(ItemStack selected) {
+ GT_Values.NW.sendToServer(new GT_Packet_SetConfigurationCircuit(mContainer.mTileEntity, selected));
+ // we will not do any validation on client side
+ // it doesn't get to actually decide what inventory contains anyway
+ IConfigurationCircuitSupport ccs = (IConfigurationCircuitSupport) mContainer.mTileEntity.getMetaTileEntity();
+ mContainer.mTileEntity.setInventorySlotContents(ccs.getCircuitSlot(), selected);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_1by1.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_1by1.java
new file mode 100644
index 0000000000..5bd44668c5
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_1by1.java
@@ -0,0 +1,42 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_GUIContainer_1by1 extends GT_GUIContainerMetaTile_Machine {
+
+ private final String mName;
+ private final int textColor = this.getTextColorOrDefault("title", 0x404040);
+
+ public GT_GUIContainer_1by1(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName) {
+ super(
+ new GT_Container_1by1(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", "1by1.png"));
+ mName = aName;
+ }
+
+ public GT_GUIContainer_1by1(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName,
+ String aBackground) {
+ super(
+ new GT_Container_1by1(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", aBackground + "1by1.png"));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ fontRendererObj.drawString(mName, 8, 4, textColor);
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_2by2.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_2by2.java
new file mode 100644
index 0000000000..107bcc3859
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_2by2.java
@@ -0,0 +1,42 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_GUIContainer_2by2 extends GT_GUIContainerMetaTile_Machine {
+
+ private final String mName;
+ private final int textColor = this.getTextColorOrDefault("title", 0x404040);
+
+ public GT_GUIContainer_2by2(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName) {
+ super(
+ new GT_Container_2by2(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", "2by2.png"));
+ mName = aName;
+ }
+
+ public GT_GUIContainer_2by2(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName,
+ String aBackground) {
+ super(
+ new GT_Container_2by2(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", aBackground + "2by2.png"));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ fontRendererObj.drawString(mName, 8, 4, textColor);
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_3by3.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_3by3.java
new file mode 100644
index 0000000000..0c8b63664a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_3by3.java
@@ -0,0 +1,42 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_GUIContainer_3by3 extends GT_GUIContainerMetaTile_Machine {
+
+ private final String mName;
+ private final int textColor = this.getTextColorOrDefault("title", 0x404040);
+
+ public GT_GUIContainer_3by3(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName) {
+ super(
+ new GT_Container_3by3(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", "3by3.png"));
+ mName = aName;
+ }
+
+ public GT_GUIContainer_3by3(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName,
+ String aBackground) {
+ super(
+ new GT_Container_3by3(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", aBackground + "3by3.png"));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ fontRendererObj.drawString(mName, 8, 4, textColor);
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_4by4.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_4by4.java
new file mode 100644
index 0000000000..9e5d7f7155
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_4by4.java
@@ -0,0 +1,42 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+
+@Deprecated
+public class GT_GUIContainer_4by4 extends GT_GUIContainerMetaTile_Machine {
+
+ private final String mName;
+ private final int textColor = this.getTextColorOrDefault("title", 0x404040);
+
+ public GT_GUIContainer_4by4(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName) {
+ super(
+ new GT_Container_4by4(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", "4by4.png"));
+ mName = aName;
+ }
+
+ public GT_GUIContainer_4by4(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName,
+ String aBackground) {
+ super(
+ new GT_Container_4by4(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", aBackground + "4by4.png"));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ fontRendererObj.drawString(mName, 8, 4, textColor);
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_BasicTank.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_BasicTank.java
new file mode 100644
index 0000000000..54aa42d2a3
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_BasicTank.java
@@ -0,0 +1,47 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.util.StatCollector;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_Utility;
+
+public class GT_GUIContainer_BasicTank extends GT_GUIContainerMetaTile_Machine {
+
+ private final String mName;
+ private final int textColor = this.getTextColorOrDefault("text", 0xFAFAFF),
+ textColorTitle = this.getTextColorOrDefault("title", 0x404040),
+ textColorValue = this.getTextColorOrDefault("value", 0xFAFAFF);
+
+ public GT_GUIContainer_BasicTank(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName) {
+ super(
+ new GT_Container_BasicTank(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath("textures", "gui", "BasicTank.png"));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ fontRendererObj
+ .drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, textColorTitle);
+ fontRendererObj.drawString(mName, 8, 6, textColorTitle);
+ if (mContainer != null) {
+ fontRendererObj.drawString("Liquid Amount", 10, 20, textColor);
+ fontRendererObj.drawString(
+ GT_Utility.parseNumberToString(((GT_Container_BasicTank) mContainer).mContent),
+ 10,
+ 30,
+ textColorValue);
+ }
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIContainer_MultiMachine.java b/src/main/java/gregtech/api/gui/GT_GUIContainer_MultiMachine.java
new file mode 100644
index 0000000000..3d9515b19a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIContainer_MultiMachine.java
@@ -0,0 +1,173 @@
+package gregtech.api.gui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import net.minecraft.entity.player.InventoryPlayer;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_DrillerBase;
+import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine;
+
+/**
+ * NEVER INCLUDE THIS FILE IN YOUR MOD!!!
+ * <p/>
+ * The GUI-Container I use for all my Basic Machines
+ */
+@Deprecated
+public class GT_GUIContainer_MultiMachine extends GT_GUIContainerMetaTile_Machine {
+
+ final String mName;
+ private final int textColor = this.getTextColorOrDefault("text", 0xFAFAFF),
+ textColorTitle = this.getTextColorOrDefault("title", 0xFAFAFF);
+
+ public GT_GUIContainer_MultiMachine(InventoryPlayer aInventoryPlayer, IGregTechTileEntity aTileEntity, String aName,
+ String aTextureFile) {
+ super(
+ new GT_Container_MultiMachine(aInventoryPlayer, aTileEntity),
+ GregTech.getResourcePath(
+ "textures",
+ "gui",
+ "multimachines",
+ aTextureFile == null ? "MultiblockDisplay" : aTextureFile));
+ mName = aName;
+ }
+
+ @Override
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+
+ // If text is drawn iterate down GUI 8 pixels (height of characters).
+ int line_counter = 7;
+ int max_chars_per_line = 26;
+
+ if (mName.length() > 26) {
+
+ // Split the machine name into an array, so we can try fit it on one line but if not use more.
+ String[] split = mName.split(" ");
+
+ int total_line_length = 0;
+ StringBuilder current_line = new StringBuilder();
+
+ int index = 0;
+
+ for (String str : split) {
+
+ total_line_length += str.length();
+
+ if (total_line_length > max_chars_per_line) {
+ fontRendererObj.drawString(current_line.toString(), 10, line_counter, textColorTitle);
+ line_counter += 8;
+ current_line = new StringBuilder();
+ index = 0;
+ total_line_length = str.length();
+ }
+
+ if (index == 0) {
+ current_line.append(str);
+ } else {
+ current_line.append(" ")
+ .append(str);
+ }
+ index++;
+ }
+ fontRendererObj.drawString(current_line.toString(), 10, line_counter, textColorTitle);
+ } else {
+ fontRendererObj.drawString(mName, 10, line_counter, textColorTitle);
+ }
+ line_counter += 8;
+
+ if (mContainer != null) { // (mWrench ? 0 : 1) | (mScrewdriver ? 0 : 2) | (mSoftHammer ? 0 : 4) | (mHardHammer ?
+ // 0 : 8)
+ // | (mSolderingTool ? 0 : 16) | (mCrowbar ? 0 : 32) | (mMachine ? 0 : 64));
+ if ((mContainer.mDisplayErrorCode & 1) != 0) {
+ fontRendererObj.drawString(GT_Utility.trans("132", "Pipe is loose."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 2) != 0) {
+ fontRendererObj.drawString(GT_Utility.trans("133", "Screws are loose."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 4) != 0) {
+ fontRendererObj.drawString(GT_Utility.trans("134", "Something is stuck."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 8) != 0) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("135", "Platings are dented."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 16) != 0) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("136", "Circuitry burned out."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 32) != 0) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("137", "That doesn't belong there."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if ((mContainer.mDisplayErrorCode & 64) != 0) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("138", "Incomplete Structure."), 10, line_counter, textColor);
+ line_counter += 8;
+ }
+
+ if (mContainer.mDisplayErrorCode == 0) {
+ if (mContainer.mActive == 0) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("139", "Hit with Soft Mallet"), 10, line_counter, textColor);
+ line_counter += 8;
+ fontRendererObj
+ .drawString(GT_Utility.trans("140", "to (re-)start the Machine"), 10, line_counter, textColor);
+ line_counter += 8;
+ fontRendererObj
+ .drawString(GT_Utility.trans("141", "if it doesn't start."), 10, line_counter, textColor);
+ } else {
+ fontRendererObj
+ .drawString(GT_Utility.trans("142", "Running perfectly."), 10, line_counter, textColor);
+ }
+ line_counter += 8;
+ if (mContainer.mTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_DrillerBase) {
+ ItemStack tItem = mContainer.mTileEntity.getMetaTileEntity()
+ .getStackInSlot(1);
+ if (tItem == null
+ || !GT_Utility.areStacksEqual(tItem, GT_ModHandler.getIC2Item("miningPipe", 1L))) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("143", "Missing Mining Pipe"), 10, line_counter, textColor);
+ }
+ } else if (mContainer.mTileEntity.getMetaTileEntity() instanceof GT_MetaTileEntity_LargeTurbine) {
+ ItemStack tItem = mContainer.mTileEntity.getMetaTileEntity()
+ .getStackInSlot(1);
+ if (tItem == null
+ || !(tItem.getItem() == GT_MetaGenerated_Tool_01.INSTANCE && tItem.getItemDamage() >= 170
+ && tItem.getItemDamage() <= 177)) {
+ fontRendererObj
+ .drawString(GT_Utility.trans("144", "Missing Turbine Rotor"), 10, line_counter, textColor);
+ }
+ }
+ }
+ }
+ }
+
+ @Deprecated
+ public String trans(String aKey, String aEnglish) {
+ return GT_Utility.trans(aKey, aEnglish);
+ }
+
+ @Override
+ protected void drawGuiContainerBackgroundLayer(float parTicks, int mouseX, int mouseY) {
+ super.drawGuiContainerBackgroundLayer(parTicks, mouseX, mouseY);
+ int x = (width - xSize) / 2;
+ int y = (height - ySize) / 2;
+ drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUICover.java b/src/main/java/gregtech/api/gui/GT_GUICover.java
new file mode 100644
index 0000000000..5729ada685
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUICover.java
@@ -0,0 +1,55 @@
+package gregtech.api.gui;
+
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.net.GT_Packet_GtTileEntityGuiRequest;
+
+@Deprecated
+public abstract class GT_GUICover extends GT_GUIScreen {
+
+ public final ICoverable tile;
+ public int parentGuiId = -1;
+
+ public GT_GUICover(ICoverable tile, int width, int height, ItemStack cover) {
+ super(width, height, cover == null ? "" : cover.getDisplayName());
+ this.tile = tile;
+ headerIcon.setItem(cover);
+ }
+
+ @Override
+ public void updateScreen() {
+ super.updateScreen();
+ if (!tile.isUseableByPlayer(mc.thePlayer)) {
+ closeScreen();
+ }
+ }
+
+ /**
+ * The parent GUI to exit to. -1 is ignored.
+ *
+ * @param parentGuiId parent GUI ID
+ */
+ public void setParentGuiId(int parentGuiId) {
+ this.parentGuiId = parentGuiId;
+ }
+
+ @Override
+ public void closeScreen() {
+ // If this cover was given a guiId, tell the server to open it for us when this GUI closes.
+ if (parentGuiId != -1 && tile.isUseableByPlayer(mc.thePlayer)) {
+ GT_Values.NW.sendToServer(
+ new GT_Packet_GtTileEntityGuiRequest(
+ tile.getXCoord(),
+ tile.getYCoord(),
+ tile.getZCoord(),
+ parentGuiId,
+ tile.getWorld().provider.dimensionId,
+ mc.thePlayer.getEntityId()));
+ } else {
+ this.mc.displayGuiScreen(null);
+ this.mc.setIngameFocus();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIDialogSelectItem.java b/src/main/java/gregtech/api/gui/GT_GUIDialogSelectItem.java
new file mode 100644
index 0000000000..03a6fb2a70
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIDialogSelectItem.java
@@ -0,0 +1,229 @@
+package gregtech.api.gui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.StatCollector;
+
+import gregtech.api.gui.widgets.GT_GuiFakeItemButton;
+import gregtech.api.gui.widgets.GT_GuiIcon;
+import gregtech.api.gui.widgets.GT_GuiIconButton;
+import gregtech.api.util.GT_Utility;
+
+@Deprecated
+public class GT_GUIDialogSelectItem extends GT_GUIScreen {
+
+ public static final int UNSELECTED = -1;
+ private static final int cols = 9;
+ private static final int rows = 3;
+ private final int textColor = this.getTextColorOrDefault("text", 0xff555555);
+ private final GuiScreen parent;
+ private final Consumer<ItemStack> selectedCallback;
+ // passed in stack
+ private final List<ItemStack> stacks;
+ // all slots not including btnCurrent
+ private final List<GT_GuiFakeItemButton> slots = new ArrayList<>();
+ // the currently selected slot content
+ private final GT_GuiFakeItemButton btnCurrent = new GT_GuiFakeItemButton(this, 8, 25, GT_GuiIcon.SLOT_DARKGRAY)
+ .setMimicSlot(true);
+ private final boolean noDeselect;
+ private int selected;
+ private int scroll = 0;
+ private GT_GuiIconButton btnUp;
+ private GT_GuiIconButton btnDown;
+
+ public GT_GUIDialogSelectItem(String header, ItemStack headerItem, GuiScreen parent,
+ Consumer<ItemStack> selectedCallback, List<ItemStack> stacks) {
+ this(header, headerItem, parent, selectedCallback, stacks, UNSELECTED);
+ }
+
+ public GT_GUIDialogSelectItem(String header, ItemStack headerItem, GuiScreen parent,
+ Consumer<ItemStack> selectedCallback, List<ItemStack> stacks, int selected) {
+ this(header, headerItem, parent, selectedCallback, stacks, selected, false);
+ }
+
+ /**
+ * Open a dialog to select an item from given list. Given callback may be called zero or more times depending on
+ * user action.
+ *
+ * @param header Header text
+ * @param headerItem ItemStack to use as Dialog icon
+ * @param parent open which GUIScreen when this dialog is closed. use null if it has no parent.
+ * @param selectedCallback callback upon selected
+ * @param stacks list to choose from
+ * @param selected preselected item. Use {@link #UNSELECTED} for unselected. Invalid selected will be
+ * clamped to 0 or highest index
+ * @param noDeselect true if player cannot deselect, false otherwise. If this is set to true, selectedCallback
+ * is guaranteed to be called with a nonnull stack
+ */
+ public GT_GUIDialogSelectItem(String header, ItemStack headerItem, GuiScreen parent,
+ Consumer<ItemStack> selectedCallback, List<ItemStack> stacks, int selected, boolean noDeselect) {
+ super(176, 107, header);
+ this.noDeselect = noDeselect;
+ if (headerItem != null) this.headerIcon.setItem(headerItem);
+ this.parent = parent;
+ this.selectedCallback = selectedCallback;
+ this.stacks = stacks;
+
+ if (stacks.size() > rows * cols) {
+ btnUp = new GT_GuiIconButton(this, 0, 134, 25, GT_GuiIcon.GREEN_ARROW_UP);
+ btnDown = new GT_GuiIconButton(this, 1, 152, 25, GT_GuiIcon.GREEN_ARROW_DOWN);
+ }
+
+ for (int i = 0; i < rows; i++) {
+ for (int j = 0; j < cols; j++) {
+ slots.add(
+ new GT_GuiFakeItemButton(this, 8 + 18 * j, 44 + 18 * i, GT_GuiIcon.SLOT_GRAY).setMimicSlot(true));
+ }
+ }
+
+ setSelected(noDeselect ? Math.max(0, selected) : selected);
+ ensureSelectedDisplayed();
+ }
+
+ @Override
+ protected void onInitGui(int guiLeft, int guiTop, int gui_width, int gui_height) {
+ btnCurrent
+ .setX(8 + 2 + fontRendererObj.getStringWidth(StatCollector.translateToLocal("GT5U.gui.select.current")));
+ }
+
+ @Override
+ public void closeScreen() {
+ selectedCallback.accept(getCandidate(getSelected()));
+ mc.displayGuiScreen(parent);
+ if (parent == null) mc.setIngameFocus();
+ }
+
+ @Override
+ public void buttonClicked(GuiButton button) {
+ switch (button.id) {
+ case 0 -> {
+ setScroll(scroll - 1);
+ return;
+ }
+ case 1 -> {
+ setScroll(scroll + 1);
+ return;
+ }
+ }
+ super.buttonClicked(button);
+ }
+
+ @Override
+ public void drawExtras(int mouseX, int mouseY, float parTicks) {
+ int y = 25 + (18 - getFontRenderer().FONT_HEIGHT) / 2;
+ getFontRenderer().drawString(StatCollector.translateToLocal("GT5U.gui.select.current"), 8, y, textColor);
+ super.drawExtras(mouseX, mouseY, parTicks);
+ }
+
+ @Override
+ public void mouseClicked(int x, int y, int button) {
+ int mx = x - guiLeft, my = y - guiTop;
+ if (button == 0) {
+ if (btnCurrent.getBounds()
+ .contains(mx, my)) {
+ ensureSelectedDisplayed();
+ return;
+ }
+
+ for (int i = 0, slotsSize = slots.size(); i < slotsSize; i++) {
+ GT_GuiFakeItemButton slot = slots.get(i);
+ if (slot.getBounds()
+ .contains(mx, my)) {
+ setSelected(slotIndexToListIndex(i));
+ return;
+ }
+ }
+ } else if (button == 1 && getSelected() >= 0) {
+ if (btnCurrent.getBounds()
+ .contains(mx, my)) {
+ setSelected(UNSELECTED);
+ return;
+ }
+ GT_GuiFakeItemButton slot = getSlot(listIndexToSlotIndex(getSelected()));
+ if (slot != null && slot.getBounds()
+ .contains(mx, my)) {
+ setSelected(UNSELECTED);
+ }
+ }
+ super.mouseClicked(x, y, button);
+ }
+
+ @Override
+ public void onMouseWheel(int x, int y, int delta) {
+ if (delta < 0) setScroll(scroll + 1);
+ else if (delta > 0) setScroll(scroll - 1);
+ }
+
+ private void fillSlots() {
+ for (int i = 0, j = scroll * cols; i < slots.size(); i++, j++) {
+ slots.get(i)
+ .setItem(getCandidate(j))
+ .setBgIcon(j == getSelected() ? GT_GuiIcon.SLOT_DARKGRAY : GT_GuiIcon.SLOT_GRAY);
+ }
+ }
+
+ private void ensureSelectedDisplayed() {
+ if (getSelected() < scroll * cols) {
+ setScroll(getSelected() / cols);
+ } else if (getSelected() > (scroll + rows) * cols) {
+ setScroll((getSelected() - (rows - 1) * cols) / cols);
+ } else {
+ // called nonetheless to update button enabled states
+ setScroll(scroll);
+ }
+ }
+
+ private int slotIndexToListIndex(int index) {
+ int mapped = scroll * cols + index;
+ return mapped >= stacks.size() ? UNSELECTED : mapped;
+ }
+
+ private int listIndexToSlotIndex(int index) {
+ return index - scroll * cols;
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ if (selected == this.selected) return;
+ int newSelected = GT_Utility.clamp(selected, UNSELECTED, stacks.size() - 1);
+
+ if (noDeselect && newSelected == UNSELECTED) return;
+
+ GT_GuiFakeItemButton selectedSlot = getSlot(this.selected);
+ if (selectedSlot != null) selectedSlot.setBgIcon(GT_GuiIcon.SLOT_GRAY);
+
+ this.selected = newSelected;
+
+ btnCurrent.setItem(getCandidate(this.selected));
+
+ selectedSlot = getSlot(this.selected);
+ if (selectedSlot != null) selectedSlot.setBgIcon(GT_GuiIcon.SLOT_DARKGRAY);
+ }
+
+ private void setScroll(int scroll) {
+ if (stacks.size() > rows * cols) {
+ int lo = 0;
+ int hi = (stacks.size() - rows * cols) / cols + 1;
+ this.scroll = GT_Utility.clamp(scroll, lo, hi);
+ btnUp.enabled = this.scroll != lo;
+ btnDown.enabled = this.scroll != hi;
+ }
+ fillSlots();
+ }
+
+ private ItemStack getCandidate(int listIndex) {
+ return listIndex < 0 || listIndex >= stacks.size() ? null : stacks.get(listIndex);
+ }
+
+ private GT_GuiFakeItemButton getSlot(int slotIndex) {
+ return slotIndex < 0 || slotIndex >= slots.size() ? null : slots.get(slotIndex);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_GUIScreen.java b/src/main/java/gregtech/api/gui/GT_GUIScreen.java
new file mode 100644
index 0000000000..2ff2973792
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_GUIScreen.java
@@ -0,0 +1,327 @@
+package gregtech.api.gui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.GuiTextField;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.util.ResourceLocation;
+
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.gui.widgets.GT_GuiFakeItemButton;
+import gregtech.api.gui.widgets.GT_GuiIntegerTextBox;
+import gregtech.api.gui.widgets.GT_GuiTooltip;
+import gregtech.api.gui.widgets.GT_GuiTooltipManager;
+import gregtech.api.gui.widgets.GT_GuiTooltipManager.GT_IToolTipRenderer;
+import gregtech.api.interfaces.IGuiScreen;
+
+@Deprecated
+public abstract class GT_GUIScreen extends GuiScreen implements GT_IToolTipRenderer, IGuiScreen {
+
+ protected final GT_GuiTooltipManager ttManager = new GT_GuiTooltipManager();
+
+ protected int gui_width = 176;
+ protected int gui_height = 107;
+ protected int guiTop, guiLeft;
+ protected final boolean drawButtons = true;
+ protected final ResourceLocation mGUIbackgroundLocation;
+
+ private GuiButton selectedButton;
+ private final GT_GUIColorOverride colorOverride;
+ private final int textColor;
+ private static final String guiTexturePath = "gregtech:textures/gui/GuiCover.png";
+
+ public String header;
+ public GT_GuiFakeItemButton headerIcon;
+
+ protected final List<IGuiElement> elements = new ArrayList<>();
+ protected final List<GT_GuiIntegerTextBox> textBoxes = new ArrayList<>();
+
+ public GT_GUIScreen(int width, int height, String header) {
+ this.gui_width = width;
+ this.gui_height = height;
+ this.header = header;
+ this.headerIcon = new GT_GuiFakeItemButton(this, 5, 5, null);
+ this.mGUIbackgroundLocation = new ResourceLocation(guiTexturePath);
+ this.colorOverride = GT_GUIColorOverride.get(guiTexturePath);
+ this.textColor = getTextColorOrDefault("title", 0xFF222222);
+ }
+
+ @Override
+ public void initGui() {
+ guiLeft = (this.width - this.gui_width) / 2;
+ guiTop = (this.height - this.gui_height) / 2;
+
+ for (IGuiElement element : elements) {
+ if (element instanceof GuiButton button) buttonList.add(button);
+ if (element instanceof GT_GuiIntegerTextBox) textBoxes.add((GT_GuiIntegerTextBox) element);
+ }
+
+ onInitGui(guiLeft, guiTop, gui_width, gui_height);
+
+ for (IGuiElement element : elements) {
+ element.onInit();
+ }
+ super.initGui();
+ }
+
+ protected abstract void onInitGui(int guiLeft, int guiTop, int gui_width, int gui_height);
+
+ protected int getTextColorOrDefault(String textType, int defaultColor) {
+ return colorOverride.getTextColorOrDefault(textType, defaultColor);
+ }
+
+ public void onMouseWheel(int x, int y, int delta) {}
+
+ @Override
+ public void handleMouseInput() {
+ int delta = Mouse.getEventDWheel();
+ if (delta != 0) {
+ int i = Mouse.getEventX() * this.width / this.mc.displayWidth;
+ int j = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
+ onMouseWheel(i, j, delta);
+ }
+ super.handleMouseInput();
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float parTicks) {
+ drawDefaultBackground();
+
+ drawBackground(mouseX, mouseY, parTicks);
+
+ RenderHelper.disableStandardItemLighting();
+ GL11.glDisable(GL11.GL_LIGHTING);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ GL11.glDisable(GL12.GL_RESCALE_NORMAL);
+ if (drawButtons) {
+ RenderHelper.enableGUIStandardItemLighting();
+ for (IGuiElement e : elements) e.draw(mouseX, mouseY, parTicks);
+ }
+ GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+
+ GL11.glPushMatrix();
+ GL11.glTranslatef(guiLeft, guiTop, 0.0F);
+ GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
+
+ GL11.glDisable(GL11.GL_LIGHTING);
+ drawForegroundLayer(mouseX, mouseY, parTicks);
+ GL11.glEnable(GL11.GL_LIGHTING);
+
+ GL11.glPopMatrix();
+
+ GL11.glEnable(GL11.GL_LIGHTING);
+ GL11.glEnable(GL11.GL_DEPTH_TEST);
+ RenderHelper.enableStandardItemLighting();
+ }
+
+ public void drawForegroundLayer(int mouseX, int mouseY, float parTicks) {
+ drawExtras(mouseX, mouseY, parTicks);
+ ttManager.onTick(this, mouseX, mouseY);
+ }
+
+ public void drawBackground(int mouseX, int mouseY, float parTicks) {
+ short[] color = Dyes.MACHINE_METAL.getRGBA();
+ GL11.glColor3ub((byte) color[0], (byte) color[1], (byte) color[2]);
+ this.mc.renderEngine.bindTexture(mGUIbackgroundLocation);
+ drawTexturedModalRect(guiLeft, guiTop, 0, 0, gui_width, gui_height);
+ }
+
+ public void drawExtras(int mouseX, int mouseY, float parTicks) {
+ this.fontRendererObj.drawString(header, 25, 9, textColor);
+ }
+
+ @Override
+ public boolean doesGuiPauseGame() {
+ return false;
+ }
+
+ public void closeScreen() {
+ this.mc.displayGuiScreen(null);
+ this.mc.setIngameFocus();
+ }
+
+ @Override
+ public void updateScreen() {
+ super.updateScreen();
+ for (GuiTextField f : textBoxes) {
+ f.updateCursorCounter();
+ }
+ }
+
+ @Override
+ public void mouseClicked(int x, int y, int button) {
+ for (GT_GuiIntegerTextBox tBox : textBoxes) {
+ boolean hadFocus = tBox.isFocused();
+ if (tBox.isEnabled() || hadFocus) tBox.mouseClicked(x, y, button);
+
+ if (tBox.isFocused() && button == 1 && tBox.isEnabled()) // rightclick -> lcear it
+ tBox.setText("0");
+ else if (hadFocus && !tBox.isFocused()) applyTextBox(tBox);
+ }
+ super.mouseClicked(x, y, button);
+ }
+
+ @Override
+ public void keyTyped(char c, int key) {
+ GT_GuiIntegerTextBox focusedTextBox = null;
+ for (GT_GuiIntegerTextBox textBox : textBoxes) {
+ if (textBox.isFocused()) focusedTextBox = textBox;
+ }
+
+ if (key == 1) { // esc
+ if (focusedTextBox != null) {
+ resetTextBox(focusedTextBox);
+ setFocusedTextBox(null);
+ } else {
+ closeScreen();
+ // don't fall through to parent
+ }
+ return;
+ }
+
+ if (c == '\t') { // tab
+ for (int i = 0; i < textBoxes.size(); i++) {
+ GT_GuiIntegerTextBox box = textBoxes.get(i);
+ if (box.isFocused()) {
+ applyTextBox(box);
+ setFocusedTextBox(((i + 1) < textBoxes.size()) ? textBoxes.get(i + 1) : null);
+ return;
+ }
+ }
+ if (!textBoxes.isEmpty()) setFocusedTextBox(textBoxes.get(0));
+ return;
+ }
+
+ if (focusedTextBox != null && focusedTextBox.textboxKeyTyped(c, key)) {
+ return;
+ }
+
+ if (key == 28 && focusedTextBox != null) { // enter
+ applyTextBox(focusedTextBox);
+ setFocusedTextBox(null);
+ return;
+ }
+
+ if (key == this.mc.gameSettings.keyBindInventory.getKeyCode()) {
+ if (focusedTextBox != null) {
+ applyTextBox(focusedTextBox);
+ setFocusedTextBox(null);
+ return;
+ }
+ closeScreen();
+ return;
+ }
+ super.keyTyped(c, key);
+ }
+
+ /**
+ * Button
+ */
+ @Override
+ public void actionPerformed(GuiButton button) {
+ selectedButton = button;
+ }
+
+ @Override
+ public void clearSelectedButton() {
+ selectedButton = null;
+ }
+
+ @Override
+ public GuiButton getSelectedButton() {
+ return selectedButton;
+ }
+
+ @Override
+ public void buttonClicked(GuiButton button) {}
+
+ /**
+ * TextBoxes
+ */
+ private void setFocusedTextBox(GT_GuiIntegerTextBox boxToFocus) {
+ for (GT_GuiIntegerTextBox textBox : textBoxes) {
+ textBox.setFocused(textBox.equals(boxToFocus) && textBox.isEnabled());
+ }
+ }
+
+ /**
+ * Given textbox's value might have changed.
+ */
+ public void applyTextBox(GT_GuiIntegerTextBox box) {}
+
+ /**
+ * Reset the given textbox to the last valid value, <b>NOT</b> 0.
+ */
+ public void resetTextBox(GT_GuiIntegerTextBox box) {}
+
+ /**
+ * GT_IToolTipRenderer
+ */
+ @Override
+ public void drawHoveringText(List<String> text, int mouseX, int mouseY, FontRenderer render) {
+ super.drawHoveringText(text, mouseX, mouseY, render);
+ }
+
+ @Override
+ public FontRenderer getFontRenderer() {
+ return super.fontRendererObj;
+ }
+
+ @Override
+ public void addToolTip(GT_GuiTooltip toolTip) {
+ ttManager.addToolTip(toolTip);
+ }
+
+ @Override
+ public boolean removeToolTip(GT_GuiTooltip toolTip) {
+ return ttManager.removeToolTip(toolTip);
+ }
+
+ /**
+ * Junk
+ */
+ @Override
+ public int getGuiTop() {
+ return guiTop;
+ }
+
+ @Override
+ public int getGuiLeft() {
+ return guiLeft;
+ }
+
+ @Override
+ public int getXSize() {
+ return gui_width;
+ }
+
+ @Override
+ public int getYSize() {
+ return gui_height;
+ }
+
+ @Override
+ public RenderItem getItemRenderer() {
+ return itemRender;
+ }
+
+ @Override
+ public void addElement(IGuiElement element) {
+ if (elements.contains(element)) return;
+ elements.add(element);
+ }
+
+ @Override
+ public boolean removeElement(IGuiElement element) {
+ return elements.remove(element);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Slot_Armor.java b/src/main/java/gregtech/api/gui/GT_Slot_Armor.java
new file mode 100644
index 0000000000..1c48b01430
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Slot_Armor.java
@@ -0,0 +1,30 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+public class GT_Slot_Armor extends Slot {
+
+ final int mArmorType;
+ final EntityPlayer mPlayer;
+
+ public GT_Slot_Armor(IInventory inventory, int slotIndex, int xPos, int yPos, int armorType, EntityPlayer aPlayer) {
+ super(inventory, slotIndex, xPos, yPos);
+ mArmorType = armorType;
+ mPlayer = aPlayer;
+ }
+
+ @Override
+ public int getSlotStackLimit() {
+ return 1;
+ }
+
+ @Override
+ public boolean isItemValid(ItemStack aStack) {
+ return aStack != null && aStack.getItem() != null
+ && aStack.getItem()
+ .isValidArmor(aStack, mArmorType, mPlayer);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Slot_DataOrb.java b/src/main/java/gregtech/api/gui/GT_Slot_DataOrb.java
new file mode 100644
index 0000000000..115b50ddb8
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Slot_DataOrb.java
@@ -0,0 +1,19 @@
+package gregtech.api.gui;
+
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+import gregtech.api.enums.ItemList;
+
+public class GT_Slot_DataOrb extends Slot {
+
+ public GT_Slot_DataOrb(IInventory inventory, int slotIndex, int xPos, int yPos) {
+ super(inventory, slotIndex, xPos, yPos);
+ }
+
+ @Override
+ public boolean isItemValid(ItemStack aStack) {
+ return ItemList.Tool_DataOrb.isStackEqual(aStack, false, true);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Slot_Holo.java b/src/main/java/gregtech/api/gui/GT_Slot_Holo.java
new file mode 100644
index 0000000000..9b7b75f0b2
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Slot_Holo.java
@@ -0,0 +1,77 @@
+package gregtech.api.gui;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+
+public class GT_Slot_Holo extends Slot {
+
+ public final int mSlotIndex;
+ public boolean mEnabled = true;
+ public boolean mCanInsertItem, mCanStackItem;
+ public int mMaxStacksize = 127;
+
+ public GT_Slot_Holo(IInventory inventory, int slotIndex, int xPos, int yPos, boolean aCanInsertItem,
+ boolean aCanStackItem, int aMaxStacksize) {
+ super(inventory, slotIndex, xPos, yPos);
+ mCanInsertItem = aCanInsertItem;
+ mCanStackItem = aCanStackItem;
+ mMaxStacksize = aMaxStacksize;
+ mSlotIndex = slotIndex;
+ }
+
+ @Override
+ public boolean isItemValid(ItemStack itemStack) {
+ return mCanInsertItem;
+ }
+
+ @Override
+ public int getSlotStackLimit() {
+ return mMaxStacksize;
+ }
+
+ @Override
+ public boolean getHasStack() {
+ return false;
+ }
+
+ @Override
+ public ItemStack decrStackSize(int amount) {
+ if (!mCanStackItem) return null;
+ return super.decrStackSize(amount);
+ }
+
+ @Override
+ public boolean canTakeStack(EntityPlayer player) {
+ return false;
+ }
+
+ /**
+ * Sets if this slot should be ignored in event-processing. For example, highlight the slot on mouseOver.
+ *
+ * @param enabled if the slot should be enabled
+ */
+ public void setEnabled(boolean enabled) {
+ mEnabled = enabled;
+ }
+
+ /**
+ * Use this value to determine whether to ignore this slot in event processing
+ */
+ public boolean isEnabled() {
+ return mEnabled;
+ }
+
+ /**
+ * This function controls whether to highlight the slot on mouseOver.
+ */
+ @Override
+ @SideOnly(Side.CLIENT)
+ public boolean func_111238_b() {
+ return isEnabled();
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Slot_Output.java b/src/main/java/gregtech/api/gui/GT_Slot_Output.java
new file mode 100644
index 0000000000..7c883ea2d1
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Slot_Output.java
@@ -0,0 +1,17 @@
+package gregtech.api.gui;
+
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+public class GT_Slot_Output extends Slot {
+
+ public GT_Slot_Output(IInventory inventory, int slotIndex, int xPos, int yPos) {
+ super(inventory, slotIndex, xPos, yPos);
+ }
+
+ @Override
+ public boolean isItemValid(ItemStack itemStack) {
+ return false;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GT_Slot_Render.java b/src/main/java/gregtech/api/gui/GT_Slot_Render.java
new file mode 100644
index 0000000000..ae03ce83ea
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GT_Slot_Render.java
@@ -0,0 +1,24 @@
+package gregtech.api.gui;
+
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.tileentity.TileEntity;
+
+public class GT_Slot_Render extends GT_Slot_Holo {
+
+ public GT_Slot_Render(IInventory inventory, int slotIndex, int xPos, int yPos) {
+ super(inventory, slotIndex, xPos, yPos, false, false, 0);
+ }
+
+ /**
+ * NEI has a nice and "useful" Delete-All Function, which would delete the Content of this Slot. This is here to
+ * prevent that.
+ */
+ @Override
+ public void putStack(ItemStack aStack) {
+ if (inventory instanceof TileEntity && ((TileEntity) inventory).getWorldObj().isRemote) {
+ inventory.setInventorySlotContents(getSlotIndex(), aStack);
+ }
+ onSlotChanged();
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GUIHost.java b/src/main/java/gregtech/api/gui/GUIHost.java
new file mode 100644
index 0000000000..bbb94317c4
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GUIHost.java
@@ -0,0 +1,56 @@
+package gregtech.api.gui;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.item.ItemStack;
+
+import com.gtnewhorizons.modularui.api.screen.ITileWithModularUI;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+public interface GUIHost extends ITileWithModularUI {
+
+ @Nonnull
+ @Override
+ default ModularWindow createWindow(UIBuildContext uiContext) {
+ Objects.requireNonNull(uiContext);
+ GUIProvider<?> gui = getGUI(uiContext);
+ return gui.openGUI(uiContext);
+ }
+
+ /**
+ * Width of the GUI when its being displayed
+ */
+ default int getWidth() {
+ return 170;
+ }
+
+ default int getHeight() {
+ return 192;
+ }
+
+ @Nonnull
+ GUIProvider<?> getGUI(@Nonnull UIBuildContext uiContext);
+
+ ItemStack getAsItem();
+
+ String getMachineName();
+
+ default boolean hasItemInput() {
+ return true;
+ }
+
+ default boolean hasItemOutput() {
+ return true;
+ }
+
+ default boolean hasFluidInput() {
+ return true;
+ }
+
+ default boolean hasFluidOutput() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/GUIProvider.java b/src/main/java/gregtech/api/gui/GUIProvider.java
new file mode 100644
index 0000000000..6fec4aa52a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/GUIProvider.java
@@ -0,0 +1,38 @@
+package gregtech.api.gui;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+public abstract class GUIProvider<T extends GUIHost> {
+
+ @Nonnull
+ protected final T host;
+
+ public GUIProvider(@Nonnull T host) {
+ this.host = host;
+ }
+
+ @Nonnull
+ public ModularWindow openGUI(@Nonnull UIBuildContext uiContext) {
+ Builder builder = Objects.requireNonNull(ModularWindow.builder(host.getWidth(), host.getHeight()));
+ if (shouldBindPlayerInventory()) {
+ builder.bindPlayerInventory(uiContext.getPlayer());
+ }
+ attachSynchHandlers(builder, uiContext);
+ addWidgets(builder, uiContext);
+ return Objects.requireNonNull(builder.build());
+ }
+
+ protected abstract void attachSynchHandlers(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext);
+
+ protected abstract void addWidgets(@Nonnull Builder builder, @Nonnull UIBuildContext uiContext);
+
+ protected boolean shouldBindPlayerInventory() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/FallbackableSteamTexture.java b/src/main/java/gregtech/api/gui/modularui/FallbackableSteamTexture.java
new file mode 100644
index 0000000000..8de4bc4536
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/FallbackableSteamTexture.java
@@ -0,0 +1,89 @@
+package gregtech.api.gui.modularui;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.client.Minecraft;
+
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+
+import gregtech.api.enums.SteamVariant;
+
+public class FallbackableSteamTexture {
+
+ private final SteamTexture candidate;
+ private final Object fallback;
+ private final Map<SteamVariant, Boolean> useFallbackMap = new HashMap<>();
+
+ private static final List<FallbackableSteamTexture> ALL_INSTANCES = new ArrayList<>();
+
+ public FallbackableSteamTexture(SteamTexture candidate, SteamTexture fallback) {
+ this(candidate, (Object) fallback);
+ }
+
+ public FallbackableSteamTexture(SteamTexture candidate, FallbackableSteamTexture fallback) {
+ this(candidate, (Object) fallback);
+ }
+
+ public FallbackableSteamTexture(SteamTexture fallback) {
+ this(null, fallback);
+ }
+
+ private FallbackableSteamTexture(SteamTexture candidate, Object fallback) {
+ this.candidate = candidate;
+ this.fallback = fallback;
+ ALL_INSTANCES.add(this);
+ }
+
+ public UITexture get(SteamVariant steamVariant) {
+ verifyCandidate(steamVariant);
+ if (useFallbackMap.get(steamVariant)) {
+ return castFallback(steamVariant);
+ } else {
+ return candidate.get(steamVariant);
+ }
+ }
+
+ private void verifyCandidate(SteamVariant steamVariant) {
+ if (useFallbackMap.get(steamVariant) == null) {
+ boolean useFallback;
+ if (NetworkUtils.isDedicatedClient()) {
+ if (candidate == null) {
+ useFallback = true;
+ } else {
+ try {
+ Minecraft.getMinecraft()
+ .getResourceManager()
+ .getResource(candidate.get(steamVariant).location);
+ useFallback = false;
+ } catch (IOException e) {
+ useFallback = true;
+ }
+ }
+ } else {
+ useFallback = true;
+ }
+ useFallbackMap.put(steamVariant, useFallback);
+ }
+ }
+
+ private UITexture castFallback(SteamVariant steamVariant) {
+ if (fallback instanceof SteamTexture) {
+ return ((SteamTexture) fallback).get(steamVariant);
+ } else if (fallback instanceof FallbackableSteamTexture) {
+ return ((FallbackableSteamTexture) fallback).get(steamVariant);
+ } else {
+ throw new RuntimeException("Unexpected type found for fallback: " + fallback.getClass());
+ }
+ }
+
+ public static void reload() {
+ for (FallbackableSteamTexture t : ALL_INSTANCES) {
+ t.useFallbackMap.clear();
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/GT_CoverUIBuildContext.java b/src/main/java/gregtech/api/gui/modularui/GT_CoverUIBuildContext.java
new file mode 100644
index 0000000000..f98d6099fc
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/GT_CoverUIBuildContext.java
@@ -0,0 +1,74 @@
+package gregtech.api.gui.modularui;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.api.interfaces.tileentity.ICoverable;
+
+public class GT_CoverUIBuildContext extends UIBuildContext {
+
+ // cover data is not synced to client, while ID is
+ private final int coverID;
+ private final ForgeDirection side;
+ private final ICoverable tile;
+ private final boolean anotherWindow;
+ private final int guiColorization;
+
+ /**
+ * @param player Player opened this UI
+ * @param coverID See {@link ICoverable#getCoverIDAtSide}
+ * @param side Side this cover is attached to
+ * @param tile Tile this cover is attached to
+ * @param anotherWindow If cover UI is shown on top of another window
+ * @param guiColorization The color used to render machine's GUI
+ */
+ public GT_CoverUIBuildContext(EntityPlayer player, int coverID, ForgeDirection side, ICoverable tile,
+ boolean anotherWindow, int guiColorization) {
+ super(player);
+ this.coverID = coverID;
+ this.side = side;
+ this.tile = tile;
+ this.anotherWindow = anotherWindow;
+ this.guiColorization = guiColorization;
+ }
+
+ /**
+ * @param player Player opened this UI
+ * @param coverID See {@link ICoverable#getCoverIDAtSide}
+ * @param side Side this cover is attached to
+ * @param tile Tile this cover is attached to
+ * @param anotherWindow If cover GUI is shown in opened on top of another window
+ */
+ public GT_CoverUIBuildContext(EntityPlayer player, int coverID, ForgeDirection side, ICoverable tile,
+ boolean anotherWindow) {
+ this(player, coverID, side, tile, anotherWindow, tile.getGUIColorization());
+ }
+
+ public int getCoverID() {
+ return coverID;
+ }
+
+ public ForgeDirection getCoverSide() {
+ return side;
+ }
+
+ /**
+ * Note that this will return different object between client v.s. server side on SP.
+ */
+ public ICoverable getTile() {
+ return tile;
+ }
+
+ /**
+ * If cover GUI is shown in opened on top of another window.
+ */
+ public boolean isAnotherWindow() {
+ return anotherWindow;
+ }
+
+ public int getGuiColorization() {
+ return guiColorization;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/GT_UIInfos.java b/src/main/java/gregtech/api/gui/modularui/GT_UIInfos.java
new file mode 100644
index 0000000000..89a0835f13
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/GT_UIInfos.java
@@ -0,0 +1,188 @@
+package gregtech.api.gui.modularui;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.UIInfos;
+import com.gtnewhorizons.modularui.api.screen.ITileWithModularUI;
+import com.gtnewhorizons.modularui.api.screen.ModularUIContext;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.builder.UIBuilder;
+import com.gtnewhorizons.modularui.common.builder.UIInfo;
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.internal.wrapper.ModularGui;
+import com.gtnewhorizons.modularui.common.internal.wrapper.ModularUIContainer;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords;
+import gregtech.api.net.GT_Packet_SendCoverData;
+import gregtech.api.util.GT_CoverBehaviorBase;
+
+public class GT_UIInfos {
+
+ public static void init() {}
+
+ /**
+ * Generator for {@link UIInfo} which is responsible for registering and opening UIs. Unlike
+ * {@link com.gtnewhorizons.modularui.api.UIInfos#TILE_MODULAR_UI}, this accepts custom constructors for UI. <br>
+ * Do NOT run {@link UIBuilder#build} on-the-fly, otherwise MP client won't register UIs. Instead, store to static
+ * field, just like {@link #GTTileEntityDefaultUI}. Such mistake can be easily overlooked by testing only SP.
+ */
+ public static final Function<ContainerConstructor, UIInfo<?, ?>> GTTileEntityUIFactory = containerConstructor -> UIBuilder
+ .of()
+ .container((player, world, x, y, z) -> {
+ TileEntity te = world.getTileEntity(x, y, z);
+ if (te instanceof ITileWithModularUI mui) {
+ return createTileEntityContainer(player, mui::createWindow, te::markDirty, containerConstructor);
+ }
+ return null;
+ })
+ .gui(((player, world, x, y, z) -> {
+ if (!world.isRemote) return null;
+ TileEntity te = world.getTileEntity(x, y, z);
+ if (te instanceof ITileWithModularUI mui) {
+ return createTileEntityGuiContainer(player, mui::createWindow, containerConstructor);
+ }
+ return null;
+ }))
+ .build();
+
+ private static final UIInfo<?, ?> GTTileEntityDefaultUI = GTTileEntityUIFactory.apply(ModularUIContainer::new);
+
+ private static final Map<ForgeDirection, UIInfo<?, ?>> coverUI = new HashMap<>();
+
+ static {
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ coverUI.put(
+ side,
+ UIBuilder.of()
+ .container((player, world, x, y, z) -> {
+ final TileEntity te = world.getTileEntity(x, y, z);
+ if (!(te instanceof ICoverable gtTileEntity)) return null;
+ final GT_CoverBehaviorBase<?> cover = gtTileEntity.getCoverBehaviorAtSideNew(side);
+ return createCoverContainer(
+ player,
+ cover::createWindow,
+ te::markDirty,
+ gtTileEntity.getCoverIDAtSide(side),
+ side,
+ gtTileEntity);
+ })
+ .gui((player, world, x, y, z) -> {
+ if (!world.isRemote) return null;
+ final TileEntity te = world.getTileEntity(x, y, z);
+ if (!(te instanceof ICoverable gtTileEntity)) return null;
+ final GT_CoverBehaviorBase<?> cover = gtTileEntity.getCoverBehaviorAtSideNew(side);
+ return createCoverGuiContainer(
+ player,
+ cover::createWindow,
+ gtTileEntity.getCoverIDAtSide(side),
+ side,
+ gtTileEntity);
+ })
+ .build());
+ }
+ }
+
+ /**
+ * Opens TileEntity UI, created by {@link ITileWithModularUI#createWindow}.
+ */
+ public static void openGTTileEntityUI(IHasWorldObjectAndCoords aTileEntity, EntityPlayer aPlayer) {
+ if (aTileEntity.isClientSide()) return;
+ GTTileEntityDefaultUI.open(
+ aPlayer,
+ aTileEntity.getWorld(),
+ aTileEntity.getXCoord(),
+ aTileEntity.getYCoord(),
+ aTileEntity.getZCoord());
+ }
+
+ /**
+ * Opens cover UI, created by {@link GT_CoverBehaviorBase#createWindow}.
+ */
+ public static void openCoverUI(ICoverable tileEntity, EntityPlayer player, ForgeDirection side) {
+ if (tileEntity.isClientSide()) return;
+
+ GT_Values.NW.sendToPlayer(
+ new GT_Packet_SendCoverData(
+ side,
+ tileEntity.getCoverIDAtSide(side),
+ tileEntity.getComplexCoverDataAtSide(side),
+ tileEntity),
+ (EntityPlayerMP) player);
+
+ coverUI.get(side)
+ .open(
+ player,
+ tileEntity.getWorld(),
+ tileEntity.getXCoord(),
+ tileEntity.getYCoord(),
+ tileEntity.getZCoord());
+ }
+
+ /**
+ * Opens UI for player's item, created by
+ * {@link com.gtnewhorizons.modularui.api.screen.IItemWithModularUI#createWindow}.
+ */
+ public static void openPlayerHeldItemUI(EntityPlayer player) {
+ if (NetworkUtils.isClient()) return;
+ UIInfos.PLAYER_HELD_ITEM_UI.open(player);
+ }
+
+ private static ModularUIContainer createTileEntityContainer(EntityPlayer player,
+ Function<UIBuildContext, ModularWindow> windowCreator, Runnable onWidgetUpdate,
+ ContainerConstructor containerCreator) {
+ final UIBuildContext buildContext = new UIBuildContext(player);
+ final ModularWindow window = windowCreator.apply(buildContext);
+ if (window == null) return null;
+ return containerCreator.of(new ModularUIContext(buildContext, onWidgetUpdate), window);
+ }
+
+ @SideOnly(Side.CLIENT)
+ private static ModularGui createTileEntityGuiContainer(EntityPlayer player,
+ Function<UIBuildContext, ModularWindow> windowCreator, ContainerConstructor containerConstructor) {
+ final ModularUIContainer container = createTileEntityContainer(
+ player,
+ windowCreator,
+ null,
+ containerConstructor);
+ if (container == null) return null;
+ return new ModularGui(container);
+ }
+
+ private static ModularUIContainer createCoverContainer(EntityPlayer player,
+ Function<GT_CoverUIBuildContext, ModularWindow> windowCreator, Runnable onWidgetUpdate, int coverID,
+ ForgeDirection side, ICoverable tile) {
+ final GT_CoverUIBuildContext buildContext = new GT_CoverUIBuildContext(player, coverID, side, tile, false);
+ final ModularWindow window = windowCreator.apply(buildContext);
+ if (window == null) return null;
+ return new ModularUIContainer(new ModularUIContext(buildContext, onWidgetUpdate), window);
+ }
+
+ @SideOnly(Side.CLIENT)
+ private static ModularGui createCoverGuiContainer(EntityPlayer player,
+ Function<GT_CoverUIBuildContext, ModularWindow> windowCreator, int coverID, ForgeDirection side,
+ ICoverable tile) {
+ final ModularUIContainer container = createCoverContainer(player, windowCreator, null, coverID, side, tile);
+ if (container == null) {
+ return null;
+ }
+ return new ModularGui(container);
+ }
+
+ @FunctionalInterface
+ public interface ContainerConstructor {
+
+ ModularUIContainer of(ModularUIContext context, ModularWindow mainWindow);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java b/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java
new file mode 100644
index 0000000000..b200e16d47
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/GT_UITextures.java
@@ -0,0 +1,488 @@
+package gregtech.api.gui.modularui;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import com.gtnewhorizons.modularui.api.drawable.AdaptableUITexture;
+import com.gtnewhorizons.modularui.api.drawable.FallbackableUITexture;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+public class GT_UITextures {
+
+ public static final UITexture TRANSPARENT = UITexture.fullImage(GregTech.ID, "gui/picture/transparent");
+
+ public static final AdaptableUITexture BACKGROUND_SINGLEBLOCK_DEFAULT = AdaptableUITexture
+ .of(GregTech.ID, "gui/background/singleblock_default", 176, 166, 4);
+ public static final SteamTexture BACKGROUND_STEAM = SteamTexture
+ .adaptableTexture(GregTech.ID, "gui/background/%s", 176, 166, 4);
+ public static final UITexture BACKGROUND_FUSION_COMPUTER = UITexture
+ .fullImage(GregTech.ID, "gui/background/fusion_computer");
+ public static final AdaptableUITexture BACKGROUND_TEXT_FIELD = AdaptableUITexture
+ .of(GregTech.ID, "gui/background/text_field", 142, 28, 1);
+ public static final AdaptableUITexture BACKGROUND_TEXT_FIELD_LIGHT_GRAY = AdaptableUITexture
+ .of(GregTech.ID, "gui/background/text_field_light_gray", 61, 12, 1);
+ public static final AdaptableUITexture BACKGROUND_NEI_SINGLE_RECIPE = AdaptableUITexture
+ .of(GregTech.ID, "gui/background/nei_single_recipe.png", 64, 64, 2);
+
+ public static final SteamTexture SLOT_ITEM_STEAM = SteamTexture.fullImage(GregTech.ID, "gui/slot/item_%s");
+ public static final SteamTexture SLOT_FLUID_STEAM = SteamTexture.fullImage(GregTech.ID, "gui/slot/fluid_%s");
+ public static final AdaptableUITexture SLOT_DARK_GRAY = AdaptableUITexture
+ .of(GregTech.ID, "gui/slot/dark_gray", 18, 18, 1);
+ public static final AdaptableUITexture SLOT_MAINTENANCE = AdaptableUITexture
+ .of(GregTech.ID, "gui/slot/maintenance", 20, 20, 1);
+ public static final AdaptableUITexture SLOT_UPLIFTED = AdaptableUITexture
+ .of(GregTech.ID, "gui/slot/uplifted", 18, 18, 1);
+
+ public static final UITexture OVERLAY_SLOT_ARROW_ME = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/arrow_me");
+ public static final UITexture OVERLAY_SLOT_PATTERN_ME = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/pattern_me");
+
+ public static final UITexture OVERLAY_SLOT_BEAKER_1 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/beaker_1");
+ public static final UITexture OVERLAY_SLOT_BEAKER_2 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/beaker_2");
+ public static final UITexture OVERLAY_SLOT_BEE_DRONE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/bee_drone");
+ public static final UITexture OVERLAY_SLOT_BEE_QUEEN = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/bee_queen");
+ public static final UITexture OVERLAY_SLOT_BENDER = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/bender");
+ public static final UITexture OVERLAY_SLOT_BOX = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/box");
+ public static final UITexture OVERLAY_SLOT_BOXED = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/boxed");
+ public static final UITexture OVERLAY_SLOT_CANISTER = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/canister");
+ public static final SteamTexture OVERLAY_SLOT_CANISTER_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/canister_%s");
+ public static final UITexture OVERLAY_SLOT_CANNER = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/canner");
+ public static final UITexture OVERLAY_SLOT_CAULDRON = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/cauldron");
+ public static final UITexture OVERLAY_SLOT_CENTRIFUGE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/centrifuge");
+ public static final UITexture OVERLAY_SLOT_CENTRIFUGE_FLUID = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/centrifuge_fluid");
+ public static final SteamTexture OVERLAY_SLOT_CENTRIFUGE_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/centrifuge_%s");
+ public static final UITexture OVERLAY_SLOT_CHARGER = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/charger");
+ public static final UITexture OVERLAY_SLOT_CHARGER_FLUID = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/charger_fluid");
+ public static final UITexture OVERLAY_SLOT_CIRCUIT = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/circuit");
+ public static final SteamTexture OVERLAY_SLOT_COAL_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/coal_%s");
+ public static final UITexture OVERLAY_SLOT_COMPRESSOR = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/compressor");
+ public static final SteamTexture OVERLAY_SLOT_COMPRESSOR_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/compressor_%s");
+ public static final UITexture OVERLAY_SLOT_CRUSHED_ORE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/crushed_ore");
+ public static final SteamTexture OVERLAY_SLOT_CRUSHED_ORE_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/crushed_ore_%s");
+ public static final UITexture OVERLAY_SLOT_CUTTER_SLICED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/cutter_sliced");
+ public static final UITexture OVERLAY_SLOT_DATA_ORB = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/data_orb");
+ public static final UITexture OVERLAY_SLOT_DATA_STICK = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/data_stick");
+ public static final UITexture OVERLAY_SLOT_DUST = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/dust");
+ public static final SteamTexture OVERLAY_SLOT_DUST_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/dust_%s");
+ public static final SteamTexture OVERLAY_SLOT_BLOCK_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/block_%s");
+ public static final UITexture OVERLAY_SLOT_EXPLOSIVE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/explosive");
+ public static final UITexture OVERLAY_SLOT_EXTRUDER_SHAPE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/extruder_shape");
+ public static final UITexture OVERLAY_SLOT_FURNACE = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/furnace");
+ public static final SteamTexture OVERLAY_SLOT_FURNACE_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/furnace_%s");
+ public static final UITexture OVERLAY_SLOT_GEM = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/gem");
+ public static final UITexture OVERLAY_SLOT_HAMMER = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/hammer");
+ public static final SteamTexture OVERLAY_SLOT_HAMMER_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/hammer_%s");
+ public static final UITexture OVERLAY_SLOT_HEATER_1 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/heater_1");
+ public static final UITexture OVERLAY_SLOT_HEATER_2 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/heater_2");
+ public static final UITexture OVERLAY_SLOT_IMPLOSION = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/implosion");
+ public static final UITexture OVERLAY_SLOT_IN = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/in");
+ public static final SteamTexture OVERLAY_SLOT_IN_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/in_%s");
+ public static final SteamTexture OVERLAY_SLOT_INGOT_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/ingot_%s");
+ public static final UITexture OVERLAY_SLOT_INT_CIRCUIT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/int_circuit");
+ public static final UITexture OVERLAY_SLOT_LENS = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/lens");
+ public static final UITexture OVERLAY_SLOT_MICROSCOPE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/microscope");
+ public static final UITexture OVERLAY_SLOT_MINING_PIPE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/mining_pipe");
+ public static final UITexture OVERLAY_SLOT_MOLD = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/mold");
+ public static final UITexture OVERLAY_SLOT_MOLECULAR_1 = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/molecular_1");
+ public static final UITexture OVERLAY_SLOT_MOLECULAR_2 = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/molecular_2");
+ public static final UITexture OVERLAY_SLOT_MOLECULAR_3 = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/molecular_3");
+ public static final UITexture OVERLAY_SLOT_OUT = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/out");
+ public static final SteamTexture OVERLAY_SLOT_OUT_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/out_%s");
+ public static final UITexture OVERLAY_SLOT_PAGE_BLANK = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/page_blank");
+ public static final UITexture OVERLAY_SLOT_PAGE_PRINTED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/page_printed");
+ public static final UITexture OVERLAY_SLOT_PRESS_1 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/press_1");
+ public static final UITexture OVERLAY_SLOT_PRESS_2 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/press_2");
+ public static final UITexture OVERLAY_SLOT_PRESS_3 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/press_3");
+ public static final UITexture OVERLAY_SLOT_RECYCLE = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/recycle");
+ public static final UITexture OVERLAY_SLOT_ROD_1 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/rod_1");
+ public static final UITexture OVERLAY_SLOT_ROD_2 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/rod_2");
+ public static final UITexture OVERLAY_SLOT_SLICE_SHAPE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/slice_shape");
+ public static final UITexture OVERLAY_SLOT_SLICER_SLICED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_slot/slicer_sliced");
+ public static final UITexture OVERLAY_SLOT_SQUARE = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/square");
+ public static final UITexture OVERLAY_SLOT_UUA = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/uua");
+ public static final UITexture OVERLAY_SLOT_UUM = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/uum");
+ public static final UITexture OVERLAY_SLOT_VIAL_1 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/vial_1");
+ public static final UITexture OVERLAY_SLOT_VIAL_2 = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/vial_2");
+ public static final UITexture OVERLAY_SLOT_WIREMILL = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/wiremill");
+ public static final UITexture OVERLAY_SLOT_WRENCH = UITexture.fullImage(GregTech.ID, "gui/overlay_slot/wrench");
+ public static final UITexture[] OVERLAY_SLOTS_NUMBER = IntStream.range(0, 12)
+ .mapToObj(i -> UITexture.fullImage(GregTech.ID, "gui/overlay_slot/number_" + i))
+ .collect(Collectors.toList())
+ .toArray(new UITexture[0]);
+
+ public static final UITexture PROGRESSBAR_ARROW = UITexture.fullImage(GregTech.ID, "gui/progressbar/arrow");
+ public static final SteamTexture PROGRESSBAR_ARROW_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/arrow_%s");
+ public static final SteamTexture PROGRESSBAR_ARROW_2_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/arrow_2_%s");
+ public static final UITexture PROGRESSBAR_ARROW_MULTIPLE = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/arrow_multiple");
+ public static final UITexture PROGRESSBAR_ASSEMBLE = UITexture.fullImage(GregTech.ID, "gui/progressbar/assemble");
+ public static final UITexture PROGRESSBAR_ASSEMBLY_LINE_1 = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/assemblyline_1");
+ public static final UITexture PROGRESSBAR_ASSEMBLY_LINE_2 = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/assemblyline_2");
+ public static final UITexture PROGRESSBAR_ASSEMBLY_LINE_3 = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/assemblyline_3");
+ public static final UITexture PROGRESSBAR_BATH = UITexture.fullImage(GregTech.ID, "gui/progressbar/bath");
+ public static final UITexture PROGRESSBAR_BENDING = UITexture.fullImage(GregTech.ID, "gui/progressbar/bending");
+ public static final SteamTexture PROGRESSBAR_BOILER_EMPTY_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/boiler_empty_%s");
+ public static final UITexture PROGRESSBAR_BOILER_HEAT = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/boiler_heat");
+ public static final UITexture PROGRESSBAR_BOILER_STEAM = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/boiler_steam");
+ public static final UITexture PROGRESSBAR_BOILER_WATER = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/boiler_water");
+ public static final UITexture PROGRESSBAR_CANNER = UITexture.fullImage(GregTech.ID, "gui/progressbar/canner");
+ public static final UITexture PROGRESSBAR_CIRCUIT_ASSEMBLER = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/circuit_assembler");
+ public static final UITexture PROGRESSBAR_COMPRESS = UITexture.fullImage(GregTech.ID, "gui/progressbar/compress");
+ public static final SteamTexture PROGRESSBAR_COMPRESS_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/compress_%s");
+ public static final UITexture PROGRESSBAR_CUT = UITexture.fullImage(GregTech.ID, "gui/progressbar/cut");
+ public static final UITexture PROGRESSBAR_EXTRACT = UITexture.fullImage(GregTech.ID, "gui/progressbar/extract");
+ public static final SteamTexture PROGRESSBAR_EXTRACT_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/extract_%s");
+ public static final UITexture PROGRESSBAR_EXTRUDE = UITexture.fullImage(GregTech.ID, "gui/progressbar/extrude");
+ public static final SteamTexture PROGRESSBAR_FUEL_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/fuel_%s");
+ public static final UITexture PROGRESSBAR_HAMMER = UITexture.fullImage(GregTech.ID, "gui/progressbar/hammer");
+ public static final UITexture PROGRESSBAR_HAMMER_BASE = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/hammer_base");
+ public static final SteamTexture PROGRESSBAR_HAMMER_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/hammer_%s");
+ public static final SteamTexture PROGRESSBAR_HAMMER_BASE_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/hammer_base_%s");
+ public static final UITexture PROGRESSBAR_LATHE = UITexture.fullImage(GregTech.ID, "gui/progressbar/lathe");
+ public static final UITexture PROGRESSBAR_LATHE_BASE = UITexture
+ .fullImage(GregTech.ID, "gui/progressbar/lathe_base");
+ public static final UITexture PROGRESSBAR_MACERATE = UITexture.fullImage(GregTech.ID, "gui/progressbar/macerate");
+ public static final SteamTexture PROGRESSBAR_MACERATE_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/progressbar/macerate_%s");
+ public static final UITexture PROGRESSBAR_MAGNET = UITexture.fullImage(GregTech.ID, "gui/progressbar/magnet");
+ public static final UITexture PROGRESSBAR_MIXER = UITexture.fullImage(GregTech.ID, "gui/progressbar/mixer");
+ public static final UITexture PROGRESSBAR_RECYCLE = UITexture.fullImage(GregTech.ID, "gui/progressbar/recycle");
+ public static final UITexture PROGRESSBAR_SIFT = UITexture.fullImage(GregTech.ID, "gui/progressbar/sift");
+ public static final UITexture PROGRESSBAR_SLICE = UITexture.fullImage(GregTech.ID, "gui/progressbar/slice");
+ public static final UITexture PROGRESSBAR_STORED_EU = UITexture.fullImage(GregTech.ID, "gui/progressbar/stored_eu");
+ public static final UITexture PROGRESSBAR_WIREMILL = UITexture.fullImage(GregTech.ID, "gui/progressbar/wiremill");
+
+ public static FallbackableUITexture fallbackableProgressbar(String name, UITexture fallback) {
+ return new FallbackableUITexture(UITexture.fullImage(GregTech.ID, "gui/progressbar/" + name), fallback);
+ }
+
+ public static final UITexture TAB_COVER_NORMAL = UITexture.fullImage(GregTech.ID, "gui/tab/cover_normal");
+ public static final UITexture TAB_COVER_HIGHLIGHT = UITexture.fullImage(GregTech.ID, "gui/tab/cover_highlight");
+ public static final UITexture TAB_COVER_DISABLED = UITexture.fullImage(GregTech.ID, "gui/tab/cover_disabled");
+ public static final SteamTexture TAB_COVER_STEAM_NORMAL = SteamTexture
+ .fullImage(GregTech.ID, "gui/tab/cover_%s_normal");
+ public static final SteamTexture TAB_COVER_STEAM_HIGHLIGHT = SteamTexture
+ .fullImage(GregTech.ID, "gui/tab/cover_%s_highlight");
+ public static final SteamTexture TAB_COVER_STEAM_DISABLED = SteamTexture
+ .fullImage(GregTech.ID, "gui/tab/cover_%s_disabled");
+ public static final AdaptableUITexture TAB_TITLE = AdaptableUITexture.of(GregTech.ID, "gui/tab/title", 28, 28, 4);
+ public static final AdaptableUITexture TAB_TITLE_DARK = AdaptableUITexture
+ .of(GregTech.ID, "gui/tab/title_dark", 28, 28, 4);
+ public static final SteamTexture TAB_TITLE_STEAM = SteamTexture
+ .adaptableTexture(GregTech.ID, "gui/tab/title_%s", 28, 28, 4);
+ public static final SteamTexture TAB_TITLE_DARK_STEAM = SteamTexture
+ .adaptableTexture(GregTech.ID, "gui/tab/title_dark_%s", 28, 28, 4);
+ public static final AdaptableUITexture TAB_TITLE_ANGULAR = AdaptableUITexture
+ .of(GregTech.ID, "gui/tab/title_angular", 28, 28, 4);
+ public static final SteamTexture TAB_TITLE_ANGULAR_STEAM = SteamTexture
+ .adaptableTexture(GregTech.ID, "gui/tab/title_angular_%s", 28, 28, 4);
+
+ public static final UITexture BUTTON_STANDARD = AdaptableUITexture
+ .of(GregTech.ID, "gui/button/standard", 18, 18, 1);
+ public static final UITexture BUTTON_STANDARD_PRESSED = AdaptableUITexture
+ .of(GregTech.ID, "gui/button/standard_pressed", 18, 18, 1);
+ public static final UITexture BUTTON_STANDARD_DISABLED = AdaptableUITexture
+ .of(GregTech.ID, "gui/button/standard_disabled", 18, 18, 1);
+ public static final UITexture BUTTON_STANDARD_TOGGLE = AdaptableUITexture
+ .of(GregTech.ID, "gui/button/standard_toggle", 18, 18, 1);
+ public static final UITexture BUTTON_STANDARD_TOGGLE_DISABLED = AdaptableUITexture
+ .of(GregTech.ID, "gui/button/standard_toggle_disabled", 18, 18, 1);
+ public static final UITexture BUTTON_COVER_NORMAL = UITexture.fullImage(GregTech.ID, "gui/button/cover_normal");
+ public static final UITexture BUTTON_COVER_NORMAL_HOVERED = UITexture
+ .fullImage(GregTech.ID, "gui/button/cover_normal_hovered");
+ public static final UITexture BUTTON_COVER_NORMAL_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/button/cover_normal_disabled");
+
+ public static final UITexture OVERLAY_BUTTON_DISABLE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/disable");
+ public static final UITexture OVERLAY_BUTTON_REDSTONE_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/redstone_off");
+ public static final UITexture OVERLAY_BUTTON_REDSTONE_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/redstone_on");
+ public static final UITexture OVERLAY_BUTTON_POWER_SWITCH_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/power_switch_on");
+ public static final UITexture OVERLAY_BUTTON_POWER_SWITCH_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/power_switch_off");
+ public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_NONE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/void_excess_none");
+ public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ITEM = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/void_excess_item");
+ public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_FLUID = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/void_excess_fluid");
+ public static final UITexture OVERLAY_BUTTON_VOID_EXCESS_ALL = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/void_excess_all");
+ public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/input_separation_on");
+ public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_ON_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/input_separation_on_disabled");
+ public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/input_separation_off");
+ public static final UITexture OVERLAY_BUTTON_INPUT_SEPARATION_OFF_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/input_separation_off_disabled");
+ public static final UITexture OVERLAY_BUTTON_RECIPE_LOCKED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/recipe_locked");
+ public static final UITexture OVERLAY_BUTTON_RECIPE_LOCKED_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/recipe_locked_disabled");
+ public static final UITexture OVERLAY_BUTTON_RECIPE_UNLOCKED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/recipe_unlocked");
+ public static final UITexture OVERLAY_BUTTON_RECIPE_UNLOCKED_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/recipe_unlocked_disabled");
+ public static final UITexture OVERLAY_BUTTON_BATCH_MODE_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_on");
+ public static final UITexture OVERLAY_BUTTON_BATCH_MODE_ON_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_on_disabled");
+ public static final UITexture OVERLAY_BUTTON_BATCH_MODE_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_off");
+ public static final UITexture OVERLAY_BUTTON_BATCH_MODE_OFF_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/batch_mode_off_disabled");
+ public static final UITexture OVERLAY_BUTTON_FORBIDDEN = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/forbidden");
+ public static final UITexture OVERLAY_BUTTON_LOCKED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/lock_small");
+ public static final UITexture OVERLAY_BUTTON_DOWN_TIERING_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/down_tiering_on");
+ public static final UITexture OVERLAY_BUTTON_DOWN_TIERING_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/down_tiering_off");
+ public static final UITexture OVERLAY_BUTTON_CHECKMARK = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/checkmark");
+ public static final UITexture OVERLAY_BUTTON_CROSS = UITexture.fullImage(GregTech.ID, "gui/overlay_button/cross");
+ public static final UITexture OVERLAY_BUTTON_WHITELIST = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/whitelist");
+ public static final UITexture OVERLAY_BUTTON_BLACKLIST = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/blacklist");
+ public static final UITexture OVERLAY_BUTTON_PROGRESS = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/progress");
+ public static final UITexture OVERLAY_BUTTON_EXPORT = UITexture.fullImage(GregTech.ID, "gui/overlay_button/export");
+ public static final UITexture OVERLAY_BUTTON_IMPORT = UITexture.fullImage(GregTech.ID, "gui/overlay_button/import");
+ public static final UITexture OVERLAY_BUTTON_AUTOOUTPUT_ITEM = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/autooutput_item");
+ public static final UITexture OVERLAY_BUTTON_AUTOOUTPUT_FLUID = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/autooutput_fluid");
+ public static final UITexture OVERLAY_BUTTON_ALLOW_INPUT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/allow_input");
+ public static final UITexture OVERLAY_BUTTON_ALLOW_OUTPUT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/allow_output");
+ public static final UITexture OVERLAY_BUTTON_AUTOPULL_ME = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/auto_pull_me");
+ public static final UITexture OVERLAY_BUTTON_AUTOPULL_ME_DISABLED = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/auto_pull_me_disabled");
+ public static final UITexture OVERLAY_BUTTON_BLOCK_INPUT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/block_input");
+ public static final UITexture OVERLAY_BUTTON_BLOCK_OUTPUT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/block_output");
+ public static final UITexture OVERLAY_BUTTON_ARROW_GREEN_UP = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/arrow_green_up");
+ public static final UITexture OVERLAY_BUTTON_ARROW_GREEN_DOWN = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/arrow_green_down");
+ public static final UITexture OVERLAY_BUTTON_CYCLIC = UITexture.fullImage(GregTech.ID, "gui/overlay_button/cyclic");
+ public static final UITexture OVERLAY_BUTTON_EMIT_ENERGY = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/emit_energy");
+ public static final UITexture OVERLAY_BUTTON_EMIT_REDSTONE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/emit_redstone");
+ public static final UITexture OVERLAY_BUTTON_INVERT_REDSTONE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/invert_redstone");
+ public static final UITexture OVERLAY_BUTTON_STOCKING_MODE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/stocking_mode");
+ public static final UITexture OVERLAY_BUTTON_INVERT_FILTER = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/invert_filter");
+ public static final UITexture OVERLAY_BUTTON_NBT = UITexture.fullImage(GregTech.ID, "gui/overlay_button/nbt");
+ public static final UITexture OVERLAY_BUTTON_PRINT = UITexture.fullImage(GregTech.ID, "gui/overlay_button/print");
+ public static final UITexture OVERLAY_BUTTON_TRANSPOSE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/transpose");
+ public static final UITexture OVERLAY_BUTTON_SORTING_MODE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/sorting_mode");
+ public static final UITexture OVERLAY_BUTTON_ONE_STACK_LIMIT = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/one_stack_limit");
+ public static final UITexture OVERLAY_BUTTON_BOUNDING_BOX = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/bounding_box");
+ public static final UITexture OVERLAY_BUTTON_MINUS_SMALL = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/minus_small");
+ public static final UITexture OVERLAY_BUTTON_MINUS_LARGE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/minus_large");
+ public static final UITexture OVERLAY_BUTTON_PLUS_SMALL = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/plus_small");
+ public static final UITexture OVERLAY_BUTTON_PLUS_LARGE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/plus_large");
+ public static final UITexture OVERLAY_BUTTON_GATE_AND = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/gate_and");
+ public static final UITexture OVERLAY_BUTTON_GATE_NAND = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/gate_nand");
+ public static final UITexture OVERLAY_BUTTON_GATE_OR = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/gate_or");
+ public static final UITexture OVERLAY_BUTTON_GATE_NOR = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/gate_nor");
+ public static final UITexture OVERLAY_BUTTON_ANALOG = UITexture.fullImage(GregTech.ID, "gui/overlay_button/analog");
+ public static final UITexture OVERLAY_BUTTON_LOCK = UITexture.fullImage(GregTech.ID, "gui/overlay_button/lock");
+ public static final UITexture OVERLAY_BUTTON_INPUT_FROM_OUTPUT_SIDE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/input_from_output_side");
+ public static final UITexture OVERLAY_BUTTON_TANK_VOID_EXCESS = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/tank_void_excess");
+ public static final UITexture OVERLAY_BUTTON_TANK_VOID_ALL = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/tank_void_all");
+ public static final UITexture OVERLAY_BUTTON_NEI = UITexture.fullImage(GregTech.ID, "gui/overlay_button/nei");
+ public static final UITexture OVERLAY_BUTTON_USE_PROCESSING_STATE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/use_processing_state.png");
+ public static final UITexture OVERLAY_BUTTON_USE_INVERTED_PROCESSING_STATE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/use_inverted_processing_state.png");
+ public static final UITexture OVERLAY_BUTTON_CHUNK_LOADING = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/chunkloading");
+ public static final UITexture OVERLAY_BUTTON_CHUNK_LOADING_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/chunkloading_off");
+ public static final UITexture OVERLAY_BUTTON_WORK_AREA = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/work_area");
+ public static final UITexture OVERLAY_BUTTON_REPLACE_COBBLE_ON = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/replace_cobble_on");
+ public static final UITexture OVERLAY_BUTTON_REPLACE_COBBLE_OFF = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/replace_cobble_off");
+ public static final UITexture OVERLAY_BUTTON_RETRACT_PIPE = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/retract_pipes");
+ public static final UITexture OVERLAY_BUTTON_HOURGLASS = UITexture
+ .fullImage(GregTech.ID, "gui/overlay_button/hourglass");
+
+ /**
+ * Can adjust size as needed.
+ */
+ public static final AdaptableUITexture PICTURE_SCREEN_BLACK = AdaptableUITexture
+ .of(GregTech.ID, "gui/picture/screen_black", 16, 16, 2);
+
+ public static final UITexture PICTURE_RADIATION_WARNING = UITexture
+ .fullImage(GregTech.ID, "gui/picture/radiation_warning");
+ public static final UITexture PICTURE_GT_LOGO_17x17_TRANSPARENT = UITexture
+ .fullImage(GregTech.ID, "gui/picture/gt_logo_17x17_transparent");
+ public static final UITexture PICTURE_GT_LOGO_17x17_TRANSPARENT_GRAY = UITexture
+ .fullImage(GregTech.ID, "gui/picture/gt_logo_17x17_transparent_gray");
+ public static final SteamTexture PICTURE_GT_LOGO_17x17_TRANSPARENT_STEAM = SteamTexture
+ .fullImage(GregTech.ID, "gui/picture/gt_logo_17x17_transparent_%s");
+ public static final UITexture PICTURE_GT_LOGO_18x18 = UITexture.fullImage(GregTech.ID, "gui/picture/gt_logo_18x18");
+ public static final UITexture PICTURE_GT_LOGO_19x19 = UITexture.fullImage(GregTech.ID, "gui/picture/gt_logo_19x19");
+ public static final UITexture PICTURE_INFORMATION = UITexture.fullImage(GregTech.ID, "gui/picture/information");
+ public static final UITexture PICTURE_STALLED_ELECTRICITY = UITexture
+ .fullImage(GregTech.ID, "gui/picture/stalled_electricity");
+ public static final UITexture PICTURE_STALLED_STEAM = UITexture.fullImage(GregTech.ID, "gui/picture/stalled_steam");
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_22_RED = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_22_red",
+ 87,
+ 22,
+ fromRight ? 87 - width : 0,
+ 0,
+ fromRight ? 87 : width,
+ 22);
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_22_BLUE = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_22_blue",
+ 87,
+ 22,
+ fromRight ? 87 - width : 0,
+ 0,
+ fromRight ? 87 : width,
+ 22);
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_22_WHITE = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_22_white",
+ 87,
+ 22,
+ fromRight ? 87 - width : 0,
+ 0,
+ fromRight ? 87 : width,
+ 22);
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_24_RED = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_24_red",
+ 69,
+ 24,
+ fromRight ? 69 - width : 0,
+ 0,
+ fromRight ? 69 : width,
+ 24);
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_24_BLUE = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_24_blue",
+ 69,
+ 24,
+ fromRight ? 69 - width : 0,
+ 0,
+ fromRight ? 69 : width,
+ 24);
+ public static final BiFunction<Integer, Boolean, UITexture> PICTURE_ARROW_24_WHITE = (width, fromRight) -> UITexture
+ .partly(
+ GregTech.ID,
+ "gui/picture/arrow_24_white",
+ 69,
+ 24,
+ fromRight ? 69 - width : 0,
+ 0,
+ fromRight ? 69 : width,
+ 24);
+ public static final UITexture PICTURE_FLUID_WINDOW = UITexture.fullImage(GregTech.ID, "gui/picture/fluid_window");
+ public static final UITexture PICTURE_FLUID_TANK = UITexture.fullImage(GregTech.ID, "gui/picture/fluid_tank");
+ public static final UITexture PICTURE_SLOTS_HOLO_3BY3 = UITexture
+ .fullImage(GregTech.ID, "gui/picture/slots_holo_3by3");
+ public static final UITexture PICTURE_ARROW_DOUBLE = UITexture.fullImage(GregTech.ID, "gui/picture/arrow_double");
+ public static final UITexture PICTURE_SUPER_BUFFER = UITexture.fullImage(GregTech.ID, "gui/picture/super_buffer");
+ public static final UITexture PICTURE_SQUARE_LIGHT_GRAY = UITexture
+ .fullImage(GregTech.ID, "gui/picture/square_light_gray");
+ public static final UITexture PICTURE_GAUGE = UITexture.fullImage(GregTech.ID, "gui/picture/gauge");
+ public static final UITexture PICTURE_ITEM_IN = UITexture.fullImage(GregTech.ID, "gui/picture/item_in");
+ public static final UITexture PICTURE_ITEM_OUT = UITexture.fullImage(GregTech.ID, "gui/picture/item_out");
+ public static final UITexture PICTURE_FLUID_IN = UITexture.fullImage(GregTech.ID, "gui/picture/fluid_in");
+ public static final UITexture PICTURE_FLUID_OUT = UITexture.fullImage(GregTech.ID, "gui/picture/fluid_out");
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/GUITextureSet.java b/src/main/java/gregtech/api/gui/modularui/GUITextureSet.java
new file mode 100644
index 0000000000..18d7741421
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/GUITextureSet.java
@@ -0,0 +1,156 @@
+package gregtech.api.gui.modularui;
+
+import java.util.function.Function;
+
+import com.gtnewhorizons.modularui.api.ModularUITextures;
+import com.gtnewhorizons.modularui.api.drawable.AdaptableUITexture;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.api.enums.SteamVariant;
+
+/**
+ * Set of textures that is commonly used for GUI but can vary depending on "style" of machines, e.g. bronze steam or
+ * steel steam. <br>
+ * This has builder pattern; Textures you didn't specify will fall back to default ones.
+ */
+public class GUITextureSet {
+
+ private UITexture mainBackground;
+ private UITexture itemSlot;
+ private UITexture fluidSlot;
+ private UITexture coverTabNormal;
+ private UITexture coverTabHighlight;
+ private UITexture coverTabDisabled;
+ private UITexture coverTabNormalFlipped;
+ private UITexture coverTabHighlightFlipped;
+ private UITexture coverTabDisabledFlipped;
+ private AdaptableUITexture titleTabNormal;
+ private AdaptableUITexture titleTabDark;
+ private AdaptableUITexture titleTabAngular;
+ private UITexture gregtechLogo;
+
+ public static final GUITextureSet DEFAULT = new GUITextureSet()
+ .setMainBackground(GT_UITextures.BACKGROUND_SINGLEBLOCK_DEFAULT)
+ .setItemSlot(ModularUITextures.ITEM_SLOT)
+ .setFluidSlot(ModularUITextures.FLUID_SLOT)
+ .setCoverTab(
+ GT_UITextures.TAB_COVER_NORMAL,
+ GT_UITextures.TAB_COVER_HIGHLIGHT,
+ GT_UITextures.TAB_COVER_DISABLED)
+ .setTitleTab(GT_UITextures.TAB_TITLE, GT_UITextures.TAB_TITLE_DARK, GT_UITextures.TAB_TITLE_ANGULAR)
+ .setGregTechLogo(GT_UITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT);
+
+ public static final Function<SteamVariant, GUITextureSet> STEAM = steamVariant -> new GUITextureSet()
+ .setMainBackground(GT_UITextures.BACKGROUND_STEAM.get(steamVariant))
+ .setItemSlot(GT_UITextures.SLOT_ITEM_STEAM.get(steamVariant))
+ .setFluidSlot(GT_UITextures.SLOT_FLUID_STEAM.get(steamVariant))
+ .setCoverTab(
+ GT_UITextures.TAB_COVER_STEAM_NORMAL.get(steamVariant),
+ GT_UITextures.TAB_COVER_STEAM_HIGHLIGHT.get(steamVariant),
+ GT_UITextures.TAB_COVER_STEAM_DISABLED.get(steamVariant))
+ .setTitleTab(
+ GT_UITextures.TAB_TITLE_STEAM.getAdaptable(steamVariant),
+ GT_UITextures.TAB_TITLE_DARK_STEAM.getAdaptable(steamVariant),
+ GT_UITextures.TAB_TITLE_ANGULAR_STEAM.getAdaptable(steamVariant))
+ .setGregTechLogo(GT_UITextures.PICTURE_GT_LOGO_17x17_TRANSPARENT_STEAM.get(steamVariant));
+
+ public GUITextureSet() {}
+
+ // region setters
+
+ public GUITextureSet setMainBackground(UITexture mainBackground) {
+ this.mainBackground = mainBackground;
+ return this;
+ }
+
+ public GUITextureSet setItemSlot(UITexture itemSlot) {
+ this.itemSlot = itemSlot;
+ return this;
+ }
+
+ public GUITextureSet setFluidSlot(UITexture fluidSlot) {
+ this.fluidSlot = fluidSlot;
+ return this;
+ }
+
+ public GUITextureSet setCoverTab(UITexture coverNormal, UITexture coverHighlight, UITexture coverDisabled) {
+ this.coverTabNormal = coverNormal;
+ this.coverTabHighlight = coverHighlight;
+ this.coverTabDisabled = coverDisabled;
+ this.coverTabNormalFlipped = coverNormal.getFlipped(true, false);
+ this.coverTabHighlightFlipped = coverHighlight.getFlipped(true, false);
+ this.coverTabDisabledFlipped = coverDisabled.getFlipped(true, false);
+ return this;
+ }
+
+ public GUITextureSet setTitleTab(AdaptableUITexture titleNormal, AdaptableUITexture titleDark,
+ AdaptableUITexture titleTabAngular) {
+ this.titleTabNormal = titleNormal;
+ this.titleTabDark = titleDark;
+ this.titleTabAngular = titleTabAngular;
+ return this;
+ }
+
+ public GUITextureSet setGregTechLogo(UITexture gregtechLogo) {
+ this.gregtechLogo = gregtechLogo;
+ return this;
+ }
+
+ // endregion
+
+ // region getters
+
+ public UITexture getMainBackground() {
+ return mainBackground != null ? mainBackground : DEFAULT.mainBackground;
+ }
+
+ public UITexture getItemSlot() {
+ return itemSlot != null ? itemSlot : DEFAULT.itemSlot;
+ }
+
+ public UITexture getFluidSlot() {
+ return fluidSlot != null ? fluidSlot : DEFAULT.fluidSlot;
+ }
+
+ public UITexture getCoverTabNormal() {
+ return coverTabNormal != null ? coverTabNormal : DEFAULT.coverTabNormal;
+ }
+
+ public UITexture getCoverTabHighlight() {
+ return coverTabHighlight != null ? coverTabHighlight : DEFAULT.coverTabHighlight;
+ }
+
+ public UITexture getCoverTabDisabled() {
+ return coverTabDisabled != null ? coverTabDisabled : DEFAULT.coverTabDisabled;
+ }
+
+ public UITexture getCoverTabNormalFlipped() {
+ return coverTabNormalFlipped != null ? coverTabNormalFlipped : DEFAULT.coverTabNormalFlipped;
+ }
+
+ public UITexture getCoverTabHighlightFlipped() {
+ return coverTabHighlightFlipped != null ? coverTabHighlightFlipped : DEFAULT.coverTabHighlightFlipped;
+ }
+
+ public UITexture getCoverTabDisabledFlipped() {
+ return coverTabDisabledFlipped != null ? coverTabDisabledFlipped : DEFAULT.coverTabDisabledFlipped;
+ }
+
+ public AdaptableUITexture getTitleTabNormal() {
+ return titleTabNormal != null ? titleTabNormal : DEFAULT.titleTabNormal;
+ }
+
+ public AdaptableUITexture getTitleTabDark() {
+ return titleTabDark != null ? titleTabDark : DEFAULT.titleTabDark;
+ }
+
+ public AdaptableUITexture getTitleTabAngular() {
+ return titleTabAngular != null ? titleTabAngular : DEFAULT.titleTabAngular;
+ }
+
+ public UITexture getGregTechLogo() {
+ return gregtechLogo != null ? gregtechLogo : DEFAULT.gregtechLogo;
+ }
+
+ // endregion
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/IDataFollowerWidget.java b/src/main/java/gregtech/api/gui/modularui/IDataFollowerWidget.java
new file mode 100644
index 0000000000..393b8431e2
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/IDataFollowerWidget.java
@@ -0,0 +1,50 @@
+package gregtech.api.gui.modularui;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import com.gtnewhorizons.modularui.api.widget.Widget;
+
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.util.ISerializableObject;
+import gregtech.common.gui.modularui.widget.DataControllerWidget;
+
+/**
+ * Widget whose state is controlled by specific data. Data can be anything, e.g. {@link ISerializableObject} or machine
+ * recipe mode. <br>
+ * No widgets implementing this interface should not sync; Instead, {@link DataControllerWidget} will sync data, either
+ * when this widget triggers update on client or data update is detected on server.
+ *
+ * @param <T> Data type stored in the parent widget
+ * @param <U> State type stored in this widget
+ * @see DataControllerWidget
+ */
+@SuppressWarnings("UnusedReturnValue")
+public interface IDataFollowerWidget<T, U> {
+
+ /**
+ * Sets function to get widget state from provided data. This function will be called when client receives data from
+ * server and {@link DataControllerWidget} updates all children, including this widget.
+ */
+ Widget setDataToStateGetter(Function<T, U> dataToStateGetter);
+
+ /**
+ * Sets setter called when this widget gets action from player. Basically the same functionality with widgets that
+ * have getter/setter.
+ */
+ Widget setStateSetter(Consumer<U> setter);
+
+ /**
+ * Updates state of this widget with provided data. On server {@link DataControllerWidget} won't propagate data
+ * update to this widget, so this method is client-only.
+ */
+ @SideOnly(Side.CLIENT)
+ void updateState(T data);
+
+ /**
+ * Called on {@link Widget#onPostInit}.
+ */
+ @SuppressWarnings("OverrideOnly") // So IntelliJ doesn't warn about the Widget#onPostInit link in the javadoc
+ default void onPostInit() {}
+}
diff --git a/src/main/java/gregtech/api/gui/modularui/SteamTexture.java b/src/main/java/gregtech/api/gui/modularui/SteamTexture.java
new file mode 100644
index 0000000000..301671afe8
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/modularui/SteamTexture.java
@@ -0,0 +1,62 @@
+package gregtech.api.gui.modularui;
+
+import com.gtnewhorizons.modularui.api.drawable.AdaptableUITexture;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+
+import gregtech.api.enums.SteamVariant;
+
+/**
+ * Wrapper for {@link UITexture}s used to ease in choosing between Bronze, Steel and Primitive textures.
+ */
+public class SteamTexture {
+
+ private final UITexture bronzeTexture;
+ private final UITexture steelTexture;
+ private final UITexture primitiveTexture;
+
+ private SteamTexture(UITexture bronzeTexture, UITexture steelTexture, UITexture primitiveTexture) {
+ this.bronzeTexture = bronzeTexture;
+ this.steelTexture = steelTexture;
+ this.primitiveTexture = primitiveTexture;
+ }
+
+ public static SteamTexture fullImage(String mod, String location) {
+ return new SteamTexture(
+ UITexture.fullImage(mod, String.format(location, SteamVariant.BRONZE)),
+ UITexture.fullImage(mod, String.format(location, SteamVariant.STEEL)),
+ UITexture.fullImage(mod, String.format(location, SteamVariant.PRIMITIVE)));
+ }
+
+ public static SteamTexture adaptableTexture(String mod, String location, int imageWidth, int imageHeight,
+ int borderWidthPixel) {
+ return new SteamTexture(
+ AdaptableUITexture
+ .of(mod, String.format(location, SteamVariant.BRONZE), imageWidth, imageHeight, borderWidthPixel),
+ AdaptableUITexture
+ .of(mod, String.format(location, SteamVariant.STEEL), imageWidth, imageHeight, borderWidthPixel),
+ AdaptableUITexture
+ .of(mod, String.format(location, SteamVariant.PRIMITIVE), imageWidth, imageHeight, borderWidthPixel));
+ }
+
+ public UITexture get(SteamVariant variant) {
+ return switch (variant) {
+ case BRONZE -> bronzeTexture;
+ case STEEL -> steelTexture;
+ case PRIMITIVE -> primitiveTexture;
+ default -> null;
+ };
+ }
+
+ public AdaptableUITexture getAdaptable(SteamVariant variant) {
+ return switch (variant) {
+ case BRONZE -> (AdaptableUITexture) bronzeTexture;
+ case STEEL -> (AdaptableUITexture) steelTexture;
+ case PRIMITIVE -> (AdaptableUITexture) primitiveTexture;
+ default -> null;
+ };
+ }
+
+ public UITexture get(boolean isHighPressure) {
+ return isHighPressure ? steelTexture : bronzeTexture;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_CoverTickRateButton.java b/src/main/java/gregtech/api/gui/widgets/GT_CoverTickRateButton.java
new file mode 100644
index 0000000000..883ffb4079
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_CoverTickRateButton.java
@@ -0,0 +1,82 @@
+package gregtech.api.gui.widgets;
+
+import static gregtech.api.gui.modularui.GT_UITextures.OVERLAY_BUTTON_HOURGLASS;
+import static gregtech.common.covers.CoverInfo.MAX_TICK_RATE_ADDITION;
+
+import java.util.List;
+
+import net.minecraft.util.StatCollector;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.common.covers.CoverInfo;
+
+public class GT_CoverTickRateButton extends ButtonWidget {
+
+ private static final UITexture BACKGROUND = GT_UITextures.BUTTON_COVER_NORMAL.getSubArea(0, 0, 1, 0.5f);
+
+ private final CoverInfo coverInfo;
+ private int clientTickRate;
+ private int tickRateAddition;
+
+ public GT_CoverTickRateButton(@NotNull CoverInfo coverInfo, @NotNull IWidgetBuilder<?> builder) {
+ this.coverInfo = coverInfo;
+ this.clientTickRate = coverInfo.getTickRate();
+ this.tickRateAddition = coverInfo.getTickRateAddition();
+
+ super.setBackground(BACKGROUND, OVERLAY_BUTTON_HOURGLASS);
+ super.setOnClick(this::onClick);
+ super.dynamicTooltip(this::dynamicTooltip);
+ super.attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(this.coverInfo::getTickRate, integer -> clientTickRate = integer),
+ builder,
+ (widget, aInt) -> notifyTooltipChange())
+ .attachSyncer(
+ new FakeSyncWidget.IntegerSyncer(
+ this.coverInfo::getTickRateAddition,
+ integer -> tickRateAddition = integer),
+ builder);
+
+ }
+
+ private void onClick(@NotNull ClickData clickData, @NotNull Widget widget) {
+ final int iterations = clickData.ctrl ? 5 : 1;
+ final boolean isDecreasing = clickData.mouseButton == 1;
+
+ // Do five operations at once if Ctrl is held down. Since the actual increase granted by each invocation can be
+ // different on each call, just call the method several times rather than trying to do a bunch of weird math.
+ for (int i = 0; i < iterations; i++) {
+ coverInfo.adjustTickRateMultiplier(isDecreasing);
+ }
+ }
+
+ private List<String> dynamicTooltip() {
+ final String boundsNotification;
+
+ if (tickRateAddition == 0) {
+ boundsNotification = StatCollector.translateToLocal("gt.cover.info.button.bounds_notification.minimum");
+ } else if (tickRateAddition >= MAX_TICK_RATE_ADDITION - 1) {
+ // Clamping can make tickRateAddition approach but never actually equal MAX_ADDITION, so we need this
+ // adjustment.
+ boundsNotification = StatCollector.translateToLocal("gt.cover.info.button.bounds_notification.maximum");
+ } else {
+ boundsNotification = "";
+ }
+
+ return ImmutableList.of(
+ StatCollector.translateToLocalFormatted(
+ "gt.cover.info.button.tick_rate.1",
+ new CoverInfo.ClientTickRateFormatter(clientTickRate),
+ boundsNotification),
+ StatCollector.translateToLocal("gt.cover.info.button.tick_rate.2"),
+ StatCollector.translateToLocal("gt.cover.info.button.tick_rate.3"));
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiCoverTabLine.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiCoverTabLine.java
new file mode 100644
index 0000000000..6f4eb0e2c2
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiCoverTabLine.java
@@ -0,0 +1,179 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+import java.util.List;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.lwjgl.opengl.GL11;
+
+import codechicken.nei.api.API;
+import codechicken.nei.api.INEIGuiAdapter;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.gui.GT_GUIContainerMetaTile_Machine;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.net.GT_Packet_GtTileEntityGuiRequest;
+import gregtech.common.GT_Proxy;
+
+/**
+ * Let's you access a GregTech IGregTechTileEntity's covers as tabs on the GUI's sides
+ */
+public class GT_GuiCoverTabLine extends GT_GuiTabLine {
+
+ // Names of the block a cover could be on
+ private static final String[] SIDES = new String[] { "GT5U.interface.coverTabs.down", "GT5U.interface.coverTabs.up",
+ "GT5U.interface.coverTabs.north", "GT5U.interface.coverTabs.south", "GT5U.interface.coverTabs.west",
+ "GT5U.interface.coverTabs.east" };
+
+ // Not sure if there's a point in JIT translation but that's what this is
+ private final String[] translatedSides;
+ private final IGregTechTileEntity tile;
+ private final int colorization;
+
+ /**
+ * Let's you access an IGregTechTileEntity's covers as tabs on the GUI's sides
+ *
+ * @param gui GT_ITabRenderer gui which this tab line attaches to
+ * @param tabLineLeft left position of the tab line in relation to the gui
+ * @param tabLineTop top position of the tab line in relation to the gui
+ * @param tabHeight height of a tab
+ * @param tabWidth width of a tab
+ * @param tabSpacing pixels between each tab
+ * @param xDir whether to extend the line horizontally to the right (NORMAL), the left (INVERSE) or not at
+ * all (NONE)
+ * @param yDir whether to extend the line vertically down (NORMAL), up (INVERSE) or not at all (NONE)
+ * @param displayMode whether to display on the left side of the GT_ITabRenderer (NORMAL), on it's right side
+ * (INVERSE) or not at all (NONE)
+ * @param tabBackground the set of textures used to draw this tab line's tab backgrounds
+ * @param tile The IGregTechTileEntity the covers of which we are accessing
+ * @param colorization The colorization of the GUI we are adding tabs to
+ */
+ public GT_GuiCoverTabLine(GT_GUIContainerMetaTile_Machine gui, int tabLineLeft, int tabLineTop, int tabHeight,
+ int tabWidth, int tabSpacing, DisplayStyle xDir, DisplayStyle yDir, DisplayStyle displayMode,
+ GT_GuiTabIconSet tabBackground, IGregTechTileEntity tile, int colorization) {
+ super(gui, 6, tabLineLeft, tabLineTop, tabHeight, tabWidth, tabSpacing, xDir, yDir, displayMode, tabBackground);
+ this.tile = tile;
+ this.colorization = colorization;
+ this.translatedSides = new String[6];
+ setupTabs();
+ }
+
+ /**
+ * Add a tab for each existing cover on this IGregTechTileEntity at creation time
+ */
+ private void setupTabs() {
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ final ItemStack cover = tile.getCoverItemAtSide(side);
+ if (cover != null) {
+ addCoverToTabs(side, cover);
+ }
+ }
+ }
+
+ @Override
+ protected void drawBackground(float parTicks, int mouseX, int mouseY) {
+ // Apply this tile's coloration to draw the background
+ GL11.glColor3ub(
+ (byte) ((colorization >> 16) & 0xFF),
+ (byte) ((colorization >> 8) & 0xFF),
+ (byte) (colorization & 0xFF));
+ super.drawBackground(parTicks, mouseX, mouseY);
+ }
+
+ @Override
+ protected void tabClicked(int tabId, int mouseButton) {
+ if (mouseButton == 0 && mTabs[tabId].enabled) {
+ GT_Values.NW.sendToServer(
+ new GT_Packet_GtTileEntityGuiRequest(
+ this.tile.getXCoord(),
+ this.tile.getYCoord(),
+ this.tile.getZCoord(),
+ tabId + GT_Proxy.GUI_ID_COVER_SIDE_BASE,
+ this.tile.getWorld().provider.dimensionId,
+ Minecraft.getMinecraft().thePlayer.getEntityId(),
+ 0));
+ }
+ }
+
+ /**
+ * Add the cover on this side of the IGregTechTileEntity to the tabs
+ *
+ * @param side side to apply the cover to
+ * @param cover cover to add
+ */
+ private void addCoverToTabs(ForgeDirection side, ItemStack cover) {
+ final boolean enabled = this.tile.getCoverBehaviorAtSideNew(side)
+ .hasCoverGUI();
+ final int ordinalSide = side.ordinal();
+ this.setTab(ordinalSide, cover, null, getTooltipForCoverTab(side, cover, enabled));
+ this.setTabEnabled(ordinalSide, enabled);
+ }
+
+ /**
+ * Decorate the cover's tooltips according to the side it's on and on whether the tab is enabled or not
+ *
+ * @param side side
+ * @param cover cover which tooltip to decorate
+ * @param enabled if the tab is enabled
+ * @return This cover tab's tooltip
+ */
+ private String[] getTooltipForCoverTab(ForgeDirection side, ItemStack cover, boolean enabled) {
+ final List<String> tooltip = cover.getTooltip(Minecraft.getMinecraft().thePlayer, true);
+ tooltip.set(
+ 0,
+ (enabled ? EnumChatFormatting.UNDERLINE : EnumChatFormatting.DARK_GRAY) + getSideDescription(side)
+ + (enabled ? EnumChatFormatting.RESET + ": " : ": " + EnumChatFormatting.RESET)
+ + tooltip.get(0));
+ return tooltip.toArray(new String[0]);
+ }
+
+ /**
+ * Get the translated name for a side of the IGregTechTileEntity
+ *
+ * @param side side of the entity
+ * @return translated name for a side of the IGregTechTileEntity
+ */
+ private String getSideDescription(ForgeDirection side) {
+ final int ordinalSide = side.ordinal();
+ if (ordinalSide < SIDES.length) {
+ if (this.translatedSides[ordinalSide] == null) {
+ this.translatedSides[ordinalSide] = StatCollector.translateToLocal(SIDES[ordinalSide]);
+ }
+ return this.translatedSides[ordinalSide];
+ }
+ return null;
+ }
+
+ /**
+ * Hide any NEI slots that would intersect with a cover tab
+ */
+ static class CoverTabLineNEIHandler extends INEIGuiAdapter {
+
+ @Override
+ public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
+ final Rectangle neiSlotArea = new Rectangle(x, y, w, h);
+ if (gui instanceof GT_GUIContainerMetaTile_Machine) {
+ final GT_GuiTabLine tabLine = ((GT_GUIContainerMetaTile_Machine) gui).coverTabs;
+ if (!tabLine.visible) {
+ return false;
+ }
+ for (int i = 0; i < tabLine.mTabs.length; i++) {
+ if (tabLine.mTabs[i] != null && tabLine.mTabs[i].getBounds()
+ .intersects(neiSlotArea)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ static {
+ API.registerNEIGuiHandler(new CoverTabLineNEIHandler());
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiFakeItemButton.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiFakeItemButton.java
new file mode 100644
index 0000000000..9f4287a65b
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiFakeItemButton.java
@@ -0,0 +1,162 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+import java.util.List;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+
+import codechicken.lib.gui.GuiDraw;
+import gregtech.api.interfaces.IGuiScreen;
+import gregtech.api.util.GT_UtilityClient;
+
+public class GT_GuiFakeItemButton implements IGuiScreen.IGuiElement {
+
+ private GT_GuiIcon bgIcon;
+ private ItemStack item;
+ private final IGuiScreen gui;
+ private int xPosition, yPosition;
+ private List<String> itemTooltips;
+ private final GT_GuiTooltip tooltip = new GT_GuiTooltip(null) {
+
+ @Override
+ public List<String> getToolTipText() {
+ return itemTooltips;
+ }
+
+ @Override
+ public boolean isDelayed() {
+ return false;
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return GT_GuiFakeItemButton.this.getBounds();
+ }
+ };
+ private final Rectangle rectangle;
+ private boolean mimicSlot;
+
+ public GT_GuiFakeItemButton(IGuiScreen gui, int x, int y, GT_GuiIcon bgIcon) {
+ this.gui = gui;
+ this.bgIcon = bgIcon;
+ item = null;
+ rectangle = new Rectangle(x, y, 18, 18);
+ gui.addElement(this);
+ }
+
+ public GT_GuiFakeItemButton setItem(ItemStack i) {
+ item = i;
+ if (getMimicSlot()) updateTooltip();
+ return this;
+ }
+
+ private void updateTooltip() {
+ itemTooltips = item == null ? null : GT_UtilityClient.getTooltip(item, true);
+ }
+
+ public ItemStack getItem() {
+ return item;
+ }
+
+ public GT_GuiFakeItemButton setMimicSlot(boolean mimicSlot) {
+ if (mimicSlot != this.mimicSlot) {
+ if (mimicSlot) {
+ updateTooltip();
+ gui.addToolTip(tooltip);
+ } else {
+ gui.removeToolTip(tooltip);
+ }
+ this.mimicSlot = mimicSlot;
+ }
+ return this;
+ }
+
+ public boolean getMimicSlot() {
+ return mimicSlot;
+ }
+
+ public GT_GuiIcon getBgIcon() {
+ return bgIcon;
+ }
+
+ public GT_GuiFakeItemButton setBgIcon(GT_GuiIcon bgIcon) {
+ this.bgIcon = bgIcon;
+ return this;
+ }
+
+ @Override
+ public void onInit() {
+ xPosition = rectangle.x + gui.getGuiLeft();
+ yPosition = rectangle.y + gui.getGuiTop();
+ }
+
+ @Override
+ public void onRemoved() {
+ if (mimicSlot) gui.removeToolTip(tooltip);
+ }
+
+ @Override
+ public void draw(int mouseX, int mouseY, float parTicks) {
+ GL11.glColor4f(1, 1, 1, 1);
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ if (bgIcon != null) {
+ GT_GuiIcon.render(bgIcon, xPosition - 1, yPosition - 1, 18, 18, 0, true);
+ }
+
+ if (item != null) {
+ if (item.getItem() instanceof ItemBlock) {
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+ }
+ gui.getItemRenderer()
+ .renderItemAndEffectIntoGUI(
+ gui.getFontRenderer(),
+ Minecraft.getMinecraft()
+ .getTextureManager(),
+ item,
+ xPosition,
+ yPosition);
+
+ if (item.getItem() instanceof ItemBlock) GL11.glPopAttrib();
+ }
+
+ if (getMimicSlot()) if (getBounds().contains(mouseX - gui.getGuiLeft(), mouseY - gui.getGuiTop())) {
+ GL11.glDisable(GL11.GL_LIGHTING);
+ GL11.glDisable(GL11.GL_DEPTH_TEST);
+ GL11.glColorMask(true, true, true, false);
+ GuiDraw.drawGradientRect(xPosition, yPosition, 16, 16, 0x80ffffff, 0x80ffffff);
+ GL11.glColorMask(true, true, true, true);
+ // no glEnable, state will be recovered by glPopAttrib
+ }
+
+ GL11.glPopAttrib();
+ }
+
+ public Rectangle getBounds() {
+ return rectangle;
+ }
+
+ public void setX(int x) {
+ rectangle.x = x;
+ }
+
+ public void setY(int y) {
+ rectangle.y = y;
+ }
+
+ public void setWidth(int width) {
+ rectangle.width = width;
+ }
+
+ public void setHeight(int height) {
+ rectangle.height = height;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiIcon.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiIcon.java
new file mode 100644
index 0000000000..66ab27356e
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiIcon.java
@@ -0,0 +1,157 @@
+package gregtech.api.gui.widgets;
+
+import static gregtech.api.enums.Mods.GregTech;
+
+import java.util.Arrays;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.util.ResourceLocation;
+
+import gregtech.api.interfaces.IGuiIcon;
+
+public enum GT_GuiIcon implements IGuiIcon {
+
+ BUTTON_NORMAL(0, 0, 0),
+ BUTTON_DOWN(0, 32, 0),
+ BUTTON_HIGHLIGHT(0, 32 * 2, 0),
+ BUTTON_HIGHLIGHT_DOWN(0, 32 * 3, 0),
+ BUTTON_DISABLED(0, 32 * 4, 0),
+
+ DISABLE(0, 0, 32),
+ REDSTONE_OFF(0, 32, 32),
+ REDSTONE_ON(0, 32 * 2, 32),
+ CHECKMARK(0, 32 * 3, 32),
+ CROSS(0, 32 * 4, 32),
+ WHITELIST(0, 32 * 5, 32),
+ BLACKLIST(0, 32 * 6, 32),
+ PROGRESS(0, 32 * 7, 32),
+
+ EXPORT(0, 0, 32 * 2),
+ IMPORT(0, 32, 32 * 2),
+ ALLOW_INPUT(0, 32 * 2, 32 * 2),
+ BLOCK_INPUT(0, 32 * 3, 32 * 2),
+ GREEN_ARROW_UP(0, 32 * 4, 32 * 2),
+ GREEN_ARROW_DOWN(0, 32 * 5, 32 * 2),
+ CYCLIC(0, 32 * 6, 32 * 2),
+
+ AND_GATE(0, 0, 32 * 3),
+ NAND_GATE(0, 32, 32 * 3),
+ OR_GATE(0, 32 * 2, 32 * 3),
+ NOR_GATE(0, 32 * 3, 32 * 3),
+ ANALOG_MODE(0, 32 * 4, 32 * 3),
+
+ SLOT_DARKGRAY(1, 176, 0, 18, 18),
+ SLOT_GRAY(1, 176, 18, 18, 18),
+
+ TAB_NORMAL(2, 0, 0, 18, 20),
+ TAB_HIGHLIGHT(2, 18, 0, 18, 20),
+ TAB_DISABLED(2, 18 * 2, 0, 18, 20),
+ TAB_NORMAL_BRONZE(2, 0, 20, 18, 20),
+ TAB_HIGHLIGHT_BRONZE(2, 18, 20, 18, 20),
+ TAB_DISABLED_BRONZE(2, 18 * 2, 20, 18, 20),
+ TAB_NORMAL_STEEL(2, 0, 2 * 20, 18, 20),
+ TAB_HIGHLIGHT_STEEL(2, 18, 2 * 20, 18, 20),
+ TAB_DISABLED_STEEL(2, 18 * 2, 2 * 20, 18, 20),
+ TAB_NORMAL_BRICK(2, 0, 3 * 20, 18, 20),
+ TAB_HIGHLIGHT_BRICK(2, 18, 3 * 20, 18, 20),
+ TAB_DISABLED_BRICK(2, 18 * 2, 3 * 20, 18, 20),
+ TAB_INFO_GRAY(2, 220, 0, 18, 20),
+ TAB_INFO_BLUE(2, 220 + 18, 0, 18, 20),;
+
+ private static final int T_SIZE = 256;
+ private static ResourceLocation[] TEXTURES = { new ResourceLocation(GregTech.ID, "textures/gui/GuiButtons.png"),
+ new ResourceLocation(GregTech.ID, "textures/gui/GuiCover.png"),
+ new ResourceLocation(GregTech.ID, "textures/gui/GuiTabs.png"), };
+
+ public final int x, y, width, height;
+ public final IGuiIcon overlay;
+ private final int texID;
+
+ GT_GuiIcon(int texID, int x, int y, int width, int height, IGuiIcon overlay) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ this.overlay = overlay;
+ this.texID = texID;
+ }
+
+ GT_GuiIcon(int texID, int x, int y) {
+ this(texID, x, y, 32, 32, null);
+ }
+
+ GT_GuiIcon(int texID, int x, int y, int width, int height) {
+ this(texID, x, y, width, height, null);
+ }
+
+ public static void render(IGuiIcon icon, double x, double y, double width, double height, double zLevel,
+ boolean doDraw) {
+ render(icon, x, y, width, height, zLevel, doDraw, false);
+ }
+
+ public static void render(IGuiIcon icon, double x, double y, double width, double height, double zLevel,
+ boolean doDraw, boolean flipHoritontally) {
+ Tessellator tess = Tessellator.instance;
+ if (doDraw) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(TEXTURES[icon.getTexId()]);
+ tess.startDrawingQuads();
+ }
+ double minU = (double) (icon.getX() + (flipHoritontally ? icon.getWidth() : 0)) / T_SIZE;
+ double maxU = (double) (icon.getX() + (flipHoritontally ? 0 : icon.getWidth())) / T_SIZE;
+ double minV = (double) icon.getY() / T_SIZE;
+ double maxV = (double) (icon.getY() + icon.getHeight()) / T_SIZE;
+ tess.addVertexWithUV(x, y + height, zLevel, minU, maxV);
+ tess.addVertexWithUV(x + width, y + height, zLevel, maxU, maxV);
+ tess.addVertexWithUV(x + width, y + 0, zLevel, maxU, minV);
+ tess.addVertexWithUV(x, y + 0, zLevel, minU, minV);
+
+ if (icon.getOverlay() != null) render(icon.getOverlay(), x, y, width, height, zLevel, false);
+
+ if (doDraw) tess.draw();
+ }
+
+ /**
+ * This is intended to enable addon mods to register additional textures. They can then add to this enum using
+ * EnumHelper.addEnum or by creating their enum that implements IGuiIcon (still requires adding a texture here)
+ *
+ * @param location location of the texture to add
+ */
+ public static void addTextures(ResourceLocation... location) {
+ if (location == null || location.length == 0) return;
+
+ int startIndex = TEXTURES.length;
+ TEXTURES = Arrays.copyOf(TEXTURES, location.length);
+ System.arraycopy(location, 0, TEXTURES, startIndex, location.length);
+ }
+
+ @Override
+ public int getX() {
+ return this.x;
+ }
+
+ @Override
+ public int getY() {
+ return this.y;
+ }
+
+ @Override
+ public int getWidth() {
+ return this.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return this.height;
+ }
+
+ @Override
+ public int getTexId() {
+ return this.texID;
+ }
+
+ @Override
+ public IGuiIcon getOverlay() {
+ return this.overlay;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiIconButton.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconButton.java
new file mode 100644
index 0000000000..d4bfe31404
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconButton.java
@@ -0,0 +1,114 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiButton;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.interfaces.IGuiScreen;
+
+public class GT_GuiIconButton extends GuiButton implements IGuiScreen.IGuiElement {
+
+ public static final int DEFAULT_WIDTH = 16;
+ public static final int DEFAULT_HEIGHT = 16;
+
+ protected GT_GuiIcon icon;
+ private final int x0;
+ private final int y0;
+ protected final IGuiScreen gui;
+
+ private GT_GuiTooltip tooltip;
+
+ public GT_GuiIconButton(IGuiScreen gui, int id, int x, int y, GT_GuiIcon icon) {
+ super(id, x, y, DEFAULT_WIDTH, DEFAULT_HEIGHT, "");
+ this.gui = gui;
+ this.icon = icon;
+ this.x0 = x;
+ this.y0 = y;
+ gui.addElement(this);
+ }
+
+ @Override
+ public void onInit() {
+ if (tooltip != null) gui.addToolTip(tooltip);
+ xPosition = x0 + gui.getGuiLeft();
+ yPosition = y0 + gui.getGuiTop();
+ }
+
+ @Override
+ public void draw(int mouseX, int mouseY, float parTicks) {
+ drawButton(Minecraft.getMinecraft(), mouseX, mouseY);
+ }
+
+ @Override
+ public void drawButton(Minecraft mc, int mouseX, int mouseY) {
+ if (this.tooltip != null) this.tooltip.enabled = true;
+
+ if (this.visible) {
+ // moused over
+ this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition
+ && mouseX < this.xPosition + width
+ && mouseY < this.yPosition + height;
+
+ mouseDragged(mc, mouseX, mouseY);
+
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ int x = xPosition;
+ int y = yPosition;
+ if (!this.field_146123_n) {
+ // GL11.glColor4f(200F/255F, 210F/255F, 1, 1);
+ } else GL11.glColor4f(1, 1, 1, 1);
+
+ GT_GuiIcon.render(getButtonTexture(this.field_146123_n), x, y, width, height, 0, true);
+
+ GL11.glColor4f(1, 1, 1, 1);
+ if (icon != null) {
+ GT_GuiIcon.render(icon, x, y, width, height, 0, true);
+ }
+
+ GL11.glPopAttrib();
+ }
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY) {
+ this.gui.clearSelectedButton();
+ if (mousePressed(Minecraft.getMinecraft(), mouseX, mouseY)) this.gui.buttonClicked(this);
+ }
+
+ public GT_GuiIcon getButtonTexture(boolean mouseOver) {
+ if (!enabled) return GT_GuiIcon.BUTTON_DISABLED;
+ if (this.equals(this.gui.getSelectedButton()))
+ return mouseOver ? GT_GuiIcon.BUTTON_HIGHLIGHT_DOWN : GT_GuiIcon.BUTTON_DOWN;
+
+ return mouseOver ? GT_GuiIcon.BUTTON_HIGHLIGHT : GT_GuiIcon.BUTTON_NORMAL;
+ }
+
+ public GT_GuiIcon getIcon() {
+ return icon;
+ }
+
+ public GT_GuiIconButton setIcon(GT_GuiIcon icon) {
+ this.icon = icon;
+ return this;
+ }
+
+ public GT_GuiTooltip getTooltip() {
+ return tooltip;
+ }
+
+ public GT_GuiIconButton setTooltipText(String... text) {
+ if (tooltip == null) tooltip = new GT_GuiTooltip(getBounds(), text);
+ else tooltip.setToolTipText(text);
+ return this;
+ }
+
+ public Rectangle getBounds() {
+ return new Rectangle(x0, y0, width, height);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java
new file mode 100644
index 0000000000..5b5007fef3
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiIconCheckButton.java
@@ -0,0 +1,43 @@
+package gregtech.api.gui.widgets;
+
+import gregtech.api.interfaces.IGuiScreen;
+
+public class GT_GuiIconCheckButton extends GT_GuiIconButton {
+
+ private final GT_GuiIcon checkedIcon;
+ private final GT_GuiIcon normalIcon;
+ private final String checkedTooltip;
+ private final String normalTooltip;
+ private boolean checked = false;
+
+ public GT_GuiIconCheckButton(IGuiScreen gui, int id, int x, int y, GT_GuiIcon checkedIcon, GT_GuiIcon normalIcon) {
+ this(gui, id, x, y, checkedIcon, normalIcon, null, null);
+ }
+
+ public GT_GuiIconCheckButton(IGuiScreen gui, int id, int x, int y, GT_GuiIcon checkedIcon, GT_GuiIcon normalIcon,
+ String checkedTooltip, String normalTooltip) {
+ super(gui, id, x, y, normalIcon);
+ this.checkedIcon = checkedIcon;
+ this.normalIcon = normalIcon;
+ this.checkedTooltip = checkedTooltip;
+ this.normalTooltip = normalTooltip;
+ }
+
+ @Override
+ public GT_GuiIcon getButtonTexture(boolean mouseOver) {
+ if (!enabled) return GT_GuiIcon.BUTTON_DISABLED;
+ if (this.equals(super.gui.getSelectedButton()))
+ return mouseOver ? GT_GuiIcon.BUTTON_HIGHLIGHT_DOWN : GT_GuiIcon.BUTTON_DOWN;
+ return mouseOver ? GT_GuiIcon.BUTTON_HIGHLIGHT : GT_GuiIcon.BUTTON_NORMAL;
+ }
+
+ public boolean isChecked() {
+ return checked;
+ }
+
+ public void setChecked(boolean checked) {
+ super.setIcon(checked ? checkedIcon : normalIcon);
+ super.setTooltipText(checked ? checkedTooltip : normalTooltip);
+ this.checked = checked;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiIntegerTextBox.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiIntegerTextBox.java
new file mode 100644
index 0000000000..2d3c7374bd
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiIntegerTextBox.java
@@ -0,0 +1,73 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiTextField;
+
+import gregtech.api.interfaces.IGuiScreen;
+
+public class GT_GuiIntegerTextBox extends GuiTextField implements IGuiScreen.IGuiElement {
+
+ private final int x0, y0;
+ private final IGuiScreen gui;
+ public final int id;
+ private boolean enabled;
+
+ public GT_GuiIntegerTextBox(IGuiScreen gui, int id, int x, int y, int width, int height) {
+ super(Minecraft.getMinecraft().fontRenderer, x, y, width, height);
+ super.setText("");
+ this.id = id;
+ x0 = x;
+ y0 = y;
+ this.gui = gui;
+ enabled = true;
+ gui.addElement(this);
+ }
+
+ @Override
+ public void onInit() {
+ xPosition = x0 + gui.getGuiLeft();
+ yPosition = y0 + gui.getGuiTop();
+ }
+
+ @Override
+ public void draw(int mouseX, int mouseY, float parTicks) {
+ super.drawTextBox();
+ }
+
+ public Rectangle getBounds() {
+ return new Rectangle(x0, y0, width, height);
+ }
+
+ public boolean validChar(char c, int key) {
+ return Character.isDigit(c);
+ }
+
+ @Override
+ public boolean textboxKeyTyped(char c, int key) {
+ if (validChar(c, key) || c == 1
+ || c == 3
+ || c == 22
+ || c == 24
+ || key == 14
+ || key == 199
+ || key == 203
+ || key == 205
+ || key == 207
+ || key == 211) {
+ return super.textboxKeyTyped(c, key);
+ }
+ return false;
+ }
+
+ @Override
+ public void setEnabled(boolean p_146184_1_) {
+ super.setEnabled(p_146184_1_);
+ enabled = p_146184_1_;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiSlotTooltip.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiSlotTooltip.java
new file mode 100644
index 0000000000..015c8c7697
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiSlotTooltip.java
@@ -0,0 +1,24 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import net.minecraft.inventory.Slot;
+
+import gregtech.api.util.GT_TooltipDataCache.TooltipData;
+
+public class GT_GuiSlotTooltip extends GT_GuiTooltip {
+
+ private final Slot slot;
+
+ public GT_GuiSlotTooltip(Slot slot, TooltipData data) {
+ super(new Rectangle(slot.xDisplayPosition - 1, slot.yDisplayPosition - 1, 18, 18), data);
+ this.slot = slot;
+ }
+
+ @Override
+ protected void onTick() {
+ super.onTick();
+ // If disabled by super, stay disabled.
+ this.enabled = this.enabled && this.slot.getStack() == null;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiSmartTooltip.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiSmartTooltip.java
new file mode 100644
index 0000000000..ffae5c30e6
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiSmartTooltip.java
@@ -0,0 +1,27 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import gregtech.api.util.GT_TooltipDataCache.TooltipData;
+
+public class GT_GuiSmartTooltip extends GT_GuiTooltip {
+
+ public interface TooltipVisibilityProvider {
+
+ boolean shouldShowTooltip();
+ }
+
+ private final TooltipVisibilityProvider visibilityProvider;
+
+ public GT_GuiSmartTooltip(Rectangle bounds, TooltipVisibilityProvider visibilityProvider, TooltipData data) {
+ super(bounds, data);
+ this.visibilityProvider = visibilityProvider;
+ }
+
+ @Override
+ protected void onTick() {
+ super.onTick();
+ // If disabled by super, stay disabled.
+ this.enabled = this.enabled && this.visibilityProvider.shouldShowTooltip();
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiTab.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiTab.java
new file mode 100644
index 0000000000..d06c2bd2eb
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiTab.java
@@ -0,0 +1,174 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemBlock;
+import net.minecraft.item.ItemStack;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+
+import gregtech.api.gui.widgets.GT_GuiTabLine.GT_GuiTabIconSet;
+import gregtech.api.gui.widgets.GT_GuiTabLine.GT_ITabRenderer;
+import gregtech.api.interfaces.IGuiIcon;
+
+/**
+ * A tab to be attached to a tab line
+ */
+public class GT_GuiTab {
+
+ private static final int SLOT_SIZE = 18;
+
+ public boolean visible = true, mousedOver, enabled = true;
+
+ private Rectangle bounds;
+ private final GT_GuiTabIconSet tabBackground;
+ private final ItemStack item;
+ private final GT_ITabRenderer gui;
+ private GT_GuiTooltip tooltip;
+ private final IGuiIcon overlay;
+ private final boolean flipHorizontally;
+
+ /**
+ * A tab to be attached to a tab line
+ *
+ * @param gui IGregTechTileEntity the tab line this tab belongs to is attached to
+ * @param id both the ID and position in the tab line of this tab. Not used, kept for compatibility.
+ * @param bounds bounds of this tab
+ * @param tabBackground set of background textures
+ * @param item item to draw atop the background texture, not colored
+ * @param overlay texture to draw atop the background texture, not colored
+ * @param tooltipText tooltip of this tab
+ * @param flipHorizontally whether to draw this tab on the right side of the IGregTechTileEntity
+ */
+ public GT_GuiTab(GT_ITabRenderer gui, int id, Rectangle bounds, GT_GuiTabIconSet tabBackground, ItemStack item,
+ IGuiIcon overlay, String[] tooltipText, boolean flipHorizontally) {
+ this.gui = gui;
+ this.bounds = bounds;
+ this.item = item;
+ this.tabBackground = tabBackground;
+ this.overlay = overlay;
+ if (tooltipText != null) {
+ setTooltipText(tooltipText);
+ }
+ this.flipHorizontally = flipHorizontally;
+ }
+
+ public GT_GuiTab(GT_ITabRenderer gui, int id, Rectangle bounds, GT_GuiTabIconSet tabBackground) {
+ this(gui, id, bounds, tabBackground, null, null, null, false);
+ }
+
+ /**
+ * Set this tab's tooltip text
+ *
+ * @param text text to set
+ * @return This tab for chaining
+ */
+ public GT_GuiTab setTooltipText(String... text) {
+ if (tooltip == null) {
+ tooltip = new GT_GuiTooltip(bounds, text);
+ gui.addToolTip(tooltip);
+ } else {
+ tooltip.setToolTipText(text);
+ }
+ return this;
+ }
+
+ /**
+ * @return This tab's tooltip object
+ */
+ public GT_GuiTooltip getTooltip() {
+ return tooltip;
+ }
+
+ /**
+ * Draw the background texture for this tab
+ *
+ * @param mouseX not used, likely kept for backward compatibility
+ * @param mouseY not used, likely kept for backward compatibility
+ * @param parTicks not used, likely kept for backward compatibility
+ */
+ public void drawBackground(int mouseX, int mouseY, float parTicks) {
+ if (this.visible) {
+ GT_GuiIcon.render(
+ getBackgroundTexture(),
+ bounds.x,
+ bounds.y,
+ bounds.width,
+ bounds.height,
+ 1,
+ true,
+ this.flipHorizontally);
+ }
+ }
+
+ /**
+ * Draw overlay textures and items atop the background texture
+ *
+ * @param mouseX X mouse coordinate
+ * @param mouseY Y mouse coordinate
+ * @param parTicks not used, likely kept for backward compatibility
+ */
+ public void drawOverlays(int mouseX, int mouseY, float parTicks) {
+ this.mousedOver = bounds.contains(mouseX, mouseY);
+
+ if (this.tooltip != null) {
+ this.tooltip.enabled = this.visible;
+ }
+
+ if (this.visible) {
+ if (overlay != null) {
+ GL11.glColor4f(1, 1, 1, 1);
+ GT_GuiIcon.render(overlay, bounds.x, bounds.y, bounds.width, bounds.height, 1, true);
+ }
+ if (item != null) {
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+
+ if (item.getItem() instanceof ItemBlock) {
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glEnable(GL12.GL_RESCALE_NORMAL);
+ }
+ int margin = (bounds.height - SLOT_SIZE);
+ gui.getItemRenderer()
+ .renderItemAndEffectIntoGUI(
+ gui.getFontRenderer(),
+ Minecraft.getMinecraft()
+ .getTextureManager(),
+ item,
+ bounds.x + (this.flipHorizontally ? 0 : margin),
+ bounds.y + margin);
+
+ if (item.getItem() instanceof ItemBlock) GL11.glPopAttrib();
+
+ GL11.glPopAttrib();
+ }
+ }
+ }
+
+ /**
+ * @return the texture this tab should currently use as it's background
+ */
+ protected IGuiIcon getBackgroundTexture() {
+ if (!enabled) return tabBackground.disabled;
+
+ return mousedOver ? tabBackground.highlight : tabBackground.normal;
+ }
+
+ /**
+ * @return the screen space occupied by this tab
+ */
+ public Rectangle getBounds() {
+ return this.bounds;
+ }
+
+ /**
+ * Reposition this tab on the screen
+ *
+ * @param xPos X tab coordinate
+ * @param yPos Y tab coordinate
+ */
+ public void setPosition(int xPos, int yPos) {
+ this.bounds = new Rectangle(xPos, yPos, bounds.width, bounds.height);
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiTabLine.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiTabLine.java
new file mode 100644
index 0000000000..950478cdfa
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiTabLine.java
@@ -0,0 +1,274 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.item.ItemStack;
+
+import org.lwjgl.opengl.GL11;
+
+import gregtech.api.interfaces.IGuiIcon;
+
+/**
+ * Draws clickable and configurable tabs on the left or right side of another GUI
+ */
+public class GT_GuiTabLine {
+
+ /**
+ * Defines a set of textures a tab line can use to render it's tab backgrounds
+ */
+ public static class GT_GuiTabIconSet {
+
+ public IGuiIcon disabled;
+ public IGuiIcon normal;
+ public IGuiIcon highlight;
+
+ public GT_GuiTabIconSet(IGuiIcon normalIcon, IGuiIcon highlightIcon, IGuiIcon disabledIcon) {
+ this.normal = normalIcon;
+ this.highlight = highlightIcon;
+ this.disabled = disabledIcon;
+ }
+ }
+
+ /**
+ * Controls the rendering style of the tab line
+ */
+ public enum DisplayStyle {
+
+ NONE((byte) 0),
+ NORMAL((byte) 1),
+ INVERSE((byte) -1);
+
+ private final byte value;
+
+ DisplayStyle(byte value) {
+ this.value = value;
+ }
+
+ public byte getValue() {
+ return value;
+ }
+ }
+
+ /**
+ * A GUI should implement these methods as well as call the tab line's onMouseClicked, onInit and drawTabs for the
+ * tab line to attach to it properly.
+ */
+ public interface GT_ITabRenderer {
+
+ int getGuiLeft();
+
+ int getGuiTop();
+
+ int getXSize();
+
+ RenderItem getItemRenderer();
+
+ FontRenderer getFontRenderer();
+
+ void addToolTip(GT_GuiTooltip tooltip);
+
+ boolean removeToolTip(GT_GuiTooltip tooltip);
+ }
+
+ // The tabs are arranged according to their index in this array
+ protected final GT_GuiTab[] mTabs;
+
+ private final int tabLineLeft;
+ private final int tabLineTop;
+ private final int tabHeight;
+ private final int tabWidth;
+ private final int tabSpacing;
+
+ // In which direction to draw the tab line
+ private final DisplayStyle xDir;
+ private final DisplayStyle yDir;
+
+ // Whether to display on the right side of the GT_ITabRenderer instead of left
+ protected final boolean flipHorizontally;
+ protected final boolean visible;
+
+ private final GT_GuiTabIconSet tabBackground;
+ private final GT_ITabRenderer gui;
+
+ /**
+ * Draws clickable and configurable tabs on the left or right side of a GT_ITabRenderer
+ *
+ * @param gui GT_ITabRenderer gui which this tab line attaches to
+ * @param numTabs number of tab positions in this tab line
+ * @param tabLineLeft left position of the tab line in relation to the gui
+ * @param tabLineTop top position of the tab line in relation to the gui
+ * @param tabHeight height of a tab
+ * @param tabWidth width of a tab
+ * @param tabSpacing pixels between each tab
+ * @param xDir whether to extend the line horizontally to the right (NORMAL), the left (INVERSE) or not at
+ * all (NONE)
+ * @param yDir whether to extend the line vertically down (NORMAL), up (INVERSE) or not at all (NONE)
+ * @param displayMode whether to display on the left side of the GT_ITabRenderer (NORMAL), on it's right side
+ * (INVERSE) or not at all (NONE)
+ * @param tabBackground the set of textures used to draw this tab line's tab backgrounds
+ */
+ public GT_GuiTabLine(GT_ITabRenderer gui, int numTabs, int tabLineLeft, int tabLineTop, int tabHeight, int tabWidth,
+ int tabSpacing, DisplayStyle xDir, DisplayStyle yDir, DisplayStyle displayMode,
+ GT_GuiTabIconSet tabBackground) {
+ this.gui = gui;
+ this.mTabs = new GT_GuiTab[numTabs];
+ this.tabLineLeft = tabLineLeft;
+ this.tabLineTop = tabLineTop;
+ this.tabHeight = tabHeight;
+ this.tabWidth = tabWidth;
+ this.tabSpacing = tabSpacing;
+ this.xDir = xDir;
+ this.yDir = yDir;
+ this.tabBackground = tabBackground;
+ this.flipHorizontally = displayMode == DisplayStyle.INVERSE;
+ this.visible = !(displayMode == DisplayStyle.NONE);
+ }
+
+ /**
+ * Creates a new tab at the specified position with the given parameters. This class handles the positioning.
+ *
+ * @param tabId tab ID
+ * @param item item to draw atop the background texture, not colored
+ * @param overlay texture to draw atop the background texture, not colored
+ * @param text tooltip of this tab
+ */
+ public void setTab(int tabId, ItemStack item, IGuiIcon overlay, String[] text) {
+ mTabs[tabId] = new GT_GuiTab(
+ this.gui,
+ tabId,
+ getBoundsForTab(tabId),
+ this.tabBackground,
+ item,
+ overlay,
+ text,
+ this.flipHorizontally);
+ }
+
+ /**
+ * Get the bounds a given tab should occupy
+ *
+ * @param tabId tab ID
+ * @return tab bounds
+ */
+ protected Rectangle getBoundsForTab(int tabId) {
+ return new Rectangle(getTabX(tabId), getTabY(tabId), this.tabWidth, this.tabHeight);
+ }
+
+ /**
+ * Enable or disable a tab. Disabled tabs have a dark background.
+ *
+ * @param tabId tab ID
+ * @param enable true to enable, false to disable
+ */
+ public void setTabEnabled(int tabId, boolean enable) {
+ if (mTabs[tabId] != null) {
+ mTabs[tabId].enabled = enable;
+ }
+ }
+
+ /**
+ * Draw the tabs for this tab bar GT_ITabRenderer must call this method on drawGuiContainerBackgroundLayer or on
+ * drawScreen.
+ *
+ * @param parTicks
+ */
+ public void drawTabs(float parTicks, int mouseX, int mouseY) {
+ if (this.visible) {
+ GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
+ GL11.glEnable(GL11.GL_BLEND);
+ GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ drawBackground(parTicks, mouseX, mouseY);
+ drawOverlays(parTicks, mouseX, mouseY);
+ GL11.glPopAttrib();
+ }
+ }
+
+ /**
+ * Draw the tab's backgrounds first
+ *
+ * @param parTicks not used, likely kept for compatibility
+ * @param mouseX mouse X position
+ * @param mouseY mouse Y position
+ */
+ protected void drawOverlays(float parTicks, int mouseX, int mouseY) {
+ for (GT_GuiTab mTab : mTabs) {
+ if (mTab != null) {
+ mTab.drawOverlays(mouseX, mouseY, parTicks);
+ }
+ }
+ }
+
+ /**
+ * Draw anything that overlays the tab's background texture
+ *
+ * @param parTicks not used, likely kept for compatibility
+ * @param mouseX mouse X position
+ * @param mouseY mouse Y position
+ */
+ protected void drawBackground(float parTicks, int mouseX, int mouseY) {
+ for (GT_GuiTab mTab : mTabs) {
+ if (mTab != null) {
+ mTab.drawBackground(mouseX, mouseY, parTicks);
+ }
+ }
+ }
+
+ /**
+ * Call tabClick for every tab that was clicked. GT_ITabRenderer must call this method on mouseClicked.
+ *
+ * @param mouseX mouse X position
+ * @param mouseY mouse Y position
+ * @param mouseButton which mouse button was used to click
+ */
+ public void onMouseClicked(int mouseX, int mouseY, int mouseButton) {
+ for (int tabId = 0; tabId < mTabs.length; tabId++) {
+ if (mTabs[tabId] != null && mTabs[tabId].getBounds()
+ .contains(mouseX, mouseY)) {
+ tabClicked(tabId, mouseButton);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Act on a tab being clicked.
+ *
+ * @param tabId tab ID
+ * @param mouseButton which mouse button was used to click
+ */
+ protected void tabClicked(int tabId, int mouseButton) {}
+
+ /**
+ * Reposition ourselves whenever the GT_ITabRenderer does so. GT_ITabRenderer must call this method on Init.
+ */
+ public void onInit() {
+ for (int i = 0; i < mTabs.length; i++) {
+ if (mTabs[i] != null) {
+ mTabs[i].setPosition(getTabX(i), getTabY(i));
+ }
+ }
+ }
+
+ /**
+ * Get the proper X position for a given tab
+ *
+ * @param tabId tab ID
+ * @return X position of the tab
+ */
+ private int getTabX(int tabId) {
+ return this.gui.getGuiLeft() + (flipHorizontally ? (gui.getXSize() - tabLineLeft - tabWidth) : tabLineLeft)
+ + (tabId * (tabWidth + tabSpacing) * xDir.getValue());
+ }
+
+ /**
+ * Get the proper Y position for a given tab
+ *
+ * @param tabId tab ID
+ * @return Y position of the tab
+ */
+ private int getTabY(int tabId) {
+ return this.gui.getGuiTop() + tabLineTop + (tabId * (tabHeight + tabSpacing) * yDir.getValue());
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltip.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltip.java
new file mode 100644
index 0000000000..fe20b2b57a
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltip.java
@@ -0,0 +1,121 @@
+package gregtech.api.gui.widgets;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.lwjgl.input.Keyboard;
+
+import gregtech.api.util.GT_TooltipDataCache.TooltipData;
+
+public class GT_GuiTooltip {
+
+ protected final Rectangle bounds;
+ protected TooltipData data;
+ private List<String> displayedText;
+ public boolean enabled = true;
+
+ /**
+ * Used to create a tooltip that will appear over the specified bounds. This will initially be a "static" tooltip
+ * that doesn't respect verbosity levels or respond to the shift key.
+ *
+ * @param bounds tooltip bounds
+ * @param text tooltip text
+ */
+ public GT_GuiTooltip(Rectangle bounds, String... text) {
+ this.bounds = bounds;
+ setToolTipText(text);
+ }
+
+ /**
+ * Used to create a tooltip that will appear over the specified bounds. This will initially be a "dynamic" tooltip
+ * that respects verbosity levels and responds to the shift key.
+ *
+ * @param bounds tooltip bounds
+ * @param data tooltip data
+ */
+ public GT_GuiTooltip(Rectangle bounds, TooltipData data) {
+ this.bounds = bounds;
+ // Trust that the tooltips have already been formatted and colored, just make sure it has no nulls
+ this.data = sanitizeTooltipData(data);
+ }
+
+ private TooltipData sanitizeTooltipData(TooltipData data) {
+ if (data.text == null) {
+ data.text = Collections.emptyList();
+ }
+ if (data.shiftText == null) {
+ data.shiftText = Collections.emptyList();
+ }
+ return data;
+ }
+
+ /**
+ * Called before the tooltip manager checks whether this tooltip is enabled
+ */
+ protected void onTick() {
+ // Switch which of our 2 stored texts we're displaying now.
+ this.displayedText = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) ? this.data.shiftText : this.data.text;
+ // If this text is empty, let's not display a tooltip at all.
+ this.enabled = this.displayedText.size() != 0;
+ }
+
+ /**
+ * Called once this tooltip has been determined to be enabled
+ */
+ protected void updateText() {}
+
+ /**
+ * Used to set a "static" tooltip that doesn't respect verbosity levels or respond to the shift key
+ *
+ * @param text tooltip text
+ */
+ public void setToolTipText(String... text) {
+ this.data = formatTooltip(text);
+ this.displayedText = data.text;
+ }
+
+ /**
+ * Used to set a "dynamic" tooltip that respects verbosity levels and responds to the shift key
+ *
+ * @param data tooltip data
+ */
+ public void setToolTipText(TooltipData data) {
+ // Trust that the tooltips have already been formatted and colored, just make sure it has no nulls
+ this.data = sanitizeTooltipData(data);
+ }
+
+ /**
+ * Apply tooltip colors in case the text doesn't contain them and return as tooltip data
+ *
+ * @param text text to apply the colors to
+ * @return colored tooltip lines as list
+ */
+ protected TooltipData formatTooltip(String[] text) {
+ List<String> list;
+ if (text != null) {
+ list = new ArrayList<>(text.length);
+ for (String s : text) {
+ if (s == null) continue;
+ if (list.isEmpty()) list.add("\u00a7f" + s);
+ else list.add("\u00a77" + s);
+ }
+ } else {
+ list = Collections.emptyList();
+ }
+ return new TooltipData(list, list);
+ }
+
+ public List<String> getToolTipText() {
+ return this.displayedText;
+ }
+
+ public Rectangle getBounds() {
+ return bounds;
+ }
+
+ public boolean isDelayed() {
+ return true;
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltipManager.java b/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltipManager.java
new file mode 100644
index 0000000000..4304ca14fc
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_GuiTooltipManager.java
@@ -0,0 +1,80 @@
+package gregtech.api.gui.widgets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.client.gui.FontRenderer;
+
+public class GT_GuiTooltipManager {
+
+ public interface GT_IToolTipRenderer {
+
+ int getGuiLeft();
+
+ int getGuiTop();
+
+ int getXSize();
+
+ FontRenderer getFontRenderer();
+
+ void drawHoveringText(List<String> text, int mouseX, int mouseY, FontRenderer font);
+ }
+
+ private static final long DELAY = 5;
+ private int mouseStopped;
+ private int lastMouseX = -1;
+ private int lastMouseY = -1;
+ private final List<GT_GuiTooltip> tips = new ArrayList<>();
+
+ public void addToolTip(GT_GuiTooltip tip) {
+ if (tip != null && !tips.contains(tip)) tips.add(tip);
+ }
+
+ public boolean removeToolTip(GT_GuiTooltip tip) {
+ return tips.remove(tip);
+ }
+
+ public final void onTick(GT_IToolTipRenderer render, int mouseX, int mouseY) {
+ if ((Math.abs(mouseX - lastMouseX) < 2) && (Math.abs(mouseY - lastMouseY) < 2)) {
+ mouseStopped = Math.min(mouseStopped + 1, 50);
+ } else {
+ mouseStopped = 0;
+ }
+
+ lastMouseX = mouseX;
+ lastMouseY = mouseY;
+
+ mouseX -= render.getGuiLeft();
+ mouseY -= render.getGuiTop();
+ for (GT_GuiTooltip tip : tips) {
+ // Give the tooltip the opportunity to decide whether they should be enabled
+ tip.onTick();
+ if (tip.enabled && (!tip.isDelayed() || mouseStopped > DELAY)
+ && tip.getBounds()
+ .contains(mouseX, mouseY)) {
+ tip.updateText();
+ drawTooltip(tip, mouseX, mouseY, render);
+ break;
+ }
+ }
+ }
+
+ private void drawTooltip(GT_GuiTooltip tip, int mouseX, int mouseY, GT_IToolTipRenderer render) {
+ List<String> text = tip.getToolTipText();
+ if (text == null) return;
+
+ if (mouseX > render.getGuiLeft() + render.getXSize() / 2) {
+ int maxWidth = 0;
+ for (String s : text) {
+ int w = render.getFontRenderer()
+ .getStringWidth(s);
+ if (w > maxWidth) {
+ maxWidth = w;
+ }
+ }
+ mouseX -= (maxWidth + 18);
+ }
+
+ render.drawHoveringText(text, mouseX, mouseY, render.getFontRenderer());
+ }
+}
diff --git a/src/main/java/gregtech/api/gui/widgets/GT_LockedWhileActiveButton.java b/src/main/java/gregtech/api/gui/widgets/GT_LockedWhileActiveButton.java
new file mode 100644
index 0000000000..9a93a8fadf
--- /dev/null
+++ b/src/main/java/gregtech/api/gui/widgets/GT_LockedWhileActiveButton.java
@@ -0,0 +1,90 @@
+package gregtech.api.gui.widgets;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+import net.minecraft.util.StatCollector;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.widget.Widget;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+
+public class GT_LockedWhileActiveButton extends ButtonWidget {
+
+ @NotNull
+ private final IMachineProgress machine;
+
+ public GT_LockedWhileActiveButton(@NotNull IMachineProgress machine, @NotNull ModularWindow.Builder builder) {
+ super();
+ this.machine = machine;
+
+ super.attachSyncer(
+ new FakeSyncWidget.BooleanSyncer(machine::isActive, a -> {}),
+ builder,
+ (widget, aBoolean) -> widget.notifyTooltipChange());
+
+ super.dynamicTooltip(this::generateTooltip);
+ }
+
+ @NotNull
+ @Override
+ public ButtonWidget setOnClick(@NotNull BiConsumer<ClickData, Widget> clickAction) {
+ return super.setOnClick((clickData, widget) -> {
+ if (!machine.isActive()) {
+ clickAction.accept(clickData, widget);
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ public Widget setBackground(@NotNull IDrawable... drawables) {
+ return super.setBackground(() -> appendLockedOverlay(drawables));
+ }
+
+ @NotNull
+ @Override
+ public Widget setBackground(@NotNull Supplier<IDrawable[]> drawablesSupplier) {
+ return super.setBackground(() -> appendLockedOverlay(drawablesSupplier.get()));
+ }
+
+ @NotNull
+ @Override
+ public Widget dynamicTooltip(@NotNull Supplier<List<String>> dynamicTooltip) {
+ return super.dynamicTooltip(() -> {
+ ImmutableList.Builder<String> tooltips = ImmutableList.<String>builder()
+ .addAll(dynamicTooltip.get());
+ tooltips.addAll(generateTooltip());
+
+ return tooltips.build();
+ });
+ }
+
+ @NotNull
+ private IDrawable[] appendLockedOverlay(@NotNull IDrawable[] drawables) {
+ if (machine.isActive()) {
+ final IDrawable[] copy = Arrays.copyOf(drawables, drawables.length + 1);
+ copy[drawables.length] = GT_UITextures.OVERLAY_BUTTON_LOCKED;
+ return copy;
+ }
+ return drawables;
+ }
+
+ @NotNull
+ private List<String> generateTooltip() {
+ if (machine.isActive()) {
+ return ImmutableList.of(StatCollector.translateToLocal("GT5U.gui.button.forbidden_while_running"));
+ }
+ return ImmutableList.of();
+ }
+}