mirror of
https://github.com/GTNewHorizons/Applied-Energistics-2-Unofficial.git
synced 2026-10-26 14:25:20 +00:00
Co-authored-by: Martin Robertz <dream-master@gmx.net> Co-authored-by: UltraProdigy <187078471+UltraProdigy@users.noreply.github.com>
1189 lines
45 KiB
Java
1189 lines
45 KiB
Java
/*
|
|
* This file is part of Applied Energistics 2. Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved. Applied
|
|
* Energistics 2 is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
|
|
* Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
|
* later version. Applied Energistics 2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
* Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
|
|
* Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
|
|
*/
|
|
|
|
package appeng.client.gui;
|
|
|
|
import static appeng.client.gui.implementations.GuiMEMonitorable.keyBindPickBlockAction;
|
|
import static appeng.server.ServerHelper.CONTAINER_INTERACTION_KEY;
|
|
|
|
import java.io.IOException;
|
|
import java.text.DecimalFormat;
|
|
import java.text.ParseException;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
|
|
import net.minecraft.client.gui.FontRenderer;
|
|
import net.minecraft.client.gui.GuiButton;
|
|
import net.minecraft.client.gui.inventory.GuiContainer;
|
|
import net.minecraft.client.renderer.RenderHelper;
|
|
import net.minecraft.client.renderer.Tessellator;
|
|
import net.minecraft.client.renderer.texture.TextureMap;
|
|
import net.minecraft.inventory.Container;
|
|
import net.minecraft.inventory.Slot;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.EnumChatFormatting;
|
|
import net.minecraft.util.IIcon;
|
|
import net.minecraft.util.ResourceLocation;
|
|
import net.minecraft.util.StringUtils;
|
|
import net.minecraftforge.client.event.GuiScreenEvent;
|
|
import net.minecraftforge.common.MinecraftForge;
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.lwjgl.input.Keyboard;
|
|
import org.lwjgl.input.Mouse;
|
|
import org.lwjgl.opengl.GL11;
|
|
import org.lwjgl.opengl.GL12;
|
|
|
|
import com.google.common.base.Joiner;
|
|
import com.google.common.base.Stopwatch;
|
|
|
|
import appeng.api.config.TerminalFontSize;
|
|
import appeng.api.events.GuiScrollEvent;
|
|
import appeng.api.storage.data.IAEFluidStack;
|
|
import appeng.api.storage.data.IAEStack;
|
|
import appeng.client.gui.slots.VirtualMEPhantomSlot;
|
|
import appeng.client.gui.slots.VirtualMESlot;
|
|
import appeng.client.gui.widgets.GuiQuantityButton;
|
|
import appeng.client.gui.widgets.GuiScrollbar;
|
|
import appeng.client.gui.widgets.ITooltip;
|
|
import appeng.client.render.AppEngRenderItem;
|
|
import appeng.client.render.StackSizeRenderer;
|
|
import appeng.client.render.TranslatedRenderItem;
|
|
import appeng.container.AEBaseContainer;
|
|
import appeng.container.slot.AppEngCraftingSlot;
|
|
import appeng.container.slot.AppEngSlot;
|
|
import appeng.container.slot.AppEngSlot.hasCalculatedValidness;
|
|
import appeng.container.slot.OptionalSlotFake;
|
|
import appeng.container.slot.OptionalSlotRestrictedInput;
|
|
import appeng.container.slot.SlotCraftingTerm;
|
|
import appeng.container.slot.SlotDisabled;
|
|
import appeng.container.slot.SlotFake;
|
|
import appeng.container.slot.SlotInaccessible;
|
|
import appeng.container.slot.SlotOutput;
|
|
import appeng.container.slot.SlotPatternTerm;
|
|
import appeng.container.slot.SlotRestrictedInput;
|
|
import appeng.container.slot.SlotRestrictedInput.PlacableItemType;
|
|
import appeng.core.AEConfig;
|
|
import appeng.core.AELog;
|
|
import appeng.core.AppEng;
|
|
import appeng.core.localization.GuiColors;
|
|
import appeng.core.localization.GuiText;
|
|
import appeng.core.sync.network.NetworkHandler;
|
|
import appeng.core.sync.packets.PacketClickOrDragFakeSlot;
|
|
import appeng.core.sync.packets.PacketInventoryAction;
|
|
import appeng.core.sync.packets.PacketSwapSlots;
|
|
import appeng.helpers.ICustomButtonProvider;
|
|
import appeng.helpers.InventoryAction;
|
|
import appeng.integration.IntegrationRegistry;
|
|
import appeng.integration.IntegrationType;
|
|
import appeng.integration.modules.NEI;
|
|
import appeng.util.Platform;
|
|
import codechicken.lib.gui.GuiDraw;
|
|
import codechicken.nei.VisiblityData;
|
|
import codechicken.nei.api.INEIGuiHandler;
|
|
import codechicken.nei.api.TaggedInventoryArea;
|
|
import cpw.mods.fml.common.Loader;
|
|
import cpw.mods.fml.common.Optional;
|
|
|
|
@Optional.Interface(modid = "NotEnoughItems", iface = "codechicken.nei.api.INEIGuiHandler")
|
|
public abstract class AEBaseGui extends GuiContainer implements IGuiTooltipHandler, INEIGuiHandler {
|
|
|
|
private static class AEGuiTooltip {
|
|
|
|
private int shiftX = 0;
|
|
private int shiftY = 0;
|
|
|
|
private int x = 0;
|
|
private int y = 0;
|
|
public String[] lines = null;
|
|
|
|
public void set(final int x, final int y, final String message) {
|
|
set(x, y, message != null && !message.isEmpty() ? message.split("\n") : null);
|
|
}
|
|
|
|
public void set(final int x, final int y, final String[] lines) {
|
|
this.lines = lines;
|
|
this.x = this.shiftX + x;
|
|
this.y = this.shiftY + y;
|
|
}
|
|
|
|
public void shift(int shiftX, int shiftY) {
|
|
this.shiftX = shiftX;
|
|
this.shiftY = shiftY;
|
|
}
|
|
|
|
public void draw() {
|
|
if (!isEmpty()) {
|
|
List<String> list = new ArrayList<>();
|
|
list.add(this.lines[0] + GuiDraw.TOOLTIP_LINESPACE);
|
|
|
|
for (int i = 1; i < this.lines.length; i++) {
|
|
list.add(EnumChatFormatting.GRAY + this.lines[i].replace("\u00a0", " "));
|
|
}
|
|
|
|
GuiDraw.drawMultilineTip(this.x + 12, this.y - 12, list);
|
|
this.lines = null;
|
|
}
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return this.lines == null || this.lines.length == 0;
|
|
}
|
|
}
|
|
|
|
private static boolean switchingGuis;
|
|
// drag y
|
|
protected final Set<Slot> draggedSlots = new HashSet<>();
|
|
public static final AppEngRenderItem aeRenderItem = new AppEngRenderItem();
|
|
public static final TranslatedRenderItem translatedRenderItem = new TranslatedRenderItem();
|
|
private final AEGuiTooltip currentToolTip = new AEGuiTooltip();
|
|
private GuiScrollbar scrollBar = null;
|
|
private boolean disableShiftClick = false;
|
|
private Stopwatch dbl_clickTimer = Stopwatch.createStarted();
|
|
private ItemStack dbl_whichItem;
|
|
private Slot bl_clicked;
|
|
private boolean subGui;
|
|
|
|
private final List<VirtualMESlot> virtualSlots = new ArrayList<>();
|
|
private final List<VirtualMESlot> draggedVirtualSlots = new ArrayList<>();
|
|
private VirtualMESlot hoveredVirtualSlot = null;
|
|
private @Nullable ItemStack holdingNEIItem = null;
|
|
|
|
public AEBaseGui(final Container container) {
|
|
super(container);
|
|
this.subGui = switchingGuis;
|
|
switchingGuis = false;
|
|
aeRenderItem.parent = this;
|
|
}
|
|
|
|
protected static String join(final Collection<String> toolTip, final String delimiter) {
|
|
final Joiner joiner = Joiner.on(delimiter);
|
|
|
|
return joiner.join(toolTip);
|
|
}
|
|
|
|
protected int getQty(final GuiButton btn) {
|
|
if (btn instanceof GuiQuantityButton quantityButton) {
|
|
return quantityButton.getQuantity();
|
|
}
|
|
|
|
try {
|
|
final DecimalFormat df = new DecimalFormat("+#;-#");
|
|
final String plain = StringUtils.stripControlCodes(btn.displayString);
|
|
return df.parse(plain).intValue();
|
|
} catch (final ParseException e) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public boolean isSubGui() {
|
|
return this.subGui;
|
|
}
|
|
|
|
@Override
|
|
public void initGui() {
|
|
super.initGui();
|
|
|
|
this.virtualSlots.clear();
|
|
}
|
|
|
|
protected void registerVirtualSlots(VirtualMESlot slot) {
|
|
virtualSlots.add(slot);
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
protected List<Slot> getInventorySlots() {
|
|
return this.inventorySlots.inventorySlots;
|
|
}
|
|
|
|
@Override
|
|
public void drawScreen(final int mouseX, final int mouseY, final float btn) {
|
|
super.drawScreen(mouseX, mouseY, btn);
|
|
|
|
for (final Object c : this.buttonList) {
|
|
if (c instanceof ITooltip) {
|
|
handleTooltip(mouseX, mouseY, (ITooltip) c);
|
|
}
|
|
}
|
|
|
|
this.currentToolTip.draw();
|
|
}
|
|
|
|
protected void handleUpgradeSlotTooltip(final int mouseX, final int mouseY) {}
|
|
|
|
protected void handleTooltip(int mouseX, int mouseY, ITooltip tooltip) {
|
|
final int x = tooltip.xPos();
|
|
final int y = tooltip.yPos();
|
|
|
|
if (tooltip.isVisible() && x < mouseX
|
|
&& x + tooltip.getWidth() > mouseX
|
|
&& y < mouseY
|
|
&& y + tooltip.getHeight() > mouseY) {
|
|
drawTooltip(x + 11, Math.max(y, 15) + 4, tooltip.getMessage());
|
|
}
|
|
}
|
|
|
|
@Deprecated
|
|
public void drawTooltip(final int x, final int y, final int forceWidth, final String message) {
|
|
drawTooltip(x, y, message);
|
|
}
|
|
|
|
public void drawTooltip(final int x, final int y, final String message) {
|
|
if (message != null && !message.isEmpty()) {
|
|
drawTooltip(x, y, message.split("\n"));
|
|
}
|
|
}
|
|
|
|
public void drawTooltip(final int x, final int y, final String[] lines) {
|
|
if (lines != null && lines.length > 0) {
|
|
this.currentToolTip.set(x, y, lines);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Utility to add the vertices of a rectangle to an active Tesselator tesselation. The rectangle is defined to be
|
|
* between points (x0, y0)..(x1, y1) and have corresponding texture coordinates (u0, v0)..(u1, v1).
|
|
*/
|
|
public void addTexturedRectToTesselator(float x0, float y0, float x1, float y1, float zLevel, float u0, float v0,
|
|
float u1, float v1) {
|
|
final Tessellator tessellator = Tessellator.instance;
|
|
tessellator.addVertexWithUV(x0, y1, this.zLevel, u0, v1);
|
|
tessellator.addVertexWithUV(x1, y1, this.zLevel, u1, v1);
|
|
tessellator.addVertexWithUV(x1, y0, this.zLevel, u1, v0);
|
|
tessellator.addVertexWithUV(x0, y0, this.zLevel, u0, v0);
|
|
}
|
|
|
|
/**
|
|
* Like {@link net.minecraft.client.gui.Gui#drawTexturedModalRect(int, int, int, int, int, int)} but draws the
|
|
* texture in 9 patches, stretching the middle patch in X&Y directions. The north, east, west and south patches are
|
|
* stretched along one axis, and the corner patches are rendered in 1:1 scale to preserve corner texture quality. A
|
|
* 256x256 GUI texture size is assumed like in the vanilla function.
|
|
*
|
|
* @see <a href="https://developer.android.com/develop/ui/views/graphics/drawables#nine-patch">Android documentation
|
|
* for a more detailed description.</a>
|
|
* @param x X coordinate of the drawn rectangle of the screen
|
|
* @param y Y coordinate of the drawn rectangle of the screen
|
|
* @param width Width of the drawn rectangle of the screen
|
|
* @param height Height of the drawn rectangle of the screen
|
|
* @param textureX X coordinate of the top-left pixel in the texture
|
|
* @param textureY Y coordinate of the top-left pixel in the texture
|
|
* @param textureW Width of texture fragment to draw
|
|
* @param textureH Height of texture fragment to draw
|
|
*/
|
|
public void drawTextured9PatchRect(int x, int y, int width, int height, int textureX, int textureY, int textureW,
|
|
int textureH) {
|
|
final float uvScale = 1.0f / 256.0f;
|
|
|
|
// On-screen thirds (use texture thirds as corner sizes)
|
|
// 03 = 0/3, 13 = 1/3, etc.
|
|
final float x03 = x;
|
|
final float x13 = x + textureW / 3f;
|
|
final float x23 = x + width - textureW / 3f;
|
|
final float x33 = x + width;
|
|
final float y03 = y;
|
|
final float y13 = y + textureH / 3f;
|
|
final float y23 = y + height - textureH / 3f;
|
|
final float y33 = y + height;
|
|
// Texture UV thirds (uniformly scaled 3x3 grid)
|
|
final float u03 = uvScale * textureX;
|
|
final float u13 = uvScale * (textureX + textureW / 3f);
|
|
final float u23 = uvScale * (textureX + 2 * textureW / 3f);
|
|
final float u33 = uvScale * (textureX + textureW);
|
|
final float v03 = uvScale * textureY;
|
|
final float v13 = uvScale * (textureY + textureH / 3f);
|
|
final float v23 = uvScale * (textureY + 2 * textureH / 3f);
|
|
final float v33 = uvScale * (textureY + textureH);
|
|
|
|
Tessellator tessellator = Tessellator.instance;
|
|
tessellator.startDrawingQuads();
|
|
|
|
// top row
|
|
addTexturedRectToTesselator(x03, y03, x13, y13, this.zLevel, u03, v03, u13, v13); // top-left
|
|
addTexturedRectToTesselator(x13, y03, x23, y13, this.zLevel, u13, v03, u23, v13); // top-middle
|
|
addTexturedRectToTesselator(x23, y03, x33, y13, this.zLevel, u23, v03, u33, v13); // top-right
|
|
// middle row
|
|
addTexturedRectToTesselator(x03, y13, x13, y23, this.zLevel, u03, v13, u13, v23); // middle-left
|
|
addTexturedRectToTesselator(x13, y13, x23, y23, this.zLevel, u13, v13, u23, v23); // middle-middle
|
|
addTexturedRectToTesselator(x23, y13, x33, y23, this.zLevel, u23, v13, u33, v23); // middle-right
|
|
// bottom row
|
|
addTexturedRectToTesselator(x03, y23, x13, y33, this.zLevel, u03, v23, u13, v33); // bottom-left
|
|
addTexturedRectToTesselator(x13, y23, x23, y33, this.zLevel, u13, v23, u23, v33); // bottom-middle
|
|
addTexturedRectToTesselator(x23, y23, x33, y33, this.zLevel, u23, v23, u33, v33); // bottom-right
|
|
|
|
tessellator.draw();
|
|
}
|
|
|
|
@Override
|
|
protected final void drawGuiContainerForegroundLayer(final int x, final int y) {
|
|
final int ox = this.guiLeft;
|
|
final int oy = this.guiTop;
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
|
|
if (this.getScrollBar() != null) {
|
|
this.getScrollBar().draw(this);
|
|
}
|
|
|
|
this.currentToolTip.shift(ox, oy);
|
|
this.drawFG(ox, oy, x, y);
|
|
this.currentToolTip.shift(0, 0);
|
|
|
|
this.hoveredVirtualSlot = null;
|
|
this.drawVirtualSlots(this.virtualSlots, x, y);
|
|
}
|
|
|
|
public abstract void drawFG(int offsetX, int offsetY, int mouseX, int mouseY);
|
|
|
|
@Override
|
|
protected final void drawGuiContainerBackgroundLayer(final float f, final int x, final int y) {
|
|
final int ox = this.guiLeft;
|
|
final int oy = this.guiTop;
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
this.drawBG(ox, oy, x, y);
|
|
|
|
final List<Slot> slots = this.getInventorySlots();
|
|
for (final Slot slot : slots) {
|
|
if (slot instanceof OptionalSlotFake fs) {
|
|
if (fs.renderDisabled()) {
|
|
if (fs.isEnabled()) {
|
|
this.drawTexturedModalRect(
|
|
ox + fs.xDisplayPosition - 1,
|
|
oy + fs.yDisplayPosition - 1,
|
|
fs.getSourceX() - 1,
|
|
fs.getSourceY() - 1,
|
|
18,
|
|
18);
|
|
} else {
|
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 0.4F);
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
this.drawTexturedModalRect(
|
|
ox + fs.xDisplayPosition - 1,
|
|
oy + fs.yDisplayPosition - 1,
|
|
fs.getSourceX() - 1,
|
|
fs.getSourceY() - 1,
|
|
18,
|
|
18);
|
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
GL11.glPopAttrib();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void mouseClicked(final int xCoord, final int yCoord, final int btn) {
|
|
this.draggedSlots.clear();
|
|
this.draggedVirtualSlots.clear();
|
|
this.holdingNEIItem = null;
|
|
|
|
final VirtualMESlot virtualSlot = getVirtualMESlotUnderMouse();
|
|
if (virtualSlot != null && this.handleVirtualSlotClick(
|
|
virtualSlot,
|
|
btn == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100 ? keyBindPickBlockAction : btn))
|
|
return;
|
|
|
|
if (btn == 1) {
|
|
for (final GuiButton guibutton : this.buttonList) {
|
|
if (guibutton.mousePressed(this.mc, xCoord, yCoord)) {
|
|
super.mouseClicked(xCoord, yCoord, 0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.getScrollBar() != null) {
|
|
this.getScrollBar().click(this, xCoord - this.guiLeft, yCoord - this.guiTop);
|
|
}
|
|
|
|
super.mouseClicked(xCoord, yCoord, btn);
|
|
}
|
|
|
|
@Override
|
|
protected void keyTyped(char typedChar, int keyCode) {
|
|
if (keyCode == this.mc.gameSettings.keyBindPickBlock.getKeyCode()) {
|
|
final VirtualMESlot virtualSlot = getVirtualMESlotUnderMouse();
|
|
if (virtualSlot != null && this.handleVirtualSlotClick(virtualSlot, keyBindPickBlockAction)) return;
|
|
}
|
|
|
|
if (this.isCloseKey(keyCode)) {
|
|
this.flushPendingSync();
|
|
}
|
|
|
|
super.keyTyped(typedChar, keyCode);
|
|
}
|
|
|
|
@Override
|
|
public boolean handleDragNDrop(GuiContainer gui, int mouseX, int mouseY, ItemStack draggedStack, int button) {
|
|
this.draggedSlots.clear();
|
|
this.holdingNEIItem = draggedStack;
|
|
|
|
return tryClickOrDragSlot(mouseX, mouseY, draggedStack, button);
|
|
}
|
|
|
|
private boolean tryClickOrDragSlot(int mouseX, int mouseY, @Nullable ItemStack itemstack, int mouseButton) {
|
|
Slot slot = this.getSlot(mouseX, mouseY);
|
|
if (slot != null && this.draggedSlots.add(slot)) {
|
|
return handleClickOrDragSlot(slot, itemstack, mouseButton);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected boolean handleClickOrDragSlot(@NotNull Slot slot, @Nullable ItemStack stack, int mouseButton) {
|
|
if (slot instanceof SlotFake slotFake) {
|
|
handleClickOrDragFakeSlot(slotFake, stack, mouseButton);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void handleClickOrDragFakeSlot(@NotNull SlotFake slot, @Nullable ItemStack stack, int mouseButton) {
|
|
boolean isSingle = mouseButton == 1;
|
|
if (isSingle && stack != null) {
|
|
stack = stack.copy();
|
|
stack.stackSize = 1;
|
|
|
|
}
|
|
|
|
NetworkHandler.instance.sendToServer(new PacketClickOrDragFakeSlot(stack, slot.slotNumber, mouseButton != 1));
|
|
|
|
ItemStack stackInSlot = slot.getStack();
|
|
if (isSingle && stackInSlot != null) {
|
|
if (stack != null && stackInSlot.isItemEqual(stack)
|
|
&& ItemStack.areItemStackTagsEqual(stackInSlot, stack)) {
|
|
stack.stackSize = Math.min(stackInSlot.stackSize + stack.stackSize, stack.getMaxStackSize());
|
|
} else if (stack == null) {
|
|
stackInSlot.stackSize -= 1;
|
|
if (stackInSlot.stackSize <= 0) {
|
|
slot.putStack(null);
|
|
} else {
|
|
slot.putStack(stackInSlot);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
slot.putStack(stack);
|
|
}
|
|
|
|
protected ItemStack getStackFromHand() {
|
|
final ItemStack phantom = IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.NEI)
|
|
? NEI.instance.getDraggingPhantomItem()
|
|
: null;
|
|
|
|
return phantom != null ? phantom : this.mc.thePlayer.inventory.getItemStack();
|
|
}
|
|
|
|
protected boolean handleVirtualSlotClick(final VirtualMESlot slot, final int mouseButton) {
|
|
if (slot instanceof VirtualMEPhantomSlot vSlot) {
|
|
this.handlePhantomSlotInteraction(vSlot, mouseButton);
|
|
|
|
// Prevent double dragging
|
|
if (this.getStackFromHand() != null && !this.draggedVirtualSlots.contains(this.hoveredVirtualSlot)) {
|
|
this.draggedVirtualSlots.add(this.hoveredVirtualSlot);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
protected void handleDragVirtualSlot(VirtualMESlot slot, int mouseButton) {
|
|
if (slot instanceof VirtualMEPhantomSlot patternSlot) {
|
|
this.handlePhantomSlotInteraction(patternSlot, mouseButton);
|
|
}
|
|
}
|
|
|
|
private void handlePhantomSlotInteraction(VirtualMEPhantomSlot slot, int mouseButton) {
|
|
slot.handleMouseClicked(this.getStackFromHand(), isCtrlKeyDown(), mouseButton);
|
|
}
|
|
|
|
@Override
|
|
protected void mouseClickMove(final int x, final int y, final int c, final long d) {
|
|
final ItemStack holding = this.holdingNEIItem != null ? this.holdingNEIItem
|
|
: this.mc.thePlayer.inventory.getItemStack();
|
|
|
|
// Hold left or right mouse button
|
|
if (c == 0 || c == 1) {
|
|
// Update hovered slot
|
|
for (VirtualMESlot slot : virtualSlots) {
|
|
if (slot.isHovered(x - this.guiLeft + 1, y - this.guiTop + 1)) {
|
|
this.hoveredVirtualSlot = slot;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (holding != null && this.hoveredVirtualSlot != null
|
|
&& !this.draggedVirtualSlots.contains(this.hoveredVirtualSlot)) {
|
|
this.draggedVirtualSlots.add(this.hoveredVirtualSlot);
|
|
this.handleDragVirtualSlot(this.hoveredVirtualSlot, c);
|
|
}
|
|
}
|
|
|
|
if (this.getScrollBar() != null) {
|
|
this.getScrollBar().clickMove(y - this.guiTop);
|
|
}
|
|
|
|
final Slot slot = this.getSlot(x, y);
|
|
|
|
if (slot != null && this.draggedSlots.add(slot)) {
|
|
if (handleClickOrDragSlot(slot, holding, c)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
super.mouseClickMove(x, y, c, d);
|
|
}
|
|
|
|
@Override
|
|
protected void handleMouseClick(final Slot slot, final int slotIdx, final int clickedButton, final int clickType) {
|
|
if (clickType == 0 && this.draggedSlots.add(slot)) {
|
|
final ItemStack holding = this.holdingNEIItem != null ? this.holdingNEIItem
|
|
: this.mc.thePlayer.inventory.getItemStack();
|
|
if (this.handleClickOrDragSlot(slot, holding, clickedButton)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (slot instanceof SlotPatternTerm) {
|
|
if (clickType == 6) {
|
|
return; // prevent weird double clicks..
|
|
}
|
|
|
|
try {
|
|
NetworkHandler.instance.sendToServer(((SlotPatternTerm) slot).getRequest(isShiftKeyDown()));
|
|
} catch (final IOException e) {
|
|
AELog.debug(e);
|
|
}
|
|
} else if (slot instanceof SlotCraftingTerm) {
|
|
if (clickType == 6) {
|
|
return; // prevent weird double clicks..
|
|
}
|
|
|
|
InventoryAction action = null;
|
|
if (isShiftKeyDown()) {
|
|
action = InventoryAction.CRAFT_SHIFT;
|
|
} else {
|
|
// Craft stack on right-click, craft single on left-click
|
|
action = (clickType == 1) ? InventoryAction.CRAFT_STACK : InventoryAction.CRAFT_ITEM;
|
|
}
|
|
|
|
final PacketInventoryAction p = new PacketInventoryAction(action, slotIdx, 0);
|
|
NetworkHandler.instance.sendToServer(p);
|
|
|
|
return;
|
|
}
|
|
|
|
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
|
|
if (this.enableSpaceClicking() && !(slot instanceof SlotPatternTerm)) {
|
|
int slotNum = this.getInventorySlots().size();
|
|
|
|
if (slot != null) {
|
|
slotNum = slot.slotNumber;
|
|
}
|
|
|
|
((AEBaseContainer) this.inventorySlots).setTargetStack(null);
|
|
final PacketInventoryAction p = new PacketInventoryAction(InventoryAction.MOVE_REGION, slotNum, 0);
|
|
NetworkHandler.instance.sendToServer(p);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!this.disableShiftClick && isShiftKeyDown()) {
|
|
this.disableShiftClick = true;
|
|
|
|
if (this.dbl_whichItem == null || this.bl_clicked != slot
|
|
|| this.dbl_clickTimer.elapsed(TimeUnit.MILLISECONDS) > 150) {
|
|
// some simple double click logic.
|
|
this.bl_clicked = slot;
|
|
this.dbl_clickTimer = Stopwatch.createStarted();
|
|
if (slot != null) {
|
|
this.dbl_whichItem = slot.getHasStack() ? slot.getStack().copy() : null;
|
|
} else {
|
|
this.dbl_whichItem = null;
|
|
}
|
|
} else if (this.dbl_whichItem != null) {
|
|
// a replica of the weird broken vanilla feature.
|
|
|
|
final List<Slot> slots = this.getInventorySlots();
|
|
for (final Slot inventorySlot : slots) {
|
|
if (inventorySlot != null && inventorySlot.canTakeStack(this.mc.thePlayer)
|
|
&& inventorySlot.getHasStack()
|
|
&& inventorySlot.inventory == slot.inventory
|
|
&& Container.func_94527_a(inventorySlot, this.dbl_whichItem, true)) {
|
|
this.handleMouseClick(inventorySlot, inventorySlot.slotNumber, clickedButton, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle Virtual Phantom Slot Shift click interaction
|
|
if (this.inventorySlots instanceof AEBaseContainer baseContainer) {
|
|
if (slot instanceof AppEngSlot appEngSlot && baseContainer.isValidSrcSlotForTransfer(appEngSlot)) {
|
|
ItemStack stackInSlot = appEngSlot.getStack();
|
|
final List<AppEngSlot> selectedSlots = baseContainer
|
|
.getValidDestinationSlots(appEngSlot.isPlayerSide(), stackInSlot);
|
|
|
|
if (selectedSlots.isEmpty() && appEngSlot.isPlayerSide()
|
|
&& this.shouldShiftClickFillVirtualPhantomSlot(slot)
|
|
&& baseContainer.getValidDestinationFakeSlot(stackInSlot) == null) {
|
|
for (VirtualMESlot vmeSlot : this.virtualSlots) {
|
|
if (vmeSlot instanceof VirtualMEPhantomSlot vmepSlot && vmepSlot.getAEStack() == null) {
|
|
vmepSlot.handleMouseClicked(stackInSlot, isCtrlKeyDown(), clickType);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.disableShiftClick = false;
|
|
}
|
|
|
|
super.handleMouseClick(slot, slotIdx, clickedButton, clickType);
|
|
}
|
|
|
|
protected boolean shouldShiftClickFillVirtualPhantomSlot(final Slot slot) {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected boolean checkHotbarKeys(final int keyCode) {
|
|
if (this.mc.thePlayer.inventory.getItemStack() == null && theSlot != null) {
|
|
for (int j = 0; j < 9; ++j) {
|
|
if (keyCode == this.mc.gameSettings.keyBindsHotbar[j].getKeyCode()) {
|
|
final List<Slot> slots = this.getInventorySlots();
|
|
for (final Slot s : slots) {
|
|
if (s.getSlotIndex() == j
|
|
&& s.inventory == ((AEBaseContainer) this.inventorySlots).getPlayerInv()) {
|
|
if (!s.canTakeStack(((AEBaseContainer) this.inventorySlots).getPlayerInv().player)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (theSlot.getSlotStackLimit() == 64) {
|
|
this.handleMouseClick(theSlot, theSlot.slotNumber, j, 2);
|
|
return true;
|
|
} else {
|
|
for (final Slot s : slots) {
|
|
if (s.getSlotIndex() == j
|
|
&& s.inventory == ((AEBaseContainer) this.inventorySlots).getPlayerInv()) {
|
|
NetworkHandler.instance
|
|
.sendToServer(new PacketSwapSlots(s.slotNumber, theSlot.slotNumber));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onGuiClosed() {
|
|
this.flushPendingSync();
|
|
super.onGuiClosed();
|
|
this.subGui = true; // in case the gui is reopened later ( i'm looking at you NEI )
|
|
aeRenderItem.parent = null;
|
|
}
|
|
|
|
@Override
|
|
public void updateScreen() {
|
|
super.updateScreen();
|
|
if (this.inventorySlots instanceof AEBaseContainer container) {
|
|
container.tickClientSync();
|
|
}
|
|
}
|
|
|
|
protected void closeGui() {
|
|
this.flushPendingSync();
|
|
this.mc.thePlayer.closeScreen();
|
|
}
|
|
|
|
private void flushPendingSync() {
|
|
if (this.inventorySlots instanceof AEBaseContainer container) {
|
|
container.getSyncManager().flushClient();
|
|
}
|
|
}
|
|
|
|
protected boolean isCloseKey(final int keyCode) {
|
|
return keyCode == Keyboard.KEY_ESCAPE || keyCode == this.mc.gameSettings.keyBindInventory.getKeyCode();
|
|
}
|
|
|
|
@Nullable
|
|
protected Slot getSlot(final int mouseX, final int mouseY) {
|
|
final List<Slot> slots = this.getInventorySlots();
|
|
for (final Slot slot : slots) {
|
|
// isPointInRegion
|
|
if (this.func_146978_c(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, mouseX, mouseY)) {
|
|
return slot;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public abstract void drawBG(int offsetX, int offsetY, int mouseX, int mouseY);
|
|
|
|
private static boolean hasLwjgl3 = Loader.isModLoaded("lwjgl3ify");
|
|
|
|
@Override
|
|
public void handleMouseInput() {
|
|
super.handleMouseInput();
|
|
|
|
int wheel = Mouse.getEventDWheel();
|
|
if (wheel == 0) {
|
|
return;
|
|
}
|
|
if (!hasLwjgl3) {
|
|
// LWJGL2 reports different scroll values for every platform, 120 for one tick on Windows.
|
|
// LWJGL3 reports the delta in exact scroll ticks.
|
|
// Round away from zero to avoid dropping small scroll events
|
|
if (wheel > 0) {
|
|
wheel = (int) Platform.ceilDiv(wheel, 120);
|
|
} else {
|
|
wheel = -(int) Platform.ceilDiv(-wheel, 120);
|
|
}
|
|
}
|
|
|
|
final int x = Mouse.getEventX() * this.width / this.mc.displayWidth;
|
|
final int y = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
|
|
|
|
if (MinecraftForge.EVENT_BUS.post(new GuiScrollEvent(this, x, y, wheel))) {
|
|
return;
|
|
}
|
|
|
|
if (!this.mouseWheelEvent(x, y, wheel)) {
|
|
if (this.getScrollBar() != null) {
|
|
final GuiScrollbar scrollBar = this.getScrollBar();
|
|
|
|
if (x > this.guiLeft && y - this.guiTop > scrollBar.getTop()
|
|
&& x <= this.guiLeft + this.xSize
|
|
&& y - this.guiTop <= scrollBar.getTop() + scrollBar.getHeight()) {
|
|
this.getScrollBar().wheel(wheel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param x Current mouse X coordinate
|
|
* @param y Current mouse Y coordinate
|
|
* @param wheel Wheel movement normalized to units of 1
|
|
* @return If the event was handled
|
|
*/
|
|
protected boolean mouseWheelEvent(final int x, final int y, final int wheel) {
|
|
return false;
|
|
}
|
|
|
|
protected boolean enableSpaceClicking() {
|
|
return true;
|
|
}
|
|
|
|
public void bindTexture(final String base, final String file) {
|
|
final ResourceLocation loc = new ResourceLocation(base, "textures/" + file);
|
|
this.mc.getTextureManager().bindTexture(loc);
|
|
}
|
|
|
|
public void drawItem(final int x, final int y, final ItemStack is) {
|
|
this.zLevel = 100.0F;
|
|
itemRender.zLevel = 100.0F;
|
|
|
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
GL11.glEnable(GL11.GL_LIGHTING);
|
|
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
|
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
|
GL11.glTranslatef(0.0f, 0.0f, 101.0f);
|
|
RenderHelper.enableGUIStandardItemLighting();
|
|
itemRender.renderItemAndEffectIntoGUI(this.fontRendererObj, this.mc.renderEngine, is, x, y);
|
|
GL11.glTranslatef(0.0f, 0.0f, -101.0f);
|
|
GL11.glPopAttrib();
|
|
|
|
itemRender.zLevel = 0.0F;
|
|
this.zLevel = 0.0F;
|
|
}
|
|
|
|
protected String getGuiDisplayName(final String in) {
|
|
return this.hasCustomInventoryName() ? this.getInventoryName() : in;
|
|
}
|
|
|
|
private boolean hasCustomInventoryName() {
|
|
if (this.inventorySlots instanceof AEBaseContainer) {
|
|
return ((AEBaseContainer) this.inventorySlots).getCustomName() != null;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private String getInventoryName() {
|
|
return ((AEBaseContainer) this.inventorySlots).getCustomName();
|
|
}
|
|
|
|
public void drawTextureOnSlot(Slot s, int icon, float opacity) {
|
|
if (icon < 0) return; // no icon to draw.
|
|
|
|
this.bindTexture("guis/states.png");
|
|
|
|
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
|
final Tessellator tessellator = Tessellator.instance;
|
|
try {
|
|
final int uv_y = (int) Math.floor((double) icon / 16);
|
|
final int uv_x = icon - uv_y * 16;
|
|
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
GL11.glDisable(GL11.GL_LIGHTING);
|
|
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
|
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
|
GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
final float par1 = s.xDisplayPosition;
|
|
final float par2 = s.yDisplayPosition;
|
|
final float par3 = uv_x * 16;
|
|
final float par4 = uv_y * 16;
|
|
|
|
tessellator.startDrawingQuads();
|
|
tessellator.setColorRGBA_F(1.0f, 1.0f, 1.0f, opacity);
|
|
final float f1 = 0.00390625F;
|
|
final float f = 0.00390625F;
|
|
final float par6 = 16;
|
|
tessellator.addVertexWithUV(par1 + 0, par2 + par6, this.zLevel, (par3 + 0) * f, (par4 + par6) * f1);
|
|
final float par5 = 16;
|
|
tessellator.addVertexWithUV(par1 + par5, par2 + par6, this.zLevel, (par3 + par5) * f, (par4 + par6) * f1);
|
|
tessellator.addVertexWithUV(par1 + par5, par2 + 0, this.zLevel, (par3 + par5) * f, (par4 + 0) * f1);
|
|
tessellator.addVertexWithUV(par1 + 0, par2 + 0, this.zLevel, (par3 + 0) * f, (par4 + 0) * f1);
|
|
tessellator.setColorRGBA_F(1.0f, 1.0f, 1.0f, 1.0f);
|
|
tessellator.draw();
|
|
|
|
} catch (final Exception ignored) {}
|
|
GL11.glPopAttrib();
|
|
}
|
|
|
|
public void bindTexture(final String file) {
|
|
final ResourceLocation loc = new ResourceLocation(AppEng.MOD_ID, "textures/" + file);
|
|
this.mc.getTextureManager().bindTexture(loc);
|
|
}
|
|
|
|
public void bindTexture(final ResourceLocation loc) {
|
|
mc.getTextureManager().bindTexture(loc);
|
|
}
|
|
|
|
/**
|
|
* Draw slot
|
|
*/
|
|
public void func_146977_a(final Slot s) {
|
|
if (s instanceof SlotFake slotFake) {
|
|
this.drawSlotWithAEFont(slotFake);
|
|
return;
|
|
} else if (s instanceof AppEngSlot aeSlot) {
|
|
try {
|
|
final ItemStack is = s.getStack();
|
|
if (aeSlot.getBackgroundIconIndex() != null && is == null) {
|
|
IIcon iicon = aeSlot.getBackgroundIconIndex();
|
|
GL11.glDisable(GL11.GL_LIGHTING);
|
|
GL11.glEnable(GL11.GL_BLEND);
|
|
this.mc.getTextureManager().bindTexture(TextureMap.locationItemsTexture);
|
|
this.drawTexturedModelRectFromIcon(aeSlot.xDisplayPosition, aeSlot.yDisplayPosition, iicon, 16, 16);
|
|
GL11.glDisable(GL11.GL_BLEND);
|
|
GL11.glEnable(GL11.GL_LIGHTING);
|
|
} else if ((aeSlot.renderIconWithItem() || is == null) && aeSlot.shouldDisplay()) {
|
|
this.drawTextureOnSlot(s, aeSlot.getIcon(), aeSlot.getOpacityOfIcon());
|
|
}
|
|
|
|
if (is != null) {
|
|
if (aeSlot.getIsValid() == hasCalculatedValidness.NotAvailable) {
|
|
boolean isValid = s.isItemValid(is) || s instanceof SlotOutput
|
|
|| s instanceof AppEngCraftingSlot
|
|
|| s instanceof SlotDisabled
|
|
|| s instanceof SlotInaccessible
|
|
|| s instanceof SlotRestrictedInput;
|
|
if (isValid && s instanceof SlotRestrictedInput) {
|
|
try {
|
|
isValid = ((SlotRestrictedInput) s).isValid(is, this.mc.theWorld);
|
|
} catch (final Exception err) {
|
|
AELog.debug(err);
|
|
}
|
|
}
|
|
aeSlot.setIsValid(isValid ? hasCalculatedValidness.Valid : hasCalculatedValidness.Invalid);
|
|
}
|
|
|
|
if (aeSlot.getIsValid() == hasCalculatedValidness.Invalid) {
|
|
this.zLevel = 100.0F;
|
|
itemRender.zLevel = 100.0F;
|
|
|
|
GL11.glDisable(GL11.GL_LIGHTING);
|
|
drawRect(
|
|
s.xDisplayPosition,
|
|
s.yDisplayPosition,
|
|
16 + s.xDisplayPosition,
|
|
16 + s.yDisplayPosition,
|
|
GuiColors.ItemSlotOverlayInvalid.getColor());
|
|
GL11.glEnable(GL11.GL_LIGHTING);
|
|
|
|
this.zLevel = 0.0F;
|
|
itemRender.zLevel = 0.0F;
|
|
}
|
|
}
|
|
|
|
this.drawSlotWithAEFont(aeSlot);
|
|
|
|
return;
|
|
} catch (final Exception err) {
|
|
AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err.toString());
|
|
}
|
|
}
|
|
|
|
// do the usual for non-ME Slots.
|
|
super.func_146977_a(s);
|
|
}
|
|
|
|
private void drawSlotWithAEFont(AppEngSlot aeSlot) {
|
|
aeSlot.setDisplay(true);
|
|
|
|
// Set stack size to 1 to disable standard stack size drawing
|
|
final ItemStack stackToDraw = aeSlot.getStack();
|
|
long stackSize = 0;
|
|
if (stackToDraw != null) {
|
|
stackSize = aeSlot instanceof SlotRestrictedInput rSlot ? rSlot.getStackSize() : stackToDraw.stackSize;
|
|
stackToDraw.stackSize = 1;
|
|
}
|
|
|
|
// Draw slot
|
|
super.func_146977_a(aeSlot);
|
|
|
|
// Draw stack size
|
|
if (stackSize > 1) {
|
|
boolean useAEFont = aeSlot instanceof SlotFake || aeSlot instanceof OptionalSlotRestrictedInput
|
|
|| (aeSlot instanceof SlotRestrictedInput restrictedInput
|
|
&& restrictedInput.getItemType() == PlacableItemType.ENCODED_PATTERN);
|
|
TerminalFontSize fontSize = useAEFont ? AEConfig.instance.getTerminalFontSize() : null;
|
|
GL11.glTranslatef(0.0f, 0.0f, 300);
|
|
GL11.glDisable(GL11.GL_LIGHTING);
|
|
GL11.glDisable(GL11.GL_BLEND);
|
|
StackSizeRenderer.drawStackSize(
|
|
aeSlot.xDisplayPosition,
|
|
aeSlot.yDisplayPosition,
|
|
StackSizeRenderer.getToBeRenderedStackSize(stackSize, fontSize),
|
|
this.mc.fontRenderer,
|
|
fontSize);
|
|
GL11.glEnable(GL11.GL_LIGHTING);
|
|
GL11.glTranslatef(0.0f, 0.0f, -300);
|
|
}
|
|
|
|
// Restore stack size
|
|
if (stackToDraw != null) {
|
|
stackToDraw.stackSize = (int) Math.min(stackSize, Integer.MAX_VALUE);
|
|
}
|
|
|
|
aeSlot.setDisplay(false);
|
|
}
|
|
|
|
protected GuiScrollbar getScrollBar() {
|
|
return this.scrollBar;
|
|
}
|
|
|
|
protected void setScrollBar(final GuiScrollbar myScrollBar) {
|
|
this.scrollBar = myScrollBar;
|
|
}
|
|
|
|
public static final synchronized boolean isSwitchingGuis() {
|
|
return switchingGuis;
|
|
}
|
|
|
|
public static final synchronized void setSwitchingGuis(final boolean switchingGuis) {
|
|
AEBaseGui.switchingGuis = switchingGuis;
|
|
}
|
|
|
|
protected void addItemTooltip(ItemStack is, List<String> lineList) {
|
|
if (isShiftKeyDown()) {
|
|
List<String> l = is.getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips);
|
|
if (!l.isEmpty()) l.remove(0);
|
|
lineList.addAll(l);
|
|
} else {
|
|
lineList.add(GuiText.HoldShiftForTooltip.getLocal());
|
|
}
|
|
}
|
|
|
|
// Accessors for protected GUI methods to make them reusable in widget classes
|
|
|
|
public FontRenderer getFontRenderer() {
|
|
return fontRendererObj;
|
|
}
|
|
|
|
@Override
|
|
public void drawHorizontalLine(int startX, int endX, int y, int color) {
|
|
super.drawHorizontalLine(startX, endX, y, color);
|
|
}
|
|
|
|
@Override
|
|
public void drawVerticalLine(int x, int startY, int endY, int color) {
|
|
super.drawVerticalLine(x, startY, endY, color);
|
|
}
|
|
|
|
@Override
|
|
public void drawGradientRect(int left, int top, int right, int bottom, int startColor, int endColor) {
|
|
super.drawGradientRect(left, top, right, bottom, startColor, endColor);
|
|
}
|
|
|
|
@Override
|
|
public void renderToolTip(ItemStack itemIn, int x, int y) {
|
|
super.renderToolTip(itemIn, x, y);
|
|
}
|
|
|
|
@Override
|
|
public void drawCreativeTabHoveringText(String tabName, int mouseX, int mouseY) {
|
|
super.drawCreativeTabHoveringText(tabName, mouseX, mouseY);
|
|
}
|
|
|
|
public void drawHoveringText(List<String> textLines, int x, int y) {
|
|
super.func_146283_a(textLines, x, y);
|
|
}
|
|
|
|
@Override
|
|
public void drawHoveringText(List<String> textLines, int x, int y, FontRenderer font) {
|
|
super.drawHoveringText(textLines, x, y, font);
|
|
}
|
|
|
|
public boolean isMouseOverRect(int left, int top, int right, int bottom, int pointX, int pointY) {
|
|
return super.func_146978_c(left, top, right, bottom, pointX, pointY);
|
|
}
|
|
|
|
public int getGuiLeft() {
|
|
return guiLeft;
|
|
}
|
|
|
|
public int getGuiTop() {
|
|
return guiTop;
|
|
}
|
|
|
|
public int getXSize() {
|
|
return xSize;
|
|
}
|
|
|
|
public int getYSize() {
|
|
return ySize;
|
|
}
|
|
|
|
public static boolean isCtrlKeyDown() {
|
|
int keyCode = CONTAINER_INTERACTION_KEY.getKeyCode();
|
|
if (keyCode < 0) {
|
|
// In vanilla code, mouse buttons are registered as keyCodes with their values offset by -100.
|
|
return Mouse.isButtonDown(keyCode + 100);
|
|
} else {
|
|
return Keyboard.isKeyDown(keyCode);
|
|
}
|
|
}
|
|
|
|
private void drawVirtualSlots(@Nonnull List<VirtualMESlot> slots, int mouseX, int mouseY) {
|
|
final int x = mouseX - this.guiLeft + 1;
|
|
final int y = mouseY - this.guiTop + 1;
|
|
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
|
|
|
|
for (VirtualMESlot slot : slots) {
|
|
boolean isHovered = slot.drawStackAndOverlay(this.mc, x, y);
|
|
if (isHovered) {
|
|
this.hoveredVirtualSlot = slot;
|
|
}
|
|
}
|
|
GL11.glPopAttrib();
|
|
}
|
|
|
|
public @Nullable VirtualMESlot getVirtualMESlotUnderMouse() {
|
|
return this.hoveredVirtualSlot;
|
|
}
|
|
|
|
public void initCustomButtons(int xOffset, int yOffset) {
|
|
if (inventorySlots instanceof AEBaseContainer abc && abc.getTarget() instanceof ICustomButtonProvider icbp)
|
|
icbp.initCustomButtons(
|
|
this.guiLeft,
|
|
this.guiTop,
|
|
this.xSize,
|
|
this.ySize,
|
|
xOffset,
|
|
yOffset,
|
|
this.buttonList);
|
|
}
|
|
|
|
public boolean actionPerformedCustomButtons(final GuiButton btn) {
|
|
if (inventorySlots instanceof AEBaseContainer abc && abc.getTarget() instanceof ICustomButtonProvider icbp)
|
|
return icbp.actionPerformedCustomButtons(btn);
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public List<String> handleItemTooltip(final ItemStack stack, final int mouseX, final int mouseY,
|
|
final List<String> currentToolTip) {
|
|
VirtualMESlot hoveredSlot = this.getVirtualMESlotUnderMouse();
|
|
if (hoveredSlot == null) return currentToolTip;
|
|
|
|
if (hoveredSlot.getAEStack() instanceof IAEFluidStack afs) {
|
|
if (currentToolTip.isEmpty()) {
|
|
currentToolTip.add(afs.getDisplayName());
|
|
} else {
|
|
currentToolTip.set(0, afs.getDisplayName());
|
|
}
|
|
}
|
|
|
|
return currentToolTip;
|
|
}
|
|
|
|
@Override
|
|
public ItemStack getHoveredStack() {
|
|
VirtualMESlot hoveredSlot = this.getVirtualMESlotUnderMouse();
|
|
if (hoveredSlot == null) return null;
|
|
|
|
IAEStack<?> hoveredAEStack = hoveredSlot.getAEStack();
|
|
if (hoveredAEStack == null) return null;
|
|
|
|
return hoveredAEStack.getItemStackForNEI();
|
|
}
|
|
|
|
@Override
|
|
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) {
|
|
return currentVisibility;
|
|
}
|
|
|
|
@Override
|
|
public Iterable<Integer> getItemSpawnSlots(GuiContainer gui, ItemStack item) {
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
@Override
|
|
public List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
|
return false;
|
|
}
|
|
|
|
public void triggerActionPerformed(final GuiButton btn) {
|
|
GuiScreenEvent.ActionPerformedEvent.Pre event = new GuiScreenEvent.ActionPerformedEvent.Pre(
|
|
this,
|
|
btn,
|
|
this.buttonList);
|
|
if (MinecraftForge.EVENT_BUS.post(event)) return;
|
|
|
|
event.button.func_146113_a(this.mc.getSoundHandler());
|
|
this.actionPerformed(event.button);
|
|
if (this.equals(this.mc.currentScreen)) MinecraftForge.EVENT_BUS
|
|
.post(new GuiScreenEvent.ActionPerformedEvent.Post(this, event.button, this.buttonList));
|
|
}
|
|
}
|