diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/InternalAccessor.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/InternalAccessor.java index a70af0af..a612f41e 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/InternalAccessor.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/InternalAccessor.java @@ -5,9 +5,11 @@ import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.v1_21_R1.inventory.AnySilentContainer; import com.lishid.openinv.internal.v1_21_R1.inventory.OpenEnderChest; import com.lishid.openinv.internal.v1_21_R1.inventory.OpenInventory; import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; +import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import com.lishid.openinv.util.lang.LanguageManager; import net.minecraft.world.Container; import org.bukkit.configuration.ConfigurationSection; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/AnySilentContainer.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/AnySilentContainer.java similarity index 93% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/AnySilentContainer.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/AnySilentContainer.java index 637c6bc4..a7c0211c 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/AnySilentContainer.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/AnySilentContainer.java @@ -14,9 +14,10 @@ * along with this program. If not, see . */ -package com.lishid.openinv.internal.v1_21_R1; +package com.lishid.openinv.internal.v1_21_R1.inventory; import com.lishid.openinv.internal.IAnySilentContainer; +import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import com.lishid.openinv.util.ReflectionHelper; import com.lishid.openinv.util.lang.LanguageManager; import net.minecraft.core.BlockPos; @@ -74,18 +75,6 @@ public AnySilentContainer(@NotNull Logger logger, @NotNull LanguageManager lang) } } - public static @NotNull MenuType getContainers(int inventorySize) { - return switch (inventorySize) { - case 9 -> MenuType.GENERIC_9x1; - case 18 -> MenuType.GENERIC_9x2; - case 36 -> MenuType.GENERIC_9x4; - case 45 -> MenuType.GENERIC_9x5; - case 54 -> MenuType.GENERIC_9x6; - // Default to 27-slot inventory - default -> MenuType.GENERIC_9x3; - }; - } - @Override public boolean activateContainer( @NotNull final Player bukkitPlayer, @@ -114,7 +103,7 @@ public boolean activateContainer( PlayerEnderChestContainer enderChest = player.getEnderChestInventory(); enderChest.setActiveChest(enderChestTile); player.openMenu(new SimpleMenuProvider((containerCounter, playerInventory, ignored) -> { - MenuType containers = getContainers(enderChest.getContainerSize()); + MenuType containers = OpenContainerMenu.getContainers(enderChest.getContainerSize()); int rows = enderChest.getContainerSize() / 9; return new ChestMenu(containers, containerCounter, playerInventory, enderChest, rows); }, Component.translatable("container.enderchest"))); diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java deleted file mode 100644 index 48b57709..00000000 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; - -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.NotNull; - -import java.util.Optional; - -/** - * A fake slot used to fill spaces in the inventory that can't be interacted with. - */ -class ContainerSlotUninteractable implements ContainerSlot { - - @NotNull ServerPlayer holder; - - ContainerSlotUninteractable(@NotNull ServerPlayer holder) { - this.holder = holder; - } - - @Override - public void setHolder(@NotNull ServerPlayer holder) { - this.holder = holder; - } - - @Override - public ItemStack get() { - return ItemStack.EMPTY; - } - - @Override - public ItemStack remove() { - return ItemStack.EMPTY; - } - - @Override - public ItemStack removePartial(int amount) { - return ItemStack.EMPTY; - } - - @Override - public void set(ItemStack itemStack) { - this.holder.drop(itemStack, false); - } - - @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotUninteractable(container, index, x, y); - } - - @Override - public InventoryType.SlotType getSlotType() { - return InventoryType.SlotType.OUTSIDE; - } - - static class SlotUninteractable extends MenuSlotPlaceholder { - - SlotUninteractable(Container container, int index, int x, int y) { - super(container, index, x, y); - } - - @Override - ItemStack getOrDefault() { - return Placeholders.notSlot; - } - - @Override - public void onQuickCraft(ItemStack var0, ItemStack var1) {} - - @Override - public void onTake(Player var0, ItemStack var1) {} - - @Override - public boolean mayPlace(ItemStack var0) { - return false; - } - - @Override - public ItemStack getItem() { - return ItemStack.EMPTY; - } - - @Override - public boolean hasItem() { - return false; - } - - @Override - public void setByPlayer(ItemStack newStack) {} - - @Override - public void setByPlayer(ItemStack newStack, ItemStack oldStack) {} - - @Override - public void set(ItemStack var0) {} - - @Override - public void setChanged() {} - - @Override - public int getMaxStackSize() { - return 0; - } - - @Override - public int getMaxStackSize(ItemStack itemStack) { - return 0; - } - - @Override - public ItemStack remove(int amount) { - return ItemStack.EMPTY; - } - - @Override - public boolean mayPickup(Player var0) { - return false; - } - - @Override - public boolean isActive() { - return false; - } - - @Override - public Optional tryRemove(int var0, int var1, Player var2) { - return Optional.empty(); - } - - @Override - public ItemStack safeTake(int var0, int var1, Player var2) { - return ItemStack.EMPTY; - } - - @Override - public ItemStack safeInsert(ItemStack itemStack) { - return itemStack; - } - - @Override - public ItemStack safeInsert(ItemStack itemStack, int amount) { - return itemStack; - } - - @Override - public boolean allowModification(Player var0) { - return false; - } - - @Override - public int getContainerSlot() { - return this.slot; - } - - @Override - public boolean isHighlightable() { - return false; - } - - @Override - public boolean isFake() { - return true; - } - - } -} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenContainerMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenContainerMenu.java new file mode 100644 index 00000000..005f2ad2 --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenContainerMenu.java @@ -0,0 +1,306 @@ +package com.lishid.openinv.internal.v1_21_R1.inventory; + +import com.google.common.base.Suppliers; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.SlotPlaceholder; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.inventory.ContainerSynchronizer; +import net.minecraft.world.inventory.DataSlot; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +/** + * An extension of {@link AbstractContainerMenu} that supports {@link SlotPlaceholder placeholders}. + */ +public abstract class OpenContainerMenu extends AbstractContainerMenu { + + private @Nullable ContainerSynchronizer synchronizer; + private final List dataSlots = new ArrayList<>(); + private final IntList remoteDataSlots = new IntArrayList(); + private final List containerListeners = new ArrayList<>(); + private ItemStack remoteCarried = ItemStack.EMPTY; + private boolean suppressRemoteUpdates; + + protected OpenContainerMenu(@Nullable MenuType containers, int containerCounter) { + super(containers, containerCounter); + } + + static @NotNull MenuType getContainers(int inventorySize) { + return switch (inventorySize) { + case 9 -> MenuType.GENERIC_9x1; + case 18 -> MenuType.GENERIC_9x2; + case 36 -> MenuType.GENERIC_9x4; + case 45 -> MenuType.GENERIC_9x5; + case 54 -> MenuType.GENERIC_9x6; + // Default to 27-slot inventory + default -> MenuType.GENERIC_9x3; + }; + } + + /** + * Reimplementation of {@link AbstractContainerMenu#moveItemStackTo(ItemStack, int, int, boolean)} that ignores fake + * slots and respects {@link Slot#hasItem()}. + * + * @param itemStack the stack to quick-move + * @param rangeLow the start of the range of slots that can be moved to, inclusive + * @param rangeHigh the end of the range of slots that can be moved to, exclusive + * @param topDown whether to start at the top of the range or bottom + * @return whether the stack was modified as a result of being quick-moved + */ + @Override + protected boolean moveItemStackTo(ItemStack itemStack, int rangeLow, int rangeHigh, boolean topDown) { + boolean modified = false; + boolean stackable = itemStack.isStackable(); + Slot firstEmpty = null; + + for (int index = topDown ? rangeHigh - 1 : rangeLow; + !itemStack.isEmpty() && (topDown ? index >= rangeLow : index < rangeHigh); + index += topDown ? -1 : 1 + ) { + Slot slot = slots.get(index); + // If the slot cannot be added to, check the next slot. + if (slot.isFake() || !slot.mayPlace(itemStack)) { + continue; + } + + if (slot.hasItem()) { + // If the item isn't stackable, check the next slot. + if (!stackable) { + continue; + } + // Otherwise, add as many as we can from our stack to the slot. + modified = addToExistingStack(itemStack, slot); + } else { + // If this is the first empty slot, keep track of it for later use. + if (firstEmpty == null) { + firstEmpty = slot; + } + // If the item isn't stackable, we've located the slot we're adding it to, so we're done. + if (!stackable) { + break; + } + } + } + + // If the item hasn't been fully added yet, add as many as we can to the first open slot. + if (!itemStack.isEmpty() && firstEmpty != null) { + firstEmpty.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), firstEmpty.getMaxStackSize(itemStack)))); + firstEmpty.setChanged(); + modified = true; + } + + return modified; + } + + private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { + ItemStack existing = slot.getItem(); + + // If the items aren't the same, we can't add our item. + if (!ItemStack.isSameItemSameComponents(itemStack, existing)) { + return false; + } + + int total = existing.getCount() + itemStack.getCount(); + int max = slot.getMaxStackSize(existing); + + // If the existing item can accept the entirety of our item, we're done! + if (total <= max) { + itemStack.setCount(0); + existing.setCount(total); + slot.setChanged(); + return true; + } + + // Otherwise, add as many as we can. + itemStack.shrink(max - existing.getCount()); + existing.setCount(max); + slot.setChanged(); + return true; + } + + @Override + protected Slot addSlot(Slot slot) { + slot.index = this.slots.size(); + this.slots.add(slot); + this.lastSlots.add(ItemStack.EMPTY); + this.remoteSlots.add(ItemStack.EMPTY); + return slot; + } + + @Override + protected DataSlot addDataSlot(DataSlot dataSlot) { + this.dataSlots.add(dataSlot); + this.remoteDataSlots.add(0); + return dataSlot; + } + + @Override + protected void addDataSlots(ContainerData containerData) { + for (int i = 0; i < containerData.getCount(); i++) { + this.addDataSlot(DataSlot.forContainer(containerData, i)); + } + } + + @Override + public void addSlotListener(ContainerListener containerListener) { + if (!this.containerListeners.contains(containerListener)) { + this.containerListeners.add(containerListener); + this.broadcastChanges(); + } + } + + @Override + public void setSynchronizer(ContainerSynchronizer containerSynchronizer) { + this.synchronizer = containerSynchronizer; + this.sendAllDataToRemote(); + } + + @Override + public void sendAllDataToRemote() { + for (int index = 0; index < slots.size(); ++index) { + Slot slot = slots.get(index); + this.remoteSlots.set(index, (slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem()).copy()); + } + + remoteCarried = getCarried().copy(); + + for (int index = 0; index < this.dataSlots.size(); ++index) { + this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); + } + + if (this.synchronizer != null) { + this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); + } + } + + @Override + public void broadcastCarriedItem() { + this.remoteCarried = this.getCarried().copy(); + if (this.synchronizer != null) { + this.synchronizer.sendCarriedChange(this, this.remoteCarried); + } + } + + @Override + public void removeSlotListener(ContainerListener containerListener) { + this.containerListeners.remove(containerListener); + } + + @Override + public void broadcastChanges() { + for (int index = 0; index < this.slots.size(); ++index) { + Slot slot = this.slots.get(index); + ItemStack itemstack = slot instanceof SlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); + Supplier supplier = Suppliers.memoize(itemstack::copy); + this.triggerSlotListeners(index, itemstack, supplier); + this.synchronizeSlotToRemote(index, itemstack, supplier); + } + + this.synchronizeCarriedToRemote(); + + for (int index = 0; index < this.dataSlots.size(); ++index) { + DataSlot dataSlot = this.dataSlots.get(index); + int j = dataSlot.get(); + if (dataSlot.checkAndClearUpdateFlag()) { + this.updateDataSlotListeners(index, j); + } + + this.synchronizeDataSlotToRemote(index, j); + } + } + + @Override + public void broadcastFullState() { + for (int index = 0; index < this.slots.size(); ++index) { + ItemStack itemstack = this.slots.get(index).getItem(); + this.triggerSlotListeners(index, itemstack, itemstack::copy); + } + + for (int index = 0; index < this.dataSlots.size(); ++index) { + DataSlot containerproperty = this.dataSlots.get(index); + if (containerproperty.checkAndClearUpdateFlag()) { + this.updateDataSlotListeners(index, containerproperty.get()); + } + } + + this.sendAllDataToRemote(); + } + + private void updateDataSlotListeners(int i, int j) { + for (ContainerListener containerListener : this.containerListeners) { + containerListener.dataChanged(this, i, j); + } + } + + private void triggerSlotListeners(int index, ItemStack itemStack, Supplier supplier) { + ItemStack itemStack1 = this.lastSlots.get(index); + if (!ItemStack.matches(itemStack1, itemStack)) { + ItemStack itemStack2 = supplier.get(); + this.lastSlots.set(index, itemStack2); + + for (ContainerListener containerListener : this.containerListeners) { + containerListener.slotChanged(this, index, itemStack2); + } + } + } + + private void synchronizeSlotToRemote(int i, ItemStack itemStack, Supplier supplier) { + if (!this.suppressRemoteUpdates) { + ItemStack itemStack1 = this.remoteSlots.get(i); + if (!ItemStack.matches(itemStack1, itemStack)) { + ItemStack itemstack2 = supplier.get(); + this.remoteSlots.set(i, itemstack2); + if (this.synchronizer != null) { + this.synchronizer.sendSlotChange(this, i, itemstack2); + } + } + } + } + + private void synchronizeDataSlotToRemote(int index, int value) { + if (!this.suppressRemoteUpdates) { + int existing = this.remoteDataSlots.getInt(index); + if (existing != value) { + this.remoteDataSlots.set(index, value); + if (this.synchronizer != null) { + this.synchronizer.sendDataChange(this, index, value); + } + } + } + } + + private void synchronizeCarriedToRemote() { + if (!this.suppressRemoteUpdates && !ItemStack.matches(this.getCarried(), this.remoteCarried)) { + this.remoteCarried = this.getCarried().copy(); + if (this.synchronizer != null) { + this.synchronizer.sendCarriedChange(this, this.remoteCarried); + } + } + } + + @Override + public void setRemoteCarried(ItemStack itemstack) { + this.remoteCarried = itemstack.copy(); + } + + @Override + public void suppressRemoteUpdates() { + this.suppressRemoteUpdates = true; + } + + @Override + public void resumeRemoteUpdates() { + this.suppressRemoteUpdates = false; + } + +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChest.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChest.java index b9234690..55ca749c 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChest.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChest.java @@ -1,24 +1,7 @@ -/* - * Copyright (C) 2011-2023 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package com.lishid.openinv.internal.v1_21_R1.inventory; import com.lishid.openinv.internal.ISpecialEnderChest; -import com.lishid.openinv.internal.v1_21_R1.AnySilentContainer; -import com.lishid.openinv.internal.v1_21_R1.PlayerManager; +import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; @@ -29,13 +12,11 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.StackedContents; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.inventory.StackedContentsCompatible; import net.minecraft.world.item.ItemStack; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_21_R1.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory; -import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryView; import org.bukkit.entity.HumanEntity; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; @@ -200,20 +181,12 @@ public Component getDisplayName() { .append(Component.translatableWithFallback("openinv.container.enderchest.suffix", " - %s", owner.getName())); } - @Nullable @Override - public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { - int rows = (getContainerSize() % 9) + 1; - return new ChestMenu(AnySilentContainer.getContainers(getContainerSize()), i, inventory, this, rows) { - private CraftInventoryView view; - @Override - public CraftInventoryView getBukkitView() { - if (view == null) { - view = new CraftInventoryView(player.getBukkitEntity(), getBukkitInventory(), this); - } - return view; - } - }; + public @Nullable AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { + if (player instanceof ServerPlayer serverPlayer) { + return new OpenEnderChestMenu(this, serverPlayer, i); + } + return null; } } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChestMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChestMenu.java new file mode 100644 index 00000000..dd333d5d --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChestMenu.java @@ -0,0 +1,127 @@ +package com.lishid.openinv.internal.v1_21_R1.inventory; + +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.SlotViewOnly; +import com.lishid.openinv.util.Permissions; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventoryView; + +class OpenEnderChestMenu extends OpenContainerMenu { + + private final OpenEnderChest enderChest; + private final boolean viewOnly; + private final ServerPlayer viewer; + private final int topSize; + private CraftInventoryView view; + + OpenEnderChestMenu(OpenEnderChest enderChest, ServerPlayer viewer, int containerId) { + super(getMenuType(enderChest), containerId); + this.enderChest = enderChest; + this.viewer = viewer; + var bukkitViewer = viewer.getBukkitEntity(); + viewOnly = !(bukkitViewer.equals(enderChest.getPlayer()) + ? Permissions.ENDERCHEST_EDIT_SELF + : Permissions.ENDERCHEST_OPEN_OTHER) + .hasPermission(bukkitViewer); + int upperRows = (int) Math.ceil(enderChest.getContainerSize() / 9.0); + topSize = upperRows * 9; + + // View's upper inventory - our container + for (int row = 0; row < upperRows; ++row) { + for (int col = 0; col < 9; ++col) { + // x and y for client purposes, but hey, we're thorough here. + // Adapted from net.minecraft.world.inventory.ChestMenu + int x = 8 + col * 18; + int y = 18 + row * 18; + int index = row * 9 + col; + + // Guard against weird inventory sizes. + if (index >= enderChest.getContainerSize()) { + addSlot(new SlotViewOnly(enderChest, index, x, y)); + continue; + } + + addSlot(new Slot(enderChest, index, x, y)); + } + } + + // View's lower inventory - viewer inventory + int playerInvPad = (upperRows - 4) * 18; + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 9; ++col) { + int x = 8 + col * 18; + int y = playerInvPad + row * 18 + 103; + addSlot(new Slot(viewer.getInventory(), row * 9 + col + 9, x, y)); + } + } + // Hotbar + for (int col = 0; col < 9; ++col) { + int x = 8 + col * 18; + int y = playerInvPad + 161; + addSlot(new Slot(viewer.getInventory(), col, x, y)); + } + } + + private static MenuType getMenuType(OpenEnderChest enderChest) { + return OpenContainerMenu.getContainers(((int) Math.ceil(enderChest.getContainerSize() / 9.0)) * 9); + } + + @Override + public CraftInventoryView getBukkitView() { + if (view == null) { + view = new CraftInventoryView(viewer.getBukkitEntity(), enderChest.getBukkitInventory(), this); + } + return view; + } + + @Override + protected Slot addSlot(Slot slot) { + slot = super.addSlot(slot); + + // If view-only and slot is in upper inventory, wrap it. + if (viewOnly && slot.index < enderChest.getContainerSize()) { + slot = SlotViewOnly.wrap(slot); + slots.set(slot.index, slot); + } + + return slot; + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + // See ChestMenu + Slot slot = this.slots.get(index); + + if (slot.isFake() || !slot.hasItem()) { + return ItemStack.EMPTY; + } + + ItemStack itemStack = slot.getItem(); + ItemStack original = itemStack.copy(); + + if (index < topSize) { + if (!this.moveItemStackTo(itemStack, topSize, this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else if (!this.moveItemStackTo(itemStack, 0, topSize, false)) { + return ItemStack.EMPTY; + } + + if (itemStack.isEmpty()) { + slot.setByPlayer(ItemStack.EMPTY); + } else { + slot.setChanged(); + } + + return original; + } + + @Override + public boolean stillValid(Player entityhuman) { + return true; + } + +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java index 9d584eb5..3f6c907f 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java @@ -1,7 +1,17 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; import com.lishid.openinv.internal.ISpecialPlayerInventory; -import com.lishid.openinv.internal.v1_21_R1.PlayerManager; +import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.Content; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentCrafting; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentCraftingResult; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentCursor; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentDrop; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentEquipment; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentList; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentOffHand; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentViewOnly; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.SlotViewOnly; import net.minecraft.ChatFormatting; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; @@ -29,7 +39,7 @@ public class OpenInventory implements Container, MenuProvider, ISpecialPlayerInventory { - private final List slots; + private final List slots; private final int size; private ServerPlayer owner; private int maxStackSize = 99; @@ -43,7 +53,7 @@ public OpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { int rawSize = owner.getInventory().getContainerSize() + owner.inventoryMenu.getCraftSlots().getContainerSize() + 1; size = ((int) Math.ceil(rawSize / 9.0)) * 9; - slots = NonNullList.withSize(size, new ContainerSlotUninteractable(owner)); + slots = NonNullList.withSize(size, new ContentViewOnly(owner)); setupSlots(); } @@ -62,9 +72,9 @@ private void setupSlots() { // Off-hand: Below chestplate. addOffHand(46); // Drop slot: Bottom right. - slots.set(53, new ContainerSlotDrop(owner)); + slots.set(53, new ContentDrop(owner)); // Cursor slot: Above drop. - slots.set(44, new ContainerSlotCursor(owner)); + slots.set(44, new ContentCursor(owner)); // Crafting is displayed in the bottom right corner. // As we're using the pretty view, this is a 3x2. @@ -76,9 +86,9 @@ private void setupSlots() { nextIndex = addArmor(nextIndex); nextIndex = addOffHand(nextIndex); nextIndex = addCrafting(nextIndex, false); - slots.set(nextIndex, new ContainerSlotCursor(owner)); + slots.set(nextIndex, new ContentCursor(owner)); // Drop slot last. - slots.set(slots.size() - 1, new ContainerSlotDrop(owner)); + slots.set(slots.size() - 1, new ContentDrop(owner)); } private int addMainInventory() { @@ -97,7 +107,7 @@ private int addMainInventory() { invIndex = localIndex - hotbarDiff; } - slots.set(localIndex, new ContainerSlotList(owner, invIndex, type) { + slots.set(localIndex, new ContentList(owner, invIndex, type) { @Override public void setHolder(@NotNull ServerPlayer holder) { items = holder.getInventory().items; @@ -140,7 +150,7 @@ private int addArmor(int startIndex) { } } - slots.set(startIndex + i, new ContainerSlotEquipment(owner, armorIndex, slot)); + slots.set(startIndex + i, new ContentEquipment(owner, armorIndex, slot)); } return startIndex + listSize; @@ -149,7 +159,7 @@ private int addArmor(int startIndex) { private int addOffHand(int startIndex) { int listSize = owner.getInventory().offhand.size(); for (int localIndex = 0; localIndex < listSize; ++localIndex) { - slots.set(startIndex + localIndex, new ContainerSlotOffHand(owner, localIndex)); + slots.set(startIndex + localIndex, new ContentOffHand(owner, localIndex)); } return startIndex + listSize; } @@ -164,29 +174,29 @@ private int addCrafting(int startIndex, boolean pretty) { // Otherwise, subtract 2 and add 9 to start in the same position on the next row. int modIndex = startIndex + (localIndex < 2 || !pretty ? localIndex : localIndex + 7); - slots.set(modIndex, new ContainerSlotCrafting(owner, localIndex)); + slots.set(modIndex, new ContentCrafting(owner, localIndex)); } if (pretty) { - slots.set(startIndex + 2, new ContainerSlotUninteractable(owner) { + slots.set(startIndex + 2, new ContentViewOnly(owner) { @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotUninteractable(container, index, x, y) { + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y) { @Override - ItemStack getOrDefault() { + public ItemStack getOrDefault() { return Placeholders.craftingOutput; } }; } }); - slots.set(startIndex + 11, new ContainerSlotCraftingResult(owner)); + slots.set(startIndex + 11, new ContentCraftingResult(owner)); } return startIndex + listSize; } public Slot getMenuSlot(int index, int x, int y) { - return slots.get(index).asMenuSlot(this, index, x, y); + return slots.get(index).asSlot(this, index, x, y); } public InventoryType.SlotType getSlotType(int index) { @@ -258,7 +268,7 @@ public int getContainerSize() { @Override public boolean isEmpty() { - return slots.stream().map(ContainerSlot::get).allMatch(ItemStack::isEmpty); + return slots.stream().map(Content::get).allMatch(ItemStack::isEmpty); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java index 7e2e4a59..3e3940cd 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java @@ -1,18 +1,12 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import com.google.common.base.Suppliers; -import com.lishid.openinv.internal.v1_21_R1.AnySilentContainer; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentDrop; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.ContentEquipment; +import com.lishid.openinv.internal.v1_21_R1.inventory.slot.SlotViewOnly; import com.lishid.openinv.util.Permissions; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.inventory.ContainerListener; -import net.minecraft.world.inventory.ContainerSynchronizer; -import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -20,13 +14,8 @@ import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -public class OpenInventoryMenu extends AbstractContainerMenu { +public class OpenInventoryMenu extends OpenContainerMenu { private final OpenInventory inventory; private final ServerPlayer viewer; @@ -50,6 +39,9 @@ protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) upperRows = inventory.getContainerSize() / 9; } + boolean viewOnly = !(ownInv ? Permissions.INVENTORY_EDIT_SELF : Permissions.INVENTORY_EDIT_OTHER) + .hasPermission(viewer.getBukkitEntity()); + // View's upper inventory - our container for (int row = 0; row < upperRows; ++row) { for (int col = 0; col < 9; ++col) { @@ -61,11 +53,11 @@ protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) // Guard against weird inventory sizes. if (index >= inventory.getContainerSize()) { - addSlot(new ContainerSlotUninteractable.SlotUninteractable(inventory, index, x, y)); + addSlot(new SlotViewOnly(inventory, index, x, y)); continue; } - Slot slot = getUpperSlot(index, x, y, ownInv); + Slot slot = getUpperSlot(index, x, y, ownInv, viewOnly); addSlot(slot); } @@ -90,21 +82,25 @@ protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) this.topSize = slots.size() - 36; } - private Slot getUpperSlot(int index, int x, int y, boolean ownInv) { + private Slot getUpperSlot(int index, int x, int y, boolean ownInv, boolean viewOnly) { Slot slot = inventory.getMenuSlot(index, x, y); // If the slot is cannot be interacted with there's nothing to configure. - if (slot.getClass().equals(ContainerSlotUninteractable.SlotUninteractable.class)) { + if (slot.getClass().equals(SlotViewOnly.class)) { return slot; } // Remove drop slot if viewer is not allowed to use it. - if (slot instanceof ContainerSlotDrop.SlotDrop - && !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity())) { - return new ContainerSlotUninteractable.SlotUninteractable(inventory, index, x, y); + if (slot instanceof ContentDrop.SlotDrop + && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { + return new SlotViewOnly(inventory, index, x, y); } - if (slot instanceof ContainerSlotEquipment.SlotEquipment equipment) { + if (slot instanceof ContentEquipment.SlotEquipment equipment) { + if (viewOnly) { + return SlotViewOnly.wrap(slot); + } + Permissions perm = switch (equipment.getEquipmentSlot()) { case HEAD -> Permissions.INVENTORY_SLOT_HEAD_ANY; case CHEST -> Permissions.INVENTORY_SLOT_CHEST_ANY; @@ -113,30 +109,36 @@ private Slot getUpperSlot(int index, int x, int y, boolean ownInv) { // Off-hand can hold anything, not just equipment. default -> null; }; + // If the viewer doesn't have permission, only allow equipment the viewee can equip in the slot. if (perm != null && !perm.hasPermission(viewer.getBukkitEntity())) { equipment.onlyEquipmentFor(inventory.getOwnerHandle()); } + // Equipment slots are a core part of the inventory, so they will always be shown. return slot; } // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). - if (ownInv && !(slot instanceof ContainerSlotDrop.SlotDrop)) { - return new ContainerSlotUninteractable.SlotUninteractable(inventory, index, x, y); + if (ownInv && !(slot instanceof ContentDrop.SlotDrop)) { + return new SlotViewOnly(inventory, index, x, y); + } + + if (viewOnly) { + return SlotViewOnly.wrap(slot); } return slot; } - static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { + private static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { int size = inventory.getContainerSize(); if (inventory.getOwnerHandle().equals(viewer)) { size -= viewer.getInventory().items.size(); size = ((int) Math.ceil(size / 9.0)) * 9; } - return AnySilentContainer.getContainers(size); + return OpenContainerMenu.getContainers(size); } @Override @@ -174,191 +176,6 @@ public InventoryType.SlotType getSlotType(int slot) { return bukkitEntity; } - // - // Back at it again, overriding a bunch of methods because we need access to 2 fields. - private @Nullable ContainerSynchronizer synchronizer; - private final List dataSlots = new ArrayList<>(); - private final IntList remoteDataSlots = new IntArrayList(); - private final List containerListeners = new ArrayList<>(); - private ItemStack remoteCarried = ItemStack.EMPTY; - private boolean suppressRemoteUpdates; - - @Override - protected Slot addSlot(Slot slot) { - slot.index = this.slots.size(); - this.slots.add(slot); - this.lastSlots.add(ItemStack.EMPTY); - this.remoteSlots.add(ItemStack.EMPTY); - return slot; - } - - @Override - protected DataSlot addDataSlot(DataSlot dataSlot) { - this.dataSlots.add(dataSlot); - this.remoteDataSlots.add(0); - return dataSlot; - } - - @Override - protected void addDataSlots(ContainerData containerData) { - for (int i = 0; i < containerData.getCount(); i++) { - this.addDataSlot(DataSlot.forContainer(containerData, i)); - } - } - - @Override - public void addSlotListener(ContainerListener containerListener) { - if (!this.containerListeners.contains(containerListener)) { - this.containerListeners.add(containerListener); - this.broadcastChanges(); - } - } - - @Override - public void setSynchronizer(ContainerSynchronizer containerSynchronizer) { - this.synchronizer = containerSynchronizer; - this.sendAllDataToRemote(); - } - - @Override - public void sendAllDataToRemote() { - for (int index = 0; index < slots.size(); ++index) { - Slot slot = slots.get(index); - this.remoteSlots.set(index, (slot instanceof MenuSlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem()).copy()); - } - - remoteCarried = getCarried().copy(); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - this.remoteDataSlots.set(index, this.dataSlots.get(index).get()); - } - - if (this.synchronizer != null) { - this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); - } - } - - @Override - public void broadcastCarriedItem() { - this.remoteCarried = this.getCarried().copy(); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, this.remoteCarried); - } - } - - @Override - public void removeSlotListener(ContainerListener containerListener) { - this.containerListeners.remove(containerListener); - } - - @Override - public void broadcastChanges() { - for (int index = 0; index < this.slots.size(); ++index) { - Slot slot = this.slots.get(index); - ItemStack itemstack = slot instanceof MenuSlotPlaceholder placeholder ? placeholder.getOrDefault() : slot.getItem(); - Supplier supplier = Suppliers.memoize(itemstack::copy); - this.triggerSlotListeners(index, itemstack, supplier); - this.synchronizeSlotToRemote(index, itemstack, supplier); - } - - this.synchronizeCarriedToRemote(); - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot dataSlot = this.dataSlots.get(index); - int j = dataSlot.get(); - if (dataSlot.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, j); - } - - this.synchronizeDataSlotToRemote(index, j); - } - } - - @Override - public void broadcastFullState() { - for (int index = 0; index < this.slots.size(); ++index) { - ItemStack itemstack = this.slots.get(index).getItem(); - this.triggerSlotListeners(index, itemstack, itemstack::copy); - } - - for (int index = 0; index < this.dataSlots.size(); ++index) { - DataSlot containerproperty = this.dataSlots.get(index); - if (containerproperty.checkAndClearUpdateFlag()) { - this.updateDataSlotListeners(index, containerproperty.get()); - } - } - - this.sendAllDataToRemote(); - } - - private void updateDataSlotListeners(int i, int j) { - for (ContainerListener containerListener : this.containerListeners) { - containerListener.dataChanged(this, i, j); - } - } - - private void triggerSlotListeners(int index, ItemStack itemStack, Supplier supplier) { - ItemStack itemStack1 = this.lastSlots.get(index); - if (!ItemStack.matches(itemStack1, itemStack)) { - ItemStack itemStack2 = supplier.get(); - this.lastSlots.set(index, itemStack2); - - for (ContainerListener containerListener : this.containerListeners) { - containerListener.slotChanged(this, index, itemStack2); - } - } - } - - private void synchronizeSlotToRemote(int i, ItemStack itemStack, Supplier supplier) { - if (!this.suppressRemoteUpdates) { - ItemStack itemStack1 = this.remoteSlots.get(i); - if (!ItemStack.matches(itemStack1, itemStack)) { - ItemStack itemstack2 = supplier.get(); - this.remoteSlots.set(i, itemstack2); - if (this.synchronizer != null) { - this.synchronizer.sendSlotChange(this, i, itemstack2); - } - } - } - } - - private void synchronizeDataSlotToRemote(int index, int value) { - if (!this.suppressRemoteUpdates) { - int existing = this.remoteDataSlots.getInt(index); - if (existing != value) { - this.remoteDataSlots.set(index, value); - if (this.synchronizer != null) { - this.synchronizer.sendDataChange(this, index, value); - } - } - } - } - - private void synchronizeCarriedToRemote() { - if (!this.suppressRemoteUpdates && !ItemStack.matches(this.getCarried(), this.remoteCarried)) { - this.remoteCarried = this.getCarried().copy(); - if (this.synchronizer != null) { - this.synchronizer.sendCarriedChange(this, this.remoteCarried); - } - } - } - - @Override - public void setRemoteCarried(ItemStack itemstack) { - this.remoteCarried = itemstack.copy(); - } - - @Override - public void suppressRemoteUpdates() { - this.suppressRemoteUpdates = true; - } - - @Override - public void resumeRemoteUpdates() { - this.suppressRemoteUpdates = false; - } - // - @Override public ItemStack quickMoveStack(Player player, int index) { // See ChestMenu and InventoryMenu @@ -384,7 +201,7 @@ public ItemStack quickMoveStack(Player player, int index) { // Locate the correct slot in the contents following the main inventory. for (int extra = inventory.getOwnerHandle().getInventory().items.size() - offset; extra < topSize; ++extra) { Slot extraSlot = getSlot(extra); - if (extraSlot instanceof ContainerSlotEquipment.SlotEquipment equipSlot + if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot && equipSlot.getEquipmentSlot() == equipmentSlot) { // If we've found a matching slot, try to move to it. // If this succeeds, even partially, we will not attempt to move to other slots. @@ -425,90 +242,9 @@ public boolean stillValid(Player player) { return true; } - /** - * Reimplementation of {@link AbstractContainerMenu#moveItemStackTo(ItemStack, int, int, boolean)} that ignores fake - * slots and respects {@link Slot#hasItem()}. - * - * @param itemStack the stack to quick-move - * @param rangeLow the start of the range of slots that can be moved to, inclusive - * @param rangeHigh the end of the range of slots that can be moved to, exclusive - * @param topDown whether to start at the top of the range or bottom - * @return whether the stack was modified as a result of being quick-moved - */ - @Override - protected boolean moveItemStackTo(ItemStack itemStack, int rangeLow, int rangeHigh, boolean topDown) { - boolean modified = false; - boolean stackable = itemStack.isStackable(); - Slot firstEmpty = null; - - for (int index = topDown ? rangeHigh - 1 : rangeLow; - !itemStack.isEmpty() && (topDown ? index >= rangeLow : index < rangeHigh); - index += topDown ? -1 : 1 - ) { - Slot slot = slots.get(index); - // If the slot cannot be added to, check the next slot. - if (slot.isFake() || !slot.mayPlace(itemStack)) { - continue; - } - - if (slot.hasItem()) { - // If the item isn't stackable, check the next slot. - if (!stackable) { - continue; - } - // Otherwise, add as many as we can from our stack to the slot. - modified = addToExistingStack(itemStack, slot); - } else { - // If this is the first empty slot, keep track of it for later use. - if (firstEmpty == null) { - firstEmpty = slot; - } - // If the item isn't stackable, we've located the slot we're adding it to, so we're done. - if (!stackable) { - break; - } - } - } - - // If the item hasn't been fully added yet, add as many as we can to the first open slot. - if (!itemStack.isEmpty() && firstEmpty != null) { - firstEmpty.setByPlayer(itemStack.split(Math.min(itemStack.getCount(), firstEmpty.getMaxStackSize(itemStack)))); - firstEmpty.setChanged(); - modified = true; - } - - return modified; - } - - private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { - ItemStack existing = slot.getItem(); - - // If the items aren't the same, we can't add our item. - if (!ItemStack.isSameItemSameComponents(itemStack, existing)) { - return false; - } - - int total = existing.getCount() + itemStack.getCount(); - int max = slot.getMaxStackSize(existing); - - // If the existing item can accept the entirety of our item, we're done! - if (total <= max) { - itemStack.setCount(0); - existing.setCount(total); - slot.setChanged(); - return true; - } - - // Otherwise, add as many as we can. - itemStack.shrink(max - existing.getCount()); - existing.setCount(max); - slot.setChanged(); - return true; - } - @Override public boolean canDragTo(Slot slot) { - return !(slot instanceof ContainerSlotDrop.SlotDrop || slot instanceof ContainerSlotUninteractable.SlotUninteractable); + return !(slot instanceof ContentDrop.SlotDrop || slot instanceof SlotViewOnly); } } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/Placeholders.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/Placeholders.java index 48b91ba7..16fc3269 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/Placeholders.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/Placeholders.java @@ -30,17 +30,17 @@ public final class Placeholders { private static final CustomModelData DEFAULT_CUSTOM_MODEL_DATA = new CustomModelData(9999); - static final @NotNull EnumMap BLOCKED_GAME_TYPE = new EnumMap<>(GameType.class); - static @NotNull ItemStack craftingOutput = defaultCraftingOutput(); - static @NotNull ItemStack cursor = defaultCursor(); - static @NotNull ItemStack drop = defaultDrop(); - static @NotNull ItemStack emptyHelmet = getEmptyArmor(Items.LEATHER_HELMET); - static @NotNull ItemStack emptyChestplate = getEmptyArmor(Items.LEATHER_CHESTPLATE); - static @NotNull ItemStack emptyLeggings = getEmptyArmor(Items.LEATHER_LEGGINGS); - static @NotNull ItemStack emptyBoots = getEmptyArmor(Items.LEATHER_BOOTS); - static @NotNull ItemStack emptyOffHand = getEmptyShield(); - static @NotNull ItemStack notSlot = defaultNotSlot(); - static @NotNull ItemStack blockedOffline = defaultBlockedOffline(); + public static final @NotNull EnumMap BLOCKED_GAME_TYPE = new EnumMap<>(GameType.class); + public static @NotNull ItemStack craftingOutput = defaultCraftingOutput(); + public static @NotNull ItemStack cursor = defaultCursor(); + public static @NotNull ItemStack drop = defaultDrop(); + public static @NotNull ItemStack emptyHelmet = getEmptyArmor(Items.LEATHER_HELMET); + public static @NotNull ItemStack emptyChestplate = getEmptyArmor(Items.LEATHER_CHESTPLATE); + public static @NotNull ItemStack emptyLeggings = getEmptyArmor(Items.LEATHER_LEGGINGS); + public static @NotNull ItemStack emptyBoots = getEmptyArmor(Items.LEATHER_BOOTS); + public static @NotNull ItemStack emptyOffHand = getEmptyShield(); + public static @NotNull ItemStack notSlot = defaultNotSlot(); + public static @NotNull ItemStack blockedOffline = defaultBlockedOffline(); static { for (GameType type : GameType.values()) { @@ -83,7 +83,7 @@ public static void load(@NotNull ConfigurationSection section) throws Exception return parsed.filter(itemStack -> !itemStack.isEmpty()).orElse(defaultStack); } - static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { + public static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { if (serverPlayer.connection == null || serverPlayer.connection.isDisconnected()) { return blockedOffline; } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlot.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/Content.java similarity index 86% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlot.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/Content.java index a61b1549..eed38f34 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlot.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/Content.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; @@ -7,9 +7,9 @@ import org.jetbrains.annotations.NotNull; /** - * An interface defining behaviors for entries in a {@link Container}. Used to reduce duplicate slot reordering. + * An interface defining behaviors for entries in a {@link Container}. Used to reduce duplicate content reordering. */ -interface ContainerSlot { +public interface Content { /** * Update internal holder. @@ -51,12 +51,12 @@ interface ContainerSlot { * impose any specific restrictions to insertion or removal. * * @param container the backing container - * @param index the slot of the backing container represented + * @param slot the slot of the backing container represented * @param x clientside x dimension from top left of inventory, not used * @param y clientside y dimension from top left of inventory, not used * @return a menu slot */ - Slot asMenuSlot(Container container, int index, int x, int y); + Slot asSlot(Container container, int slot, int x, int y); /** * Get a loose Bukkit translation of what this slot stores. For example, any slot that drops items at the owner rather diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCrafting.java similarity index 84% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCrafting.java index a071e123..5edd1ef0 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCrafting.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; @@ -14,13 +15,13 @@ /** * A slot in a survival crafting inventory. Unavailable when not online in a survival mode. */ -class ContainerSlotCrafting implements ContainerSlot { +public class ContentCrafting implements Content { private final int index; private ServerPlayer holder; private List items; - ContainerSlotCrafting(@NotNull ServerPlayer holder, int index) { + public ContentCrafting(@NotNull ServerPlayer holder, int index) { setHolder(holder); this.index = index; } @@ -85,8 +86,8 @@ public void set(ItemStack itemStack) { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotCrafting(container, index, x, y); + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotCrafting(container, slot, x, y); } @Override @@ -94,15 +95,15 @@ public InventoryType.SlotType getSlotType() { return isAvailable() ? InventoryType.SlotType.CRAFTING : InventoryType.SlotType.OUTSIDE; } - class SlotCrafting extends MenuSlotPlaceholder { + public class SlotCrafting extends SlotPlaceholder { private SlotCrafting(Container container, int index, int x, int y) { super(container, index, x, y); } @Override - ItemStack getOrDefault() { - return isAvailable() ? items.get(ContainerSlotCrafting.this.index) : Placeholders.survivalOnly(holder); + public ItemStack getOrDefault() { + return isAvailable() ? items.get(ContentCrafting.this.index) : Placeholders.survivalOnly(holder); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCraftingResult.java similarity index 68% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCraftingResult.java index 3bf9fb43..4a26a543 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCraftingResult.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.InventoryMenu; @@ -13,9 +14,9 @@ * *

Unmodifiable because I said so. Use your own crafting grid.

*/ -class ContainerSlotCraftingResult extends ContainerSlotUninteractable { +public class ContentCraftingResult extends ContentViewOnly { - ContainerSlotCraftingResult(@NotNull ServerPlayer holder) { + public ContentCraftingResult(@NotNull ServerPlayer holder) { super(holder); } @@ -26,11 +27,11 @@ public ItemStack get() { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotUninteractable(container, index, x, y) { + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y) { @Override - ItemStack getOrDefault() { - if (!ContainerSlotCrafting.isAvailable(holder)) { + public ItemStack getOrDefault() { + if (!ContentCrafting.isAvailable(holder)) { return Placeholders.survivalOnly(holder); } InventoryMenu inventoryMenu = holder.inventoryMenu; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCursor.java similarity index 86% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCursor.java index 33b83df6..19694fda 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentCursor.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; @@ -11,11 +12,11 @@ /** * A slot wrapping the active menu's cursor. Unavailable when not online in a survival mode. */ -class ContainerSlotCursor implements ContainerSlot { +public class ContentCursor implements Content { private @NotNull ServerPlayer holder; - ContainerSlotCursor(@NotNull ServerPlayer holder) { + public ContentCursor(@NotNull ServerPlayer holder) { this.holder = holder; } @@ -66,8 +67,8 @@ private boolean isAvailable() { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotCursor(container, index, x, y); + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotCursor(container, slot, x, y); } @Override @@ -76,14 +77,14 @@ public InventoryType.SlotType getSlotType() { return InventoryType.SlotType.OUTSIDE; } - class SlotCursor extends MenuSlotPlaceholder { + public class SlotCursor extends SlotPlaceholder { private SlotCursor(Container container, int index, int x, int y) { super(container, index, x, y); } @Override - ItemStack getOrDefault() { + public ItemStack getOrDefault() { if (!isAvailable()) { return Placeholders.survivalOnly(holder); } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentDrop.java similarity index 78% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentDrop.java index e7fb80c5..45594a06 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentDrop.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; @@ -10,11 +11,11 @@ /** * A fake slot used to drop items. Unavailable offline. */ -class ContainerSlotDrop implements ContainerSlot { +public class ContentDrop implements Content { private ServerPlayer holder; - ContainerSlotDrop(@NotNull ServerPlayer holder) { + public ContentDrop(@NotNull ServerPlayer holder) { this.holder = holder; } @@ -44,8 +45,8 @@ public void set(ItemStack itemStack) { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotDrop(container, index, x, y); + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotDrop(container, slot, x, y); } @Override @@ -54,14 +55,14 @@ public InventoryType.SlotType getSlotType() { return InventoryType.SlotType.OUTSIDE; } - class SlotDrop extends MenuSlotPlaceholder { + public class SlotDrop extends SlotPlaceholder { private SlotDrop(Container container, int index, int x, int y) { super(container, index, x, y); } @Override - ItemStack getOrDefault() { + public ItemStack getOrDefault() { return holder.connection != null && !holder.connection.isDisconnected() ? Placeholders.drop : Placeholders.blockedOffline; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentEquipment.java similarity index 73% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentEquipment.java index 99f8b39d..2ba44873 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentEquipment.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; @@ -11,12 +12,12 @@ /** * A slot for equipment that displays placeholders if empty. */ -class ContainerSlotEquipment extends ContainerSlotList { +public class ContentEquipment extends ContentList { private final ItemStack placeholder; private final EquipmentSlot equipmentSlot; - ContainerSlotEquipment(ServerPlayer holder, int index, EquipmentSlot equipmentSlot) { + public ContentEquipment(ServerPlayer holder, int index, EquipmentSlot equipmentSlot) { super(holder, index, InventoryType.SlotType.ARMOR); placeholder = switch (equipmentSlot) { case HEAD -> Placeholders.emptyHelmet; @@ -34,11 +35,11 @@ public void setHolder(@NotNull ServerPlayer holder) { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotEquipment(container, index, x, y); + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotEquipment(container, slot, x, y); } - class SlotEquipment extends MenuSlotPlaceholder { + public class SlotEquipment extends SlotPlaceholder { private ServerPlayer viewer; @@ -47,7 +48,7 @@ class SlotEquipment extends MenuSlotPlaceholder { } @Override - ItemStack getOrDefault() { + public ItemStack getOrDefault() { ItemStack itemStack = getItem(); if (!itemStack.isEmpty()) { return itemStack; @@ -55,11 +56,11 @@ ItemStack getOrDefault() { return placeholder; } - EquipmentSlot getEquipmentSlot() { + public EquipmentSlot getEquipmentSlot() { return equipmentSlot; } - void onlyEquipmentFor(ServerPlayer viewer) { + public void onlyEquipmentFor(ServerPlayer viewer) { this.viewer = viewer; } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotList.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentList.java similarity index 75% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotList.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentList.java index 15c0e069..980c0b12 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotList.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentList.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; @@ -12,13 +12,13 @@ /** * A normal slot backed by an item list. */ -abstract class ContainerSlotList implements ContainerSlot { +public abstract class ContentList implements Content { private final int index; private final InventoryType.SlotType slotType; - List items; + protected List items; - ContainerSlotList(ServerPlayer holder, int index, InventoryType.SlotType slotType) { + public ContentList(ServerPlayer holder, int index, InventoryType.SlotType slotType) { this.index = index; this.slotType = slotType; setHolder(holder); @@ -46,8 +46,8 @@ public void set(ItemStack itemStack) { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new Slot(container, index, x, y); + public Slot asSlot(Container container, int slot, int x, int y) { + return new Slot(container, slot, x, y); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotOffHand.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentOffHand.java similarity index 75% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotOffHand.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentOffHand.java index 556203f5..f8872900 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotOffHand.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentOffHand.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; @@ -10,11 +10,11 @@ /** * A slot for equipment that updates held items if necessary. */ -class ContainerSlotOffHand extends ContainerSlotEquipment { +public class ContentOffHand extends ContentEquipment { private ServerPlayer holder; - public ContainerSlotOffHand(ServerPlayer holder, int localIndex) { + public ContentOffHand(ServerPlayer holder, int localIndex) { super(holder, localIndex, EquipmentSlot.OFFHAND); } @@ -30,8 +30,8 @@ public InventoryType.SlotType getSlotType() { } @Override - public Slot asMenuSlot(Container container, int index, int x, int y) { - return new SlotEquipment(container, index, x, y) { + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotEquipment(container, slot, x, y) { @Override public void setChanged() { if (holder.connection != null diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentViewOnly.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentViewOnly.java new file mode 100644 index 00000000..b7dc9a1a --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/ContentViewOnly.java @@ -0,0 +1,56 @@ +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.NotNull; + +/** + * A view-only slot that can't be interacted with. + */ +public class ContentViewOnly implements Content { + + @NotNull ServerPlayer holder; + + public ContentViewOnly(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public void setHolder(@NotNull ServerPlayer holder) { + this.holder = holder; + } + + @Override + public ItemStack get() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack remove() { + return ItemStack.EMPTY; + } + + @Override + public ItemStack removePartial(int amount) { + return ItemStack.EMPTY; + } + + @Override + public void set(ItemStack itemStack) { + this.holder.drop(itemStack, false); + } + + @Override + public Slot asSlot(Container container, int slot, int x, int y) { + return new SlotViewOnly(container, slot, x, y); + } + + @Override + public InventoryType.SlotType getSlotType() { + return InventoryType.SlotType.OUTSIDE; + } + +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotPlaceholder.java similarity index 61% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotPlaceholder.java index b29afdc5..315b2b5c 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotPlaceholder.java @@ -1,4 +1,4 @@ -package com.lishid.openinv.internal.v1_21_R1.inventory; +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; @@ -9,12 +9,12 @@ * *

Used to prevent plugins (particularly sorting plugins) from adding placeholders to inventories.

*/ -abstract class MenuSlotPlaceholder extends Slot { +public abstract class SlotPlaceholder extends Slot { - MenuSlotPlaceholder(Container container, int index, int x, int y) { + public SlotPlaceholder(Container container, int index, int x, int y) { super(container, index, x, y); } - abstract ItemStack getOrDefault(); + public abstract ItemStack getOrDefault(); } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotViewOnly.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotViewOnly.java new file mode 100644 index 00000000..5fa9edd5 --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/slot/SlotViewOnly.java @@ -0,0 +1,151 @@ +package com.lishid.openinv.internal.v1_21_R1.inventory.slot; + +import com.lishid.openinv.internal.v1_21_R1.inventory.Placeholders; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +/** + * A view-only {@link Slot}. "Blank" by default, but can wrap another slot to display its content. + */ +public class SlotViewOnly extends SlotPlaceholder { + + public static @NotNull SlotViewOnly wrap(@NotNull Slot wrapped) { + SlotViewOnly wrapper; + if (wrapped instanceof SlotPlaceholder placeholder) { + wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) { + @Override + public ItemStack getOrDefault() { + return placeholder.getOrDefault(); + } + }; + } else { + wrapper = new SlotViewOnly(wrapped.container, wrapped.slot, wrapped.x, wrapped.y) { + @Override + public ItemStack getOrDefault() { + return wrapped.getItem(); + } + }; + } + wrapper.index = wrapped.index; + return wrapper; + } + + public SlotViewOnly(Container container, int index, int x, int y) { + super(container, index, x, y); + } + + @Override + public ItemStack getOrDefault() { + return Placeholders.notSlot; + } + + @Override + public void onQuickCraft(ItemStack var0, ItemStack var1) { + } + + @Override + public void onTake(Player var0, ItemStack var1) { + } + + @Override + public boolean mayPlace(ItemStack var0) { + return false; + } + + @Override + public ItemStack getItem() { + return ItemStack.EMPTY; + } + + @Override + public boolean hasItem() { + return false; + } + + @Override + public void setByPlayer(ItemStack newStack) { + } + + @Override + public void setByPlayer(ItemStack newStack, ItemStack oldStack) { + } + + @Override + public void set(ItemStack var0) { + } + + @Override + public void setChanged() { + } + + @Override + public int getMaxStackSize() { + return 0; + } + + @Override + public int getMaxStackSize(ItemStack itemStack) { + return 0; + } + + @Override + public ItemStack remove(int amount) { + return ItemStack.EMPTY; + } + + @Override + public boolean mayPickup(Player var0) { + return false; + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public Optional tryRemove(int var0, int var1, Player var2) { + return Optional.empty(); + } + + @Override + public ItemStack safeTake(int var0, int var1, Player var2) { + return ItemStack.EMPTY; + } + + @Override + public ItemStack safeInsert(ItemStack itemStack) { + return itemStack; + } + + @Override + public ItemStack safeInsert(ItemStack itemStack, int amount) { + return itemStack; + } + + @Override + public boolean allowModification(Player var0) { + return false; + } + + @Override + public int getContainerSlot() { + return this.slot; + } + + @Override + public boolean isHighlightable() { + return false; + } + + @Override + public boolean isFake() { + return true; + } + +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenPlayer.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/OpenPlayer.java similarity index 89% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenPlayer.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/OpenPlayer.java index ac07285d..cae26fef 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenPlayer.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/OpenPlayer.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2011-2023 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_21_R1; +package com.lishid.openinv.internal.v1_21_R1.player; import com.lishid.openinv.event.OpenEvents; import com.mojang.logging.LogUtils; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerManager.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/PlayerManager.java similarity index 93% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerManager.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/PlayerManager.java index e40eade4..6fd0d9ec 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerManager.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/player/PlayerManager.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2011-2023 lishid. All rights reserved. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lishid.openinv.internal.v1_21_R1; +package com.lishid.openinv.internal.v1_21_R1.player; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.v1_21_R1.inventory.OpenEnderChest; diff --git a/plugin/pom.xml b/plugin/pom.xml index 381a5018..ff10c880 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -80,6 +80,14 @@ maven-shade-plugin + + + package + + shade + + +