/* * Copyright (C) 2022 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates 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. * * NotEnoughUpdates 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 NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.config.ConfigUtil; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.events.ReplaceItemEvent; import io.github.moulberry.notenoughupdates.events.SlotClickEvent; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import lombok.var; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.ISound; import net.minecraft.client.audio.PositionedSound; import net.minecraft.client.audio.SoundCategory; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector2f; import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @NEUAutoSubscribe public class SlotLocking { private static final SlotLocking INSTANCE = new SlotLocking(); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final LockedSlot DEFAULT_LOCKED_SLOT = new LockedSlot(); private final ResourceLocation LOCK = new ResourceLocation("notenoughupdates:slotlocking/lock.png"); private final ResourceLocation BOUND = new ResourceLocation("notenoughupdates:slotlocking/bound.png"); public static SlotLocking getInstance() { return INSTANCE; } public static class LockedSlot { public boolean locked = false; public int boundTo = -1; } public static class SlotLockData { public LockedSlot[] lockedSlots = new LockedSlot[40]; public LockedSlot[] riftLockedSlots = new LockedSlot[40]; } public static class SlotLockProfile { public SlotLockData[] slotLockData = new SlotLockData[1]; } public static class SlotLockingConfig { public HashMap profileData = new HashMap<>(); } private SlotLockingConfig config = new SlotLockingConfig(); private boolean lockKeyHeld = false; private Slot pairingSlot = null; private Slot realSlot = null; public void setRealSlot(Slot slot) { realSlot = slot; } public Slot getRealSlot() {return realSlot;} public void loadConfig(File file) { config = ConfigUtil.loadConfig(SlotLockingConfig.class, file, GSON); if (config == null) { config = new SlotLockingConfig(); } } public void changedSlot(int slotNumber) { int pingModifier = NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSwapDelay; if (pingModifier == 0) { return; } if (!isSlotIndexLocked(slotNumber)) { return; } long currentTimeMilis = System.currentTimeMillis(); for (int i = 0; i < slotChanges.length; i++) { if (i != slotNumber && slotChanges[i] != 0 && (slotChanges[i] + (long) pingModifier) > currentTimeMilis) { slotChanges[i] = 0; } } slotChanges[slotNumber] = currentTimeMilis; } public boolean isSwapedSlotLocked() { int pingModifier = NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSwapDelay; if (pingModifier == 0) { return false; } long currentTimeMilis = System.currentTimeMillis(); for (int i = 0; i < slotChanges.length; i++) { if (slotChanges[i] != 0 && isSlotIndexLocked(i) && (slotChanges[i] + (long) pingModifier) > currentTimeMilis) { return true; } } return false; } private final long[] slotChanges = new long[9]; public void saveConfig(File file) { ConfigUtil.saveConfig(config, file, GSON); } private static final Pattern WINDOW_REGEX = Pattern.compile(".+ Backpack (?:✦ )?\\(Slot #(\\d+)\\)"); private static final Pattern ECHEST_WINDOW_REGEX = Pattern.compile("Ender Chest \\((\\d+)/(\\d+)\\)"); private LockedSlot[] getDataForProfile() { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || !NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking) return null; if (NotEnoughUpdates.INSTANCE.config.slotLocking.disableInStorage) { if (StorageManager.getInstance().isStorageOpen) return null; String openChestName = Utils.getOpenChestName(); if (openChestName.trim().equals("Storage")) return null; openChestName = Utils.cleanColour(openChestName); Matcher matcher = WINDOW_REGEX.matcher(openChestName); Matcher matcherEchest = ECHEST_WINDOW_REGEX.matcher(openChestName); if (matcher.matches() || matcherEchest.matches()) { return null; } } String profileName = SBInfo.getInstance().currentProfile; if (profileName == null) profileName = "generic"; SlotLockProfile profile = config.profileData.computeIfAbsent( profileName, k -> new SlotLockProfile() ); if (profile.slotLockData[0] == null) { profile.slotLockData[0] = new SlotLockData(); } if (!"rift".equals(SBInfo.getInstance().getLocation())) { return profile.slotLockData[0].lockedSlots; } else { return profile.slotLockData[0].riftLockedSlots; } } private LockedSlot getLockedSlot(LockedSlot[] lockedSlots, int index) { if (lockedSlots == null) { return DEFAULT_LOCKED_SLOT; } LockedSlot slot = lockedSlots[index]; if (slot == null) { return DEFAULT_LOCKED_SLOT; } return slot; } private Slot getFocusedSlot(GuiContainer container) { final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); final int scaledWidth = scaledresolution.getScaledWidth(); final int scaledHeight = scaledresolution.getScaledHeight(); int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; return ((AccessorGuiContainer) container).doGetSlotAtPosition(mouseX, mouseY); } @SubscribeEvent(priority = EventPriority.LOW) public void keyboardInput(GuiScreenEvent.KeyboardInputEvent.Pre event) { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || !NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking) { return; } if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen; int key = NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockKey; if (!lockKeyHeld && KeybindHelper.isKeyPressed(key) && !Keyboard.isRepeatEvent()) { Slot slot = getFocusedSlot(container); if (slot != null && slot.getSlotIndex() != 8 && slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) { int slotNum = slot.getSlotIndex(); if (slotNum >= 0 && slotNum <= 39) { boolean isHotbar = slotNum < 9; boolean isInventory = !isHotbar && slotNum < 36; boolean isArmor = !isHotbar && !isInventory; if (isInventory || isArmor) { pairingSlot = slot; } else { pairingSlot = null; } LockedSlot[] lockedSlots = getDataForProfile(); if (lockedSlots != null) { if (lockedSlots[slotNum] == null) { lockedSlots[slotNum] = new LockedSlot(); } lockedSlots[slotNum].locked = !lockedSlots[slotNum].locked; lockedSlots[slotNum].boundTo = -1; if (NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSound) { float vol = NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSoundVol / 100f; if (vol > 0) { if (vol > 1) vol = 1; final float volF = vol; final boolean locked = lockedSlots[slotNum].locked; ISound sound = new PositionedSound(new ResourceLocation("random.orb")) {{ volume = volF; pitch = locked ? 0.943f : 0.1f; repeat = false; repeatDelay = 0; attenuationType = ISound.AttenuationType.NONE; }}; float oldLevel = Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.PLAYERS); Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, 1); Minecraft.getMinecraft().getSoundHandler().playSound(sound); Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, oldLevel); } } if (isHotbar && lockedSlots[slotNum].locked) { for (int i = 9; i <= 39; i++) { if (lockedSlots[i] != null && lockedSlots[i].boundTo == slotNum) { lockedSlots[i].boundTo = -1; } } } } } } } lockKeyHeld = KeybindHelper.isKeyDown(key); if (!lockKeyHeld) { pairingSlot = null; } } @SubscribeEvent(priority = EventPriority.LOW) public void mouseEvent(GuiScreenEvent.MouseInputEvent.Pre event) { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || !NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking) { return; } if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen; if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && lockKeyHeld && pairingSlot != null) { final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); final int scaledWidth = scaledresolution.getScaledWidth(); final int scaledHeight = scaledresolution.getScaledHeight(); int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; Slot slot = ((AccessorGuiContainer) container).doGetSlotAtPosition(mouseX, mouseY); if (slot != null && slot.getSlotIndex() != 8 && slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) { int slotNum = slot.getSlotIndex(); if (slotNum >= 0 && slotNum <= 39) { boolean isHotbar = slotNum < 9; boolean isInventory = !isHotbar && slotNum < 36; boolean isArmor = !isHotbar && !isInventory; int pairingNum = pairingSlot.getSlotIndex(); if (isHotbar && slotNum != pairingNum) { LockedSlot[] lockedSlots = getDataForProfile(); if (lockedSlots != null) { if (lockedSlots[slotNum] == null) { lockedSlots[slotNum] = new LockedSlot(); } if (!lockedSlots[slotNum].locked) { if (lockedSlots[pairingNum] == null) { lockedSlots[pairingNum] = new LockedSlot(); } lockedSlots[pairingNum].boundTo = slotNum; lockedSlots[pairingNum].locked = false; lockedSlots[slotNum].boundTo = pairingNum; } } } } } else { int pairingNum = pairingSlot.getSlotIndex(); LockedSlot[] lockedSlots = getDataForProfile(); if (lockedSlots != null && lockedSlots[pairingNum] != null) { if (lockedSlots[pairingNum].boundTo >= 0) { lockedSlots[lockedSlots[pairingNum].boundTo] = null; } lockedSlots[pairingNum] = null; } } } } public void toggleLock(int lockIndex) { if (lockIndex == 8) return; LockedSlot[] lockedSlots = getDataForProfile(); if (lockedSlots != null) { if (lockedSlots[lockIndex] == null) { lockedSlots[lockIndex] = new LockedSlot(); } lockedSlots[lockIndex].locked = !lockedSlots[lockIndex].locked; lockedSlots[lockIndex].boundTo = -1; if (NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSound) { float vol = NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockSoundVol / 100f; if (vol > 0) { if (vol > 1) vol = 1; final float volF = vol; final boolean locked = lockedSlots[lockIndex].locked; ISound sound = new PositionedSound(new ResourceLocation("random.orb")) {{ volume = volF; pitch = locked ? 0.943f : 0.1f; repeat = false; repeatDelay = 0; attenuationType = ISound.AttenuationType.NONE; }}; float oldLevel = Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.PLAYERS); Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, 1); Minecraft.getMinecraft().getSoundHandler().playSound(sound); Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, oldLevel); } } if (lockIndex < 9 && lockedSlots[lockIndex].locked) { for (int i = 9; i <= 39; i++) { if (lockedSlots[i] != null && lockedSlots[i].boundTo == lockIndex) { lockedSlots[i].boundTo = -1; } } } } } @SubscribeEvent(priority = EventPriority.LOW) public void drawScreenEvent(GuiScreenEvent.DrawScreenEvent.Post event) { if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && !event.isCanceled() && pairingSlot != null && lockKeyHeld) { LockedSlot[] lockedSlots = getDataForProfile(); LockedSlot lockedSlot = getLockedSlot(lockedSlots, pairingSlot.getSlotIndex()); if (lockedSlot.boundTo >= 0 && lockedSlot.boundTo < 8) { return; } if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } AccessorGuiContainer container = (AccessorGuiContainer) Minecraft.getMinecraft().currentScreen; int x1 = container.getGuiLeft() + pairingSlot.xDisplayPosition + 8; int y1 = container.getGuiTop() + pairingSlot.yDisplayPosition + 8; int x2 = event.mouseX; int y2 = event.mouseY; if (x2 > x1 - 8 && x2 < x1 + 8 && y2 > y1 - 8 && y2 < y1 + 8) { return; } drawLinkArrow(x1, y1, x2, y2); setTopHalfBarrier = true; } else { setTopHalfBarrier = false; } } private void drawLinkArrow(int x1, int y1, int x2, int y2) { GlStateManager.color(0x33 / 255f, 0xee / 255f, 0xdd / 255f, 1f); GlStateManager.disableLighting(); RenderHelper.disableStandardItemLighting(); GlStateManager.disableTexture2D(); GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); GlStateManager.translate(0, 0, 500); drawLine(x1, y1, x2, y2); GlStateManager.translate(0, 0, -500); GlStateManager.enableTexture2D(); } private void drawLine(int x1, int y1, int x2, int y2) { Vector2f vec = new Vector2f(x2 - x1, y2 - y1); vec.normalise(vec); Vector2f side = new Vector2f(vec.y, -vec.x); GL11.glLineWidth(1f); GL11.glEnable(GL11.GL_LINE_SMOOTH); Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); int lines = 6; for (int i = 0; i < lines; i++) { worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); worldrenderer.pos(x1 - side.x + side.x * i / lines, y1 - side.y + side.y * i / lines, 0.0D).endVertex(); worldrenderer.pos(x2 - side.x + side.x * i / lines, y2 - side.y + side.y * i / lines, 0.0D).endVertex(); tessellator.draw(); } } @SubscribeEvent public void onWindowClick(SlotClickEvent slotClickEvent) { LockedSlot locked = getLockedSlot(slotClickEvent.slot); if (locked == null) { return; } if (locked.locked || (slotClickEvent.clickType == 2 && SlotLocking.getInstance().isSlotIndexLocked(slotClickEvent.clickedButton))) { slotClickEvent.setCanceled(true); return; } if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && slotClickEvent.clickType == 1 && locked.boundTo != -1) { Slot boundSlot = slotClickEvent.guiContainer.inventorySlots.getSlotFromInventory( Minecraft.getMinecraft().thePlayer.inventory, locked.boundTo ); if (boundSlot == null) { return; } LockedSlot boundLocked = getLockedSlot(boundSlot); if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen; int size = container.inventorySlots.inventorySlots.size(); int from, to; int id = slotClickEvent.slot.getSlotIndex(); int idChest = id + (size - 45); // adjust the id of the clicked slot to align with the current inventory's number of slots if (idChest >= 9 && 0 <= locked.boundTo && locked.boundTo < 8 && !boundLocked.locked) { from = idChest; to = locked.boundTo; if (boundLocked == DEFAULT_LOCKED_SLOT) { LockedSlot[] lockedSlots = getDataForProfile(); lockedSlots[locked.boundTo] = new LockedSlot(); lockedSlots[locked.boundTo].boundTo = idChest; } else { boundLocked.boundTo = id; } } else if (0 <= id && id < 8 && locked.boundTo >= 9 && locked.boundTo <= 39) { if (boundLocked.locked || boundLocked.boundTo != id) { locked.boundTo = -1; return; } else { from = boundSlot.slotNumber; to = id; } } else { return; } if (from == 39) from = 5; if (from == 38) from = 6; if (from == 37) from = 7; if (from == 36) from = 8; Minecraft.getMinecraft().playerController.windowClick( slotClickEvent.guiContainer.inventorySlots.windowId, from, to, 2, Minecraft.getMinecraft().thePlayer ); slotClickEvent.setCanceled(true); } else if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && locked.boundTo != -1 && NotEnoughUpdates.INSTANCE.config.slotLocking.bindingAlsoLocks) { slotClickEvent.setCanceled(true); } } public void drawSlot(Slot slot) { LockedSlot locked = getLockedSlot(slot); if (locked != null) { if (locked.locked) { GlStateManager.translate(0, 0, 400); Minecraft.getMinecraft().getTextureManager().bindTexture(LOCK); GlStateManager.color(1, 1, 1, 0.5f); GlStateManager.depthMask(false); RenderUtils.drawTexturedRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0, 1, 0, 1, GL11.GL_NEAREST); GlStateManager.depthMask(true); GlStateManager.enableBlend(); GlStateManager.translate(0, 0, -400); } else if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && slot.canBeHovered() && locked.boundTo >= 0 && locked.boundTo <= 39) { if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen; final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); final int scaledWidth = scaledresolution.getScaledWidth(); final int scaledHeight = scaledresolution.getScaledHeight(); int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; Slot boundSlot = container.inventorySlots.getSlotFromInventory( Minecraft.getMinecraft().thePlayer.inventory, locked.boundTo ); if (boundSlot == null) { return; } boolean hoverOverSlot = ((AccessorGuiContainer) container).doIsMouseOverSlot(slot, mouseX, mouseY); if (hoverOverSlot || slot.getSlotIndex() >= 9) { Minecraft.getMinecraft().getTextureManager().bindTexture(BOUND); GlStateManager.color(1, 1, 1, 0.7f); GlStateManager.depthMask(false); RenderUtils.drawTexturedRect( slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0, 1, 0, 1, GL11.GL_NEAREST ); GlStateManager.depthMask(true); GlStateManager.enableBlend(); //Rerender Text over Top if (slot.getStack() != null) { Minecraft.getMinecraft().getRenderItem().renderItemOverlayIntoGUI( Minecraft.getMinecraft().fontRendererObj, slot.getStack(), slot.xDisplayPosition, slot.yDisplayPosition, null ); } } else if (pairingSlot != null && lockKeyHeld && slot.getSlotIndex() < 8) { int x1 = ((AccessorGuiContainer) container).getGuiLeft() + pairingSlot.xDisplayPosition; int y1 = ((AccessorGuiContainer) container).getGuiTop() + pairingSlot.yDisplayPosition; if (mouseX <= x1 || mouseX >= x1 + 16 || mouseY <= y1 || mouseY >= y1 + 16) { Gui.drawRect( slot.xDisplayPosition, slot.yDisplayPosition, slot.xDisplayPosition + 16, slot.yDisplayPosition + 16, 0x80ffffff ); } } if (hoverOverSlot) { LockedSlot boundLocked = getLockedSlot(boundSlot); if (boundLocked == null || boundLocked.locked || (boundSlot.getSlotIndex() >= 9 && boundLocked.boundTo != slot.getSlotIndex())) { locked.boundTo = -1; return; } Minecraft.getMinecraft().getTextureManager().bindTexture(BOUND); GlStateManager.color(1, 1, 1, 0.7f); GlStateManager.depthMask(false); RenderUtils.drawTexturedRect( boundSlot.xDisplayPosition, boundSlot.yDisplayPosition, 16, 16, 0, 1, 0, 1, GL11.GL_NEAREST ); GlStateManager.depthMask(true); GlStateManager.enableBlend(); //Rerender Text over Top if (boundSlot.getStack() != null) { Minecraft.getMinecraft().getRenderItem().renderItemOverlayIntoGUI( Minecraft.getMinecraft().fontRendererObj, boundSlot.getStack(), boundSlot.xDisplayPosition, boundSlot.yDisplayPosition, null ); } int maxIter = 100; float x1 = slot.xDisplayPosition + 8; float y1 = slot.yDisplayPosition + 8; float x2 = boundSlot.xDisplayPosition + 8; float y2 = boundSlot.yDisplayPosition + 8; Vector2f vec = new Vector2f(x2 - x1, y2 - y1); vec.normalise(vec); while (x1 > slot.xDisplayPosition && x1 < slot.xDisplayPosition + 16 && y1 > slot.yDisplayPosition && y1 < slot.yDisplayPosition + 16) { if (maxIter-- < 50) break; x1 += vec.x; y1 += vec.y; } while (x2 > boundSlot.xDisplayPosition && x2 < boundSlot.xDisplayPosition + 16 && y2 > boundSlot.yDisplayPosition && y2 < boundSlot.yDisplayPosition + 16) { if (maxIter-- < 0) break; x2 -= vec.x; y2 -= vec.y; } GlStateManager.translate(0, 0, 200); drawLinkArrow((int) x1, (int) y1, (int) x2, (int) y2); GlStateManager.translate(0, 0, -200); } } else if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && slot.getSlotIndex() < 8 && pairingSlot != null && lockKeyHeld) { if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) { return; } GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen; final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); final int scaledWidth = scaledresolution.getScaledWidth(); final int scaledHeight = scaledresolution.getScaledHeight(); int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; int x1 = ((AccessorGuiContainer) container).getGuiLeft() + pairingSlot.xDisplayPosition; int y1 = ((AccessorGuiContainer) container).getGuiTop() + pairingSlot.yDisplayPosition; if (mouseX <= x1 || mouseX >= x1 + 16 || mouseY <= y1 || mouseY >= y1 + 16) { Gui.drawRect( slot.xDisplayPosition, slot.yDisplayPosition, slot.xDisplayPosition + 16, slot.yDisplayPosition + 16, 0x80ffffff ); } } } } public LockedSlot getLockedSlot(Slot slot) { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || !NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking) return null; if (slot == null) { return null; } if (slot.inventory != Minecraft.getMinecraft().thePlayer.inventory) { return null; } int index = slot.getSlotIndex(); if (index < 0 || index > 39) { return null; } return getLockedSlotIndex(index); } public LockedSlot getLockedSlotIndex(int index) { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || !NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking) { return null; } LockedSlot[] lockedSlots = getDataForProfile(); if (lockedSlots == null) { return null; } return getLockedSlot(lockedSlots, index); } public boolean isSlotLocked(Slot slot) { LockedSlot locked = getLockedSlot(slot); return locked != null && (locked.locked || (NotEnoughUpdates.INSTANCE.config.slotLocking.bindingAlsoLocks && locked.boundTo != -1)); } public boolean isSlotIndexLocked(int index) { LockedSlot locked = getLockedSlotIndex(index); return locked != null && (locked.locked || (NotEnoughUpdates.INSTANCE.config.slotLocking.bindingAlsoLocks && locked.boundTo != -1)); } boolean setTopHalfBarrier = false; private boolean shouldShowBarrier(int slotNumber, IInventory inventory) { if (!(inventory instanceof InventoryPlayer)) return false; if (slotNumber < 9) return false; if (pairingSlot != null && (slotNumber == pairingSlot.slotNumber || isArmourSlot( slotNumber, pairingSlot.slotNumber ))) return false; if (!setTopHalfBarrier) return false; return true; } @SubscribeEvent(priority = EventPriority.LOW) public void afterRenderInventory(GuiScreenEvent.DrawScreenEvent.Post event) { if (!(event.gui instanceof GuiContainer)) return; var gui = (GuiContainer) event.gui; var slot = getFocusedSlot(gui); if (slot == null || !shouldShowBarrier(slot.getSlotIndex(), slot.inventory)) return; final var scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); final int scaledWidth = scaledresolution.getScaledWidth(); final int scaledHeight = scaledresolution.getScaledHeight(); int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; Utils.drawHoveringText( Arrays.asList( "§cYou cannot bind slots to anything except the hotbar.", "§cBinding to a normal inventory slot would require cheats.", "§cAnd you are not a cheater, are you?", "§cWe certainly hope you are not."), mouseX, mouseY, scaledWidth, scaledHeight, -1 ); } @SubscribeEvent public void barrierInventory(ReplaceItemEvent event) { if (!shouldShowBarrier(event.getSlotNumber(), event.getInventory())) return; ItemStack stack = new ItemStack(Blocks.barrier); ItemUtils.getOrCreateTag(stack).setBoolean( "NEUHIDETOOLIP", true ); event.replaceWith(stack); } boolean isArmourSlot(int eventSlotNumber, int pairingSlotNumber) { if (eventSlotNumber == 39 && pairingSlotNumber == 5) return true; if (eventSlotNumber == 38 && pairingSlotNumber == 6) return true; if (eventSlotNumber == 37 && pairingSlotNumber == 7) return true; if (eventSlotNumber == 36 && pairingSlotNumber == 8) return true; return false; } public void resetSlotLocking() { String profileName = SBInfo.getInstance().currentProfile; if (profileName == null) profileName = "generic"; SlotLockProfile slotLockProfile = config.profileData.get(profileName); if (slotLockProfile != null) { slotLockProfile.slotLockData[0] = new SlotLockData(); } } }