package fi.dy.masa.enderutilities.gui.client; import java.io.IOException; import java.util.Collection; import org.lwjgl.input.Keyboard; import com.google.common.collect.Ordering; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import fi.dy.masa.enderutilities.gui.client.base.GuiContainerLargeStacks; import fi.dy.masa.enderutilities.gui.client.button.GuiButtonHoverText; import fi.dy.masa.enderutilities.gui.client.button.GuiButtonIcon; import fi.dy.masa.enderutilities.gui.client.button.GuiButtonStateCallback; import fi.dy.masa.enderutilities.gui.client.button.GuiButtonStateCallback.ButtonState; import fi.dy.masa.enderutilities.gui.client.button.IButtonStateCallback; import fi.dy.masa.enderutilities.inventory.container.ContainerHandyBag; import fi.dy.masa.enderutilities.inventory.item.InventoryItemModular; import fi.dy.masa.enderutilities.item.ItemHandyBag; import fi.dy.masa.enderutilities.item.ItemHandyBag.PickupMode; import fi.dy.masa.enderutilities.item.ItemHandyBag.RestockMode; import fi.dy.masa.enderutilities.item.ItemHandyBag.ShiftMode; import fi.dy.masa.enderutilities.network.PacketHandler; import fi.dy.masa.enderutilities.network.message.MessageGuiAction; import fi.dy.masa.enderutilities.reference.ReferenceGuiIds; import fi.dy.masa.enderutilities.registry.ModRegistry; import fi.dy.masa.enderutilities.util.nbt.NBTUtils; public class GuiHandyBag extends GuiContainerLargeStacks implements IButtonStateCallback { public static final int BTN_ID_FIRST_SELECT_MODULE = 0; public static final int BTN_ID_FIRST_MOVE_ITEMS = 4; public static final int BTN_ID_FIRST_SORT = 10; public static final int BTN_ID_FIRST_BLOCK = 14; public static final int BTN_ID_FIRST_MODES = 17; public static final int BTN_ID_BAUBLES = 100; private static final String[] BUTTON_STRINGS = new String[] { "enderutilities.gui.label.moveallitemsexcepthotbar", "enderutilities.gui.label.movematchingitemsexcepthotbar", "enderutilities.gui.label.leaveonefilledstack", "enderutilities.gui.label.fillstacks", "enderutilities.gui.label.movematchingitems", "enderutilities.gui.label.moveallitems", "enderutilities.gui.label.sortitems" }; private final ContainerHandyBag containerHB; private final InventoryItemModular invModular; private final int invSize; private final int numModuleSlots; private final int bagTier; private final int offsetXTier; private float oldMouseX; private float oldMouseY; private int firstModuleSlotX; private int firstModuleSlotY; private boolean hasActivePotionEffects; private int[] lastPos = new int[2]; private final boolean baublesLoaded; public static final ResourceLocation RESOURCES_BAUBLES_BUTTON = new ResourceLocation(ModRegistry.MODID_BAUBLES.toLowerCase(), "textures/gui/expanded_inventory.png"); public GuiHandyBag(ContainerHandyBag container) { super(container, container.getBagTier() == 1 ? 256 : 176, 256, "gui.container.handybag." + container.getBagTier()); this.containerHB = container; this.invModular = container.inventoryItemModular; this.invSize = this.invModular.getSlots(); this.numModuleSlots = this.invModular.getModuleInventory().getSlots(); this.bagTier = this.containerHB.getBagTier(); this.offsetXTier = this.bagTier == 1 ? 40 : 0; this.baublesLoaded = ModRegistry.isModLoadedBaubles(); this.scaledStackSizeTextInventories.add(this.invModular); } private void updatePositions() { this.firstModuleSlotX = this.guiLeft + this.containerHB.getSlot(0).xPos + 5 * 18; this.firstModuleSlotY = this.guiTop + this.containerHB.getSlot(0).yPos - 33; this.createButtons(); this.lastPos[0] = this.guiLeft; this.lastPos[1] = this.guiTop; } private boolean needsPositionUpdate() { return this.lastPos[0] != this.guiLeft || this.lastPos[1] != this.guiTop; } @Override public void initGui() { super.initGui(); this.updatePositions(); this.updateActivePotionEffects(); // This fixes the vanilla Realms notification stuff (if enabled) enabling this, // which causes the double-tap shift behavior to quickly flicker Keyboard.enableRepeatEvents(false); } @Override public void updateScreen() { super.updateScreen(); this.updateActivePotionEffects(); } @Override public void drawScreen(int mouseX, int mouseY, float gameTicks) { super.drawScreen(mouseX, mouseY, gameTicks); if (this.needsPositionUpdate()) { this.updatePositions(); } if (this.hasActivePotionEffects) { this.drawActivePotionEffects(); } this.drawTooltips(mouseX, mouseY); this.oldMouseX = (float)mouseX; this.oldMouseY = (float)mouseY; } @Override protected void drawGuiContainerBackgroundLayer(float gameTicks, int mouseX, int mouseY) { GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); this.bindTexture(this.guiTexture); this.drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize); this.bindTexture(this.guiTextureWidgets); // The inventory is not accessible (because there is no valid Memory Card selected) if (this.invModular.isAccessibleBy(this.player) == false) { // Draw the dark background icon over the disabled inventory slots for (int i = 0; i < this.invSize; i++) { Slot slot = this.containerHB.getSlot(i); this.drawTexturedModalRect(this.guiLeft + slot.xPos - 1, this.guiTop + slot.yPos - 1, 102, 0, 18, 18); } } // Memory Card slots are not accessible, because the opened bag isn't currently available // Draw the dark background icon over the disabled slots if (this.invModular.getModuleInventory().isAccessibleBy(this.player) == false) { for (int i = 0; i < this.numModuleSlots; i++) { this.drawTexturedModalRect(this.firstModuleSlotX - 1 + i * 18, this.firstModuleSlotY - 1, 102, 0, 18, 18); } } // Draw the colored background for the selected module slot int index = this.invModular.getSelectedModuleIndex(); if (index >= 0) { this.drawTexturedModalRect(this.firstModuleSlotX - 1 + index * 18, this.firstModuleSlotY - 1, 102, 18, 18, 18); // Draw the selection border around the selected memory card module's selection button this.drawTexturedModalRect(this.firstModuleSlotX + 3 + index * 18, this.firstModuleSlotY + 18, 120, 0, 10, 10); } // Draw the background icon over empty storage module slots for (int i = 0; i < this.numModuleSlots; i++) { if (this.invModular.getModuleInventory().getStackInSlot(i).isEmpty()) { this.drawTexturedModalRect(this.firstModuleSlotX + i * 18, this.firstModuleSlotY, 240, 80, 16, 16); } } if (this.containerHB.getBagTier() == 1) { int x = (this.width - this.xSize) / 2; int y = (this.height - this.ySize) / 2; int[] xPos = new int[] { 115 - 1, 21 - 1, 227 - 1 }; for (int i = 0; i < 3; i++) { if (this.isMaskActiveForSection(i, "LockMask")) { // Draw the hilight border for active Block-Quick-Actions buttons this.drawTexturedModalRect(x + xPos[i], y + 90, 120, 24, 10, 10); } } } // Draw the shift-click double-tap mode's effective mode indication, if applicable ItemStack modularStack = this.containerHB.inventoryItemModular.getModularItemStack(); if (modularStack.isEmpty() == false && ShiftMode.getEffectiveMode(modularStack) == ShiftMode.TO_BAG) { int x = this.guiLeft + this.offsetXTier + 64; this.drawTexturedModalRect(x, this.guiTop + 157, 154, 0, 12, 12); } int xOff = this.guiLeft + 51 + this.offsetXTier; // Draw the player model GuiInventory.drawEntityOnScreen(xOff, this.guiTop + 82, 30, xOff - this.oldMouseX, this.guiTop + 25 - this.oldMouseY, this.mc.player); } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { int xOff = this.offsetXTier; this.fontRenderer.drawString(I18n.format("container.crafting"), xOff + 97, 5, 0x404040); this.fontRenderer.drawString(I18n.format("enderutilities.gui.label.memorycards"), xOff + 99, 59, 0x404040); this.fontRenderer.drawString(I18n.format("enderutilities.container.handybag"), xOff + 8, 5, 0x404040); } protected void createButtons() { this.buttonList.clear(); // Add the Memory Card selection buttons int numModules = this.invModular.getModuleInventory().getSlots(); for (int i = 0; i < numModules; i++) { this.buttonList.add(new GuiButtonIcon(BTN_ID_FIRST_SELECT_MODULE + i, this.firstModuleSlotX + 4 + i * 18, this.firstModuleSlotY + 19, 8, 8, 0, 0, this.guiTextureWidgets, 8, 0)); } int x = this.guiLeft + this.containerHB.getSlot(0).xPos + 2; int y = this.guiTop + this.containerHB.getSlot(0).yPos + 55; // Add the quick move items buttons this.buttonList.add(new GuiButtonHoverText(BTN_ID_FIRST_MOVE_ITEMS + 0, x + 0, y + 0, 12, 12, 24, 0, this.guiTextureWidgets, 12, 0, "enderutilities.gui.label.moveallitemsexcepthotbar", "enderutilities.gui.label.holdshifttoincludehotbar")); this.buttonList.add(new GuiButtonHoverText(BTN_ID_FIRST_MOVE_ITEMS + 1, x + 18, y + 0, 12, 12, 24, 12, this.guiTextureWidgets, 12, 0, "enderutilities.gui.label.movematchingitemsexcepthotbar", "enderutilities.gui.label.holdshifttoincludehotbar")); int[] xOff = new int[] { 36, 108, 126, 144 }; for (int i = 2; i < 6; i++) { this.buttonList.add(new GuiButtonHoverText(BTN_ID_FIRST_MOVE_ITEMS + i, x + xOff[i - 2], y, 12, 12, 24, i * 12, this.guiTextureWidgets, 12, 0, BUTTON_STRINGS[i])); } y = this.guiTop + this.containerHB.getSlot(0).yPos - 11; // Locked mode toggle this.buttonList.add(new GuiButtonStateCallback(BTN_ID_FIRST_MODES + 0, x - 1, y, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 48, "enderutilities.gui.label.bag.disabled"), ButtonState.createTranslate(0, 0, "enderutilities.gui.label.bag.enabled"))); // Pickup mode toggle this.buttonList.add(new GuiButtonStateCallback(BTN_ID_FIRST_MODES + 1, x + 23, y, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.pickupmode.disabled"), ButtonState.createTranslate(0, 56, "enderutilities.gui.label.pickupmode.matching"), ButtonState.createTranslate(0, 64, "enderutilities.gui.label.pickupmode.all"))); // Restock mode toggle this.buttonList.add(new GuiButtonStateCallback(BTN_ID_FIRST_MODES + 2, x + 11, y, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.restockmode.disabled"), ButtonState.createTranslate(0, 80, "enderutilities.gui.label.restockmode.hotbar"), ButtonState.createTranslate(0, 72, "enderutilities.gui.label.restockmode.all"))); this.buttonList.add(new GuiButtonStateCallback(23, x + 35, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 16, ShiftMode.TO_BAG.getUnlocName()), ButtonState.createTranslate(0, 96, ShiftMode.INV_HOTBAR.getUnlocName()), ButtonState.createTranslate(0, 104, ShiftMode.DOUBLE_TAP.getUnlocName()))); if (this.bagTier == 0) { // Add the sort button this.buttonList.add(new GuiButtonHoverText(10, x + 74, y + 0, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, BUTTON_STRINGS[6])); // Sort player inventory this.buttonList.add(new GuiButtonHoverText(13, x + 74, y + 70, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, "enderutilities.gui.label.sortitems.player")); this.buttonList.add(new GuiButtonStateCallback(20, x + 62, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.updateitems.disabled"), ButtonState.createTranslate(0, 88, "enderutilities.gui.label.updateitems.enabled"))); } else { // Add the sort buttons this.buttonList.add(new GuiButtonHoverText(11, x - 17, y + 0, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, BUTTON_STRINGS[6])); this.buttonList.add(new GuiButtonHoverText(10, x + 53, y + 0, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, BUTTON_STRINGS[6])); this.buttonList.add(new GuiButtonHoverText(12, x + 165, y + 0, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, BUTTON_STRINGS[6])); // Sort player inventory this.buttonList.add(new GuiButtonHoverText(13, x + 74, y + 70, 8, 8, 0, 24, this.guiTextureWidgets, 8, 0, "enderutilities.gui.label.sortitems.player")); // Add the section locking buttons this.buttonList.add(new GuiButtonStateCallback(15, x - 29, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 0, "enderutilities.gui.label.blockquickactions.disabled"), ButtonState.createTranslate(0, 40, "enderutilities.gui.label.blockquickactions.enabled"))); this.buttonList.add(new GuiButtonStateCallback(14, x + 65, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 0, "enderutilities.gui.label.blockquickactions.disabled"), ButtonState.createTranslate(0, 40, "enderutilities.gui.label.blockquickactions.enabled"))); this.buttonList.add(new GuiButtonStateCallback(16, x + 177, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 0, "enderutilities.gui.label.blockquickactions.disabled"), ButtonState.createTranslate(0, 40, "enderutilities.gui.label.blockquickactions.enabled"))); // Add the update-items-in-section buttons this.buttonList.add(new GuiButtonStateCallback(21, x - 41, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.updateitems.disabled"), ButtonState.createTranslate(0, 88, "enderutilities.gui.label.updateitems.enabled"))); this.buttonList.add(new GuiButtonStateCallback(20, x + 77, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.updateitems.disabled"), ButtonState.createTranslate(0, 88, "enderutilities.gui.label.updateitems.enabled"))); this.buttonList.add(new GuiButtonStateCallback(22, x + 189, y + 0, 8, 8, 8, 0, this.guiTextureWidgets, this, ButtonState.createTranslate(0, 40, "enderutilities.gui.label.updateitems.disabled"), ButtonState.createTranslate(0, 88, "enderutilities.gui.label.updateitems.enabled"))); } if (this.baublesLoaded) { // The texture comes from the Baubles expanded inventory texture this.buttonList.add(new GuiButtonHoverText(BTN_ID_BAUBLES, this.guiLeft + 68 + this.offsetXTier, this.guiTop + 15, 10, 10, 190, 48, RESOURCES_BAUBLES_BUTTON, 10, 0, "Baubles")); } } @Override protected void actionPerformedWithButton(GuiButton button, int mouseButton) throws IOException { super.actionPerformed(button); if (button.id >= BTN_ID_FIRST_SELECT_MODULE && button.id < (BTN_ID_FIRST_SELECT_MODULE + this.numModuleSlots)) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_SELECT_MODULE, button.id - BTN_ID_FIRST_SELECT_MODULE)); } else if (button.id >= BTN_ID_FIRST_MOVE_ITEMS && button.id <= (BTN_ID_FIRST_MOVE_ITEMS + 5)) { int value = button.id - BTN_ID_FIRST_MOVE_ITEMS; if (GuiScreen.isShiftKeyDown()) { value |= 0x8000; } PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_MOVE_ITEMS, value)); } else if (button.id >= BTN_ID_FIRST_SORT && button.id < (BTN_ID_FIRST_SORT + 4)) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_SORT_ITEMS, button.id - BTN_ID_FIRST_SORT)); } else if (button.id >= BTN_ID_FIRST_BLOCK && button.id < (BTN_ID_FIRST_BLOCK + 3)) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_TOGGLE_BLOCK, button.id - BTN_ID_FIRST_BLOCK)); } else if (button.id >= BTN_ID_FIRST_MODES && button.id < (BTN_ID_FIRST_MODES + 3)) { int data = button.id - BTN_ID_FIRST_MODES; if (mouseButton == 1) { data |= 0x8000; } PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_TOGGLE_MODES, data)); } else if (button.id >= 20 && button.id <= 22) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_TOGGLE_UPDATE, button.id - 20)); } else if (button.id == 23) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_TOGGLE_SHIFTCLICK, mouseButton)); } else if (button.id == 100 && this.baublesLoaded) { PacketHandler.INSTANCE.sendToServer(new MessageGuiAction(0, new BlockPos(0, 0, 0), ReferenceGuiIds.GUI_ID_HANDY_BAG, ItemHandyBag.GUI_ACTION_OPEN_BAUBLES, 0)); } } protected void updateActivePotionEffects() { boolean hasVisibleEffect = false; for (PotionEffect potioneffect : this.mc.player.getActivePotionEffects()) { Potion potion = potioneffect.getPotion(); if (potion.shouldRender(potioneffect)) { hasVisibleEffect = true; break; } } if (this.mc.player.getActivePotionEffects().isEmpty() == false && hasVisibleEffect) { if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.GuiScreenEvent.PotionShiftEvent(this))) { this.guiLeft = (this.width - this.xSize) / 2; } else { this.guiLeft = 160 + (this.width - this.xSize - 200) / 2; } this.hasActivePotionEffects = true; } else { this.guiLeft = (this.width - this.xSize) / 2; this.hasActivePotionEffects = false; } } private void drawActivePotionEffects() { int x = this.guiLeft - 124; int y = this.guiTop; Collection<PotionEffect> collection = this.mc.player.getActivePotionEffects(); if (collection.isEmpty() == false) { GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.disableLighting(); int entryHeight = 33; if (collection.size() > 5) { entryHeight = 132 / (collection.size() - 1); } for (PotionEffect potioneffect : Ordering.natural().sortedCopy(collection)) { Potion potion = potioneffect.getPotion(); if (potion.shouldRender(potioneffect) == false) { continue; } GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(INVENTORY_BACKGROUND); this.drawTexturedModalRect(x, y, 0, 166, 140, 32); if (potion.hasStatusIcon()) { int i1 = potion.getStatusIconIndex(); this.drawTexturedModalRect(x + 6, y + 7, 0 + i1 % 8 * 18, 198 + i1 / 8 * 18, 18, 18); } potion.renderInventoryEffect(potioneffect, this, x, y, this.zLevel); if (potion.shouldRenderInvText(potioneffect) == false) { y += entryHeight; continue; } String s1 = I18n.format(potion.getName()); int amp = potioneffect.getAmplifier(); if (amp >= 1 && amp <= 3) { s1 = s1 + " " + I18n.format("enchantment.level." + (amp + 1)); } this.fontRenderer.drawStringWithShadow(s1, (float)(x + 10 + 18), (float)(y + 6), 16777215); String s = Potion.getPotionDurationString(potioneffect, 1.0F); this.fontRenderer.drawStringWithShadow(s, (float)(x + 10 + 18), (float)(y + 6 + 10), 8355711); y += entryHeight; } } } @Override public int getButtonStateIndex(int callbackId) { ItemStack stack = this.containerHB.getContainerItem(); if (stack.isEmpty() == false) { // Locked mode if (callbackId == BTN_ID_FIRST_MODES) { return NBTUtils.getBoolean(stack, "HandyBag", "DisableOpen") ? 0 : 1; } // Pickup mode else if (callbackId == BTN_ID_FIRST_MODES + 1) { PickupMode mode = ItemHandyBag.PickupMode.fromStack(stack); if (mode == PickupMode.ALL) { return 2; } else if (mode == PickupMode.MATCHING) { return 1; } return 0; // blocked/none } // Restock mode else if (callbackId == BTN_ID_FIRST_MODES + 2) { RestockMode mode = ItemHandyBag.RestockMode.fromStack(stack); if (mode == RestockMode.ALL) { return 2; } else if (mode == RestockMode.HOTBAR) { return 1; } return 0; // blocked/none } // Block quick actions else if (callbackId >= 14 && callbackId <= 16) { return this.isMaskActiveForSection(callbackId - 14, "LockMask") ? 1 : 0; } // Update items else if (callbackId >= 20 && callbackId <= 22) { return this.isMaskActiveForSection(callbackId - 20, "UpdateMask") ? 1 : 0; } // Shift-click behaviour else if (callbackId == 23) { return MathHelper.clamp(NBTUtils.getByte(stack, "HandyBag", "ShiftMode") & 0x3, 0, 2); } } return 0; } @Override public boolean isButtonEnabled(int callbackId) { return true; } private boolean isMaskActiveForSection(int section, String tagName) { int selected = this.invModular.getSelectedModuleIndex(); if (selected >= 0 && section >= 0 && section <= 2) { ItemStack stack = this.invModular.getModuleInventory().getStackInSlot(selected); if (stack.isEmpty() == false) { long[] masks = new long[] { 0x1FFFFFFL, 0x1FFF8000000L, 0x7FFE0000000000L }; long lockMask = NBTUtils.getLong(stack, "HandyBag", tagName); if ((lockMask & masks[section]) == masks[section]) { return true; } } } return false; } }