package net.minecraft.client.gui.screens.inventory; import com.google.common.collect.Sets; import com.mojang.blaze3d.platform.InputConstants; import java.util.ArrayList; import java.util.List; import java.util.Set; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.ChatFormatting; import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.BundleMouseActions; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.ItemSlotMouseAction; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public abstract class AbstractContainerScreen extends Screen implements MenuAccess { /** * The location of the inventory background texture */ public static final ResourceLocation INVENTORY_LOCATION = ResourceLocation.withDefaultNamespace("textures/gui/container/inventory.png"); private static final ResourceLocation SLOT_HIGHLIGHT_BACK_SPRITE = ResourceLocation.withDefaultNamespace("container/slot_highlight_back"); private static final ResourceLocation SLOT_HIGHLIGHT_FRONT_SPRITE = ResourceLocation.withDefaultNamespace("container/slot_highlight_front"); protected static final int BACKGROUND_TEXTURE_WIDTH = 256; protected static final int BACKGROUND_TEXTURE_HEIGHT = 256; private static final float SNAPBACK_SPEED = 100.0F; private static final int QUICKDROP_DELAY = 500; public static final int SLOT_ITEM_BLIT_OFFSET = 100; private static final int HOVER_ITEM_BLIT_OFFSET = 200; /** * The X size of the inventory window in pixels. */ protected int imageWidth = 176; /** * The Y size of the inventory window in pixels. */ protected int imageHeight = 166; protected int titleLabelX; protected int titleLabelY; protected int inventoryLabelX; protected int inventoryLabelY; private final List itemSlotMouseActions; /** * A list of the players inventory slots */ protected final T menu; protected final Component playerInventoryTitle; /** * Holds the slot currently hovered */ @Nullable protected Slot hoveredSlot; /** * Used when touchscreen is enabled */ @Nullable private Slot clickedSlot; @Nullable private Slot snapbackEnd; @Nullable private Slot quickdropSlot; @Nullable private Slot lastClickSlot; /** * Starting X position for the Gui. Inconsistent use for Gui backgrounds. */ protected int leftPos; /** * Starting Y position for the Gui. Inconsistent use for Gui backgrounds. */ protected int topPos; /** * Used when touchscreen is enabled. */ private boolean isSplittingStack; /** * Used when touchscreen is enabled */ private ItemStack draggingItem = ItemStack.EMPTY; private int snapbackStartX; private int snapbackStartY; private long snapbackTime; /** * Used when touchscreen is enabled */ private ItemStack snapbackItem = ItemStack.EMPTY; private long quickdropTime; protected final Set quickCraftSlots = Sets.newHashSet(); protected boolean isQuickCrafting; private int quickCraftingType; private int quickCraftingButton; private boolean skipNextRelease; private int quickCraftingRemainder; private long lastClickTime; private int lastClickButton; private boolean doubleclick; private ItemStack lastQuickMoved = ItemStack.EMPTY; public AbstractContainerScreen(T menu, Inventory playerInventory, Component title) { super(title); this.menu = menu; this.playerInventoryTitle = playerInventory.getDisplayName(); this.skipNextRelease = true; this.titleLabelX = 8; this.titleLabelY = 6; this.inventoryLabelX = 8; this.inventoryLabelY = this.imageHeight - 94; this.itemSlotMouseActions = new ArrayList(); } @Override protected void init() { this.leftPos = (this.width - this.imageWidth) / 2; this.topPos = (this.height - this.imageHeight) / 2; this.itemSlotMouseActions.clear(); this.addItemSlotMouseAction(new BundleMouseActions(this.minecraft)); } protected void addItemSlotMouseAction(ItemSlotMouseAction itemSlotMouseAction) { this.itemSlotMouseActions.add(itemSlotMouseAction); } @Override public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { int i = this.leftPos; int j = this.topPos; super.render(guiGraphics, mouseX, mouseY, partialTick); guiGraphics.pose().pushPose(); guiGraphics.pose().translate((float)i, (float)j, 0.0F); Slot slot = this.hoveredSlot; this.hoveredSlot = this.getHoveredSlot(mouseX, mouseY); this.renderSlotHighlightBack(guiGraphics); this.renderSlots(guiGraphics); this.renderSlotHighlightFront(guiGraphics); if (slot != null && slot != this.hoveredSlot) { this.onStopHovering(slot); } this.renderLabels(guiGraphics, mouseX, mouseY); ItemStack itemStack = this.draggingItem.isEmpty() ? this.menu.getCarried() : this.draggingItem; if (!itemStack.isEmpty()) { int k = 8; int l = this.draggingItem.isEmpty() ? 8 : 16; String string = null; if (!this.draggingItem.isEmpty() && this.isSplittingStack) { itemStack = itemStack.copyWithCount(Mth.ceil(itemStack.getCount() / 2.0F)); } else if (this.isQuickCrafting && this.quickCraftSlots.size() > 1) { itemStack = itemStack.copyWithCount(this.quickCraftingRemainder); if (itemStack.isEmpty()) { string = ChatFormatting.YELLOW + "0"; } } this.renderFloatingItem(guiGraphics, itemStack, mouseX - i - 8, mouseY - j - l, string); } if (!this.snapbackItem.isEmpty()) { float f = (float)(Util.getMillis() - this.snapbackTime) / 100.0F; if (f >= 1.0F) { f = 1.0F; this.snapbackItem = ItemStack.EMPTY; } int l = this.snapbackEnd.x - this.snapbackStartX; int m = this.snapbackEnd.y - this.snapbackStartY; int n = this.snapbackStartX + (int)(l * f); int o = this.snapbackStartY + (int)(m * f); this.renderFloatingItem(guiGraphics, this.snapbackItem, n, o, null); } guiGraphics.pose().popPose(); } protected void renderSlots(GuiGraphics guiGraphics) { for (Slot slot : this.menu.slots) { if (slot.isActive()) { this.renderSlot(guiGraphics, slot); } } } @Override public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { this.renderTransparentBackground(guiGraphics); this.renderBg(guiGraphics, partialTick, mouseX, mouseY); } @Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) { if (this.hoveredSlot != null && this.hoveredSlot.hasItem()) { for (ItemSlotMouseAction itemSlotMouseAction : this.itemSlotMouseActions) { if (itemSlotMouseAction.matches(this.hoveredSlot) && itemSlotMouseAction.onMouseScrolled(scrollX, scrollY, this.hoveredSlot.index, this.hoveredSlot.getItem())) { return true; } } } return false; } private void renderSlotHighlightBack(GuiGraphics guiGraphics) { if (this.hoveredSlot != null && this.hoveredSlot.isHighlightable()) { guiGraphics.blitSprite(RenderType::guiTextured, SLOT_HIGHLIGHT_BACK_SPRITE, this.hoveredSlot.x - 4, this.hoveredSlot.y - 4, 24, 24); } } private void renderSlotHighlightFront(GuiGraphics guiGraphics) { if (this.hoveredSlot != null && this.hoveredSlot.isHighlightable()) { guiGraphics.blitSprite(RenderType::guiTexturedOverlay, SLOT_HIGHLIGHT_FRONT_SPRITE, this.hoveredSlot.x - 4, this.hoveredSlot.y - 4, 24, 24); } } protected void renderTooltip(GuiGraphics guiGraphics, int x, int y) { if (this.hoveredSlot != null && this.hoveredSlot.hasItem()) { ItemStack itemStack = this.hoveredSlot.getItem(); if (this.menu.getCarried().isEmpty() || this.showTooltipWithItemInHand(itemStack)) { guiGraphics.renderTooltip( this.font, this.getTooltipFromContainerItem(itemStack), itemStack.getTooltipImage(), x, y, itemStack.get(DataComponents.TOOLTIP_STYLE) ); } } } private boolean showTooltipWithItemInHand(ItemStack stack) { return (Boolean)stack.getTooltipImage().map(ClientTooltipComponent::create).map(ClientTooltipComponent::showTooltipWithItemInHand).orElse(false); } protected List getTooltipFromContainerItem(ItemStack stack) { return getTooltipFromItem(this.minecraft, stack); } private void renderFloatingItem(GuiGraphics guiGraphics, ItemStack stack, int x, int y, @Nullable String text) { guiGraphics.pose().pushPose(); guiGraphics.pose().translate(0.0F, 0.0F, 232.0F); guiGraphics.renderItem(stack, x, y); guiGraphics.renderItemDecorations(this.font, stack, x, y - (this.draggingItem.isEmpty() ? 0 : 8), text); guiGraphics.pose().popPose(); } protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) { guiGraphics.drawString(this.font, this.title, this.titleLabelX, this.titleLabelY, 4210752, false); guiGraphics.drawString(this.font, this.playerInventoryTitle, this.inventoryLabelX, this.inventoryLabelY, 4210752, false); } protected abstract void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY); protected void renderSlot(GuiGraphics guiGraphics, Slot slot) { int i = slot.x; int j = slot.y; ItemStack itemStack = slot.getItem(); boolean bl = false; boolean bl2 = slot == this.clickedSlot && !this.draggingItem.isEmpty() && !this.isSplittingStack; ItemStack itemStack2 = this.menu.getCarried(); String string = null; if (slot == this.clickedSlot && !this.draggingItem.isEmpty() && this.isSplittingStack && !itemStack.isEmpty()) { itemStack = itemStack.copyWithCount(itemStack.getCount() / 2); } else if (this.isQuickCrafting && this.quickCraftSlots.contains(slot) && !itemStack2.isEmpty()) { if (this.quickCraftSlots.size() == 1) { return; } if (AbstractContainerMenu.canItemQuickReplace(slot, itemStack2, true) && this.menu.canDragTo(slot)) { bl = true; int k = Math.min(itemStack2.getMaxStackSize(), slot.getMaxStackSize(itemStack2)); int l = slot.getItem().isEmpty() ? 0 : slot.getItem().getCount(); int m = AbstractContainerMenu.getQuickCraftPlaceCount(this.quickCraftSlots, this.quickCraftingType, itemStack2) + l; if (m > k) { m = k; string = ChatFormatting.YELLOW.toString() + k; } itemStack = itemStack2.copyWithCount(m); } else { this.quickCraftSlots.remove(slot); this.recalculateQuickCraftRemaining(); } } guiGraphics.pose().pushPose(); guiGraphics.pose().translate(0.0F, 0.0F, 100.0F); if (itemStack.isEmpty() && slot.isActive()) { ResourceLocation resourceLocation = slot.getNoItemIcon(); if (resourceLocation != null) { guiGraphics.blitSprite(RenderType::guiTextured, resourceLocation, i, j, 16, 16); bl2 = true; } } if (!bl2) { if (bl) { guiGraphics.fill(i, j, i + 16, j + 16, -2130706433); } int k = slot.x + slot.y * this.imageWidth; if (slot.isFake()) { guiGraphics.renderFakeItem(itemStack, i, j, k); } else { guiGraphics.renderItem(itemStack, i, j, k); } guiGraphics.renderItemDecorations(this.font, itemStack, i, j, string); } guiGraphics.pose().popPose(); } private void recalculateQuickCraftRemaining() { ItemStack itemStack = this.menu.getCarried(); if (!itemStack.isEmpty() && this.isQuickCrafting) { if (this.quickCraftingType == 2) { this.quickCraftingRemainder = itemStack.getMaxStackSize(); } else { this.quickCraftingRemainder = itemStack.getCount(); for (Slot slot : this.quickCraftSlots) { ItemStack itemStack2 = slot.getItem(); int i = itemStack2.isEmpty() ? 0 : itemStack2.getCount(); int j = Math.min(itemStack.getMaxStackSize(), slot.getMaxStackSize(itemStack)); int k = Math.min(AbstractContainerMenu.getQuickCraftPlaceCount(this.quickCraftSlots, this.quickCraftingType, itemStack) + i, j); this.quickCraftingRemainder -= k - i; } } } } @Nullable private Slot getHoveredSlot(double mouseX, double mouseY) { for (Slot slot : this.menu.slots) { if (slot.isActive() && this.isHovering(slot, mouseX, mouseY)) { return slot; } } return null; } @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { if (super.mouseClicked(mouseX, mouseY, button)) { return true; } else { boolean bl = this.minecraft.options.keyPickItem.matchesMouse(button) && this.minecraft.player.hasInfiniteMaterials(); Slot slot = this.getHoveredSlot(mouseX, mouseY); long l = Util.getMillis(); this.doubleclick = this.lastClickSlot == slot && l - this.lastClickTime < 250L && this.lastClickButton == button; this.skipNextRelease = false; if (button != 0 && button != 1 && !bl) { this.checkHotbarMouseClicked(button); } else { int i = this.leftPos; int j = this.topPos; boolean bl2 = this.hasClickedOutside(mouseX, mouseY, i, j, button); int k = -1; if (slot != null) { k = slot.index; } if (bl2) { k = -999; } if (this.minecraft.options.touchscreen().get() && bl2 && this.menu.getCarried().isEmpty()) { this.onClose(); return true; } if (k != -1) { if (this.minecraft.options.touchscreen().get()) { if (slot != null && slot.hasItem()) { this.clickedSlot = slot; this.draggingItem = ItemStack.EMPTY; this.isSplittingStack = button == 1; } else { this.clickedSlot = null; } } else if (!this.isQuickCrafting) { if (this.menu.getCarried().isEmpty()) { if (bl) { this.slotClicked(slot, k, button, ClickType.CLONE); } else { boolean bl3 = k != -999 && ( InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340) || InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344) ); ClickType clickType = ClickType.PICKUP; if (bl3) { this.lastQuickMoved = slot != null && slot.hasItem() ? slot.getItem().copy() : ItemStack.EMPTY; clickType = ClickType.QUICK_MOVE; } else if (k == -999) { clickType = ClickType.THROW; } this.slotClicked(slot, k, button, clickType); } this.skipNextRelease = true; } else { this.isQuickCrafting = true; this.quickCraftingButton = button; this.quickCraftSlots.clear(); if (button == 0) { this.quickCraftingType = 0; } else if (button == 1) { this.quickCraftingType = 1; } else if (bl) { this.quickCraftingType = 2; } } } } } this.lastClickSlot = slot; this.lastClickTime = l; this.lastClickButton = button; return true; } } private void checkHotbarMouseClicked(int keyCode) { if (this.hoveredSlot != null && this.menu.getCarried().isEmpty()) { if (this.minecraft.options.keySwapOffhand.matchesMouse(keyCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 40, ClickType.SWAP); return; } for (int i = 0; i < 9; i++) { if (this.minecraft.options.keyHotbarSlots[i].matchesMouse(keyCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ClickType.SWAP); } } } } protected boolean hasClickedOutside(double mouseX, double mouseY, int guiLeft, int guiTop, int mouseButton) { return mouseX < guiLeft || mouseY < guiTop || mouseX >= guiLeft + this.imageWidth || mouseY >= guiTop + this.imageHeight; } @Override public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { Slot slot = this.getHoveredSlot(mouseX, mouseY); ItemStack itemStack = this.menu.getCarried(); if (this.clickedSlot != null && this.minecraft.options.touchscreen().get()) { if (button == 0 || button == 1) { if (this.draggingItem.isEmpty()) { if (slot != this.clickedSlot && !this.clickedSlot.getItem().isEmpty()) { this.draggingItem = this.clickedSlot.getItem().copy(); } } else if (this.draggingItem.getCount() > 1 && slot != null && AbstractContainerMenu.canItemQuickReplace(slot, this.draggingItem, false)) { long l = Util.getMillis(); if (this.quickdropSlot == slot) { if (l - this.quickdropTime > 500L) { this.slotClicked(this.clickedSlot, this.clickedSlot.index, 0, ClickType.PICKUP); this.slotClicked(slot, slot.index, 1, ClickType.PICKUP); this.slotClicked(this.clickedSlot, this.clickedSlot.index, 0, ClickType.PICKUP); this.quickdropTime = l + 750L; this.draggingItem.shrink(1); } } else { this.quickdropSlot = slot; this.quickdropTime = l; } } } } else if (this.isQuickCrafting && slot != null && !itemStack.isEmpty() && (itemStack.getCount() > this.quickCraftSlots.size() || this.quickCraftingType == 2) && AbstractContainerMenu.canItemQuickReplace(slot, itemStack, true) && slot.mayPlace(itemStack) && this.menu.canDragTo(slot)) { this.quickCraftSlots.add(slot); this.recalculateQuickCraftRemaining(); } return true; } @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { Slot slot = this.getHoveredSlot(mouseX, mouseY); int i = this.leftPos; int j = this.topPos; boolean bl = this.hasClickedOutside(mouseX, mouseY, i, j, button); int k = -1; if (slot != null) { k = slot.index; } if (bl) { k = -999; } if (this.doubleclick && slot != null && button == 0 && this.menu.canTakeItemForPickAll(ItemStack.EMPTY, slot)) { if (hasShiftDown()) { if (!this.lastQuickMoved.isEmpty()) { for (Slot slot2 : this.menu.slots) { if (slot2 != null && slot2.mayPickup(this.minecraft.player) && slot2.hasItem() && slot2.container == slot.container && AbstractContainerMenu.canItemQuickReplace(slot2, this.lastQuickMoved, true)) { this.slotClicked(slot2, slot2.index, button, ClickType.QUICK_MOVE); } } } } else { this.slotClicked(slot, k, button, ClickType.PICKUP_ALL); } this.doubleclick = false; this.lastClickTime = 0L; } else { if (this.isQuickCrafting && this.quickCraftingButton != button) { this.isQuickCrafting = false; this.quickCraftSlots.clear(); this.skipNextRelease = true; return true; } if (this.skipNextRelease) { this.skipNextRelease = false; return true; } if (this.clickedSlot != null && this.minecraft.options.touchscreen().get()) { if (button == 0 || button == 1) { if (this.draggingItem.isEmpty() && slot != this.clickedSlot) { this.draggingItem = this.clickedSlot.getItem(); } boolean bl2 = AbstractContainerMenu.canItemQuickReplace(slot, this.draggingItem, false); if (k != -1 && !this.draggingItem.isEmpty() && bl2) { this.slotClicked(this.clickedSlot, this.clickedSlot.index, button, ClickType.PICKUP); this.slotClicked(slot, k, 0, ClickType.PICKUP); if (this.menu.getCarried().isEmpty()) { this.snapbackItem = ItemStack.EMPTY; } else { this.slotClicked(this.clickedSlot, this.clickedSlot.index, button, ClickType.PICKUP); this.snapbackStartX = Mth.floor(mouseX - i); this.snapbackStartY = Mth.floor(mouseY - j); this.snapbackEnd = this.clickedSlot; this.snapbackItem = this.draggingItem; this.snapbackTime = Util.getMillis(); } } else if (!this.draggingItem.isEmpty()) { this.snapbackStartX = Mth.floor(mouseX - i); this.snapbackStartY = Mth.floor(mouseY - j); this.snapbackEnd = this.clickedSlot; this.snapbackItem = this.draggingItem; this.snapbackTime = Util.getMillis(); } this.clearDraggingState(); } } else if (this.isQuickCrafting && !this.quickCraftSlots.isEmpty()) { this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(0, this.quickCraftingType), ClickType.QUICK_CRAFT); for (Slot slot2x : this.quickCraftSlots) { this.slotClicked(slot2x, slot2x.index, AbstractContainerMenu.getQuickcraftMask(1, this.quickCraftingType), ClickType.QUICK_CRAFT); } this.slotClicked(null, -999, AbstractContainerMenu.getQuickcraftMask(2, this.quickCraftingType), ClickType.QUICK_CRAFT); } else if (!this.menu.getCarried().isEmpty()) { if (this.minecraft.options.keyPickItem.matchesMouse(button)) { this.slotClicked(slot, k, button, ClickType.CLONE); } else { boolean bl2 = k != -999 && ( InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 340) || InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), 344) ); if (bl2) { this.lastQuickMoved = slot != null && slot.hasItem() ? slot.getItem().copy() : ItemStack.EMPTY; } this.slotClicked(slot, k, button, bl2 ? ClickType.QUICK_MOVE : ClickType.PICKUP); } } } if (this.menu.getCarried().isEmpty()) { this.lastClickTime = 0L; } this.isQuickCrafting = false; return true; } public void clearDraggingState() { this.draggingItem = ItemStack.EMPTY; this.clickedSlot = null; } private boolean isHovering(Slot slot, double mouseX, double mouseY) { return this.isHovering(slot.x, slot.y, 16, 16, mouseX, mouseY); } protected boolean isHovering(int x, int y, int width, int height, double mouseX, double mouseY) { int i = this.leftPos; int j = this.topPos; mouseX -= i; mouseY -= j; return mouseX >= x - 1 && mouseX < x + width + 1 && mouseY >= y - 1 && mouseY < y + height + 1; } private void onStopHovering(Slot slot) { if (slot.hasItem()) { for (ItemSlotMouseAction itemSlotMouseAction : this.itemSlotMouseActions) { if (itemSlotMouseAction.matches(slot)) { itemSlotMouseAction.onStopHovering(slot); } } } } /** * Called when the mouse is clicked over a slot or outside the gui. */ protected void slotClicked(Slot slot, int slotId, int mouseButton, ClickType type) { if (slot != null) { slotId = slot.index; } this.onMouseClickAction(slot, type); this.minecraft.gameMode.handleInventoryMouseClick(this.menu.containerId, slotId, mouseButton, type, this.minecraft.player); } void onMouseClickAction(@Nullable Slot slot, ClickType type) { if (slot != null && slot.hasItem()) { for (ItemSlotMouseAction itemSlotMouseAction : this.itemSlotMouseActions) { if (itemSlotMouseAction.matches(slot)) { itemSlotMouseAction.onSlotClicked(slot, type); } } } } protected void handleSlotStateChanged(int slotId, int containerId, boolean newState) { this.minecraft.gameMode.handleSlotStateChanged(slotId, containerId, newState); } @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (super.keyPressed(keyCode, scanCode, modifiers)) { return true; } else if (this.minecraft.options.keyInventory.matches(keyCode, scanCode)) { this.onClose(); return true; } else { this.checkHotbarKeyPressed(keyCode, scanCode); if (this.hoveredSlot != null && this.hoveredSlot.hasItem()) { if (this.minecraft.options.keyPickItem.matches(keyCode, scanCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 0, ClickType.CLONE); } else if (this.minecraft.options.keyDrop.matches(keyCode, scanCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, hasControlDown() ? 1 : 0, ClickType.THROW); } } return true; } } protected boolean checkHotbarKeyPressed(int keyCode, int scanCode) { if (this.menu.getCarried().isEmpty() && this.hoveredSlot != null) { if (this.minecraft.options.keySwapOffhand.matches(keyCode, scanCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, 40, ClickType.SWAP); return true; } for (int i = 0; i < 9; i++) { if (this.minecraft.options.keyHotbarSlots[i].matches(keyCode, scanCode)) { this.slotClicked(this.hoveredSlot, this.hoveredSlot.index, i, ClickType.SWAP); return true; } } } return false; } @Override public void removed() { if (this.minecraft.player != null) { this.menu.removed(this.minecraft.player); } } @Override public boolean isPauseScreen() { return false; } @Override public final void tick() { super.tick(); if (this.minecraft.player.isAlive() && !this.minecraft.player.isRemoved()) { this.containerTick(); } else { this.minecraft.player.closeContainer(); } } protected void containerTick() { } @Override public T getMenu() { return this.menu; } @Override public void onClose() { this.minecraft.player.closeContainer(); if (this.hoveredSlot != null) { this.onStopHovering(this.hoveredSlot); } super.onClose(); } }