diff --git a/common/src/main/java/com/lishid/openinv/internal/InternalOwned.java b/common/src/main/java/com/lishid/openinv/internal/InternalOwned.java new file mode 100644 index 00000000..24f826d0 --- /dev/null +++ b/common/src/main/java/com/lishid/openinv/internal/InternalOwned.java @@ -0,0 +1,7 @@ +package com.lishid.openinv.internal; + +public interface InternalOwned { + + T getOwnerHandle(); + +} diff --git a/common/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java b/common/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java deleted file mode 100644 index 05a8c17b..00000000 --- a/common/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.lishid.openinv.internal; - -import org.bukkit.configuration.ConfigurationSection; - -public interface PlaceholderParser { - - void load(ConfigurationSection section) throws Exception; - -} diff --git a/common/src/main/java/com/lishid/openinv/internal/ViewOnly.java b/common/src/main/java/com/lishid/openinv/internal/ViewOnly.java new file mode 100644 index 00000000..b8c5bfa6 --- /dev/null +++ b/common/src/main/java/com/lishid/openinv/internal/ViewOnly.java @@ -0,0 +1,4 @@ +package com.lishid.openinv.internal; + +public interface ViewOnly { +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/AnySilentContainer.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/AnySilentContainer.java index 05fb013a..d5b91cf2 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/AnySilentContainer.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/AnySilentContainer.java @@ -17,6 +17,7 @@ package com.lishid.openinv.internal.v1_21_R1.container; import com.lishid.openinv.internal.IAnySilentContainer; +import com.lishid.openinv.internal.v1_21_R1.container.menu.OpenChestMenu; import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import com.lishid.openinv.util.ReflectionHelper; import com.lishid.openinv.util.lang.LanguageManager; @@ -103,7 +104,7 @@ public boolean activateContainer( PlayerEnderChestContainer enderChest = player.getEnderChestInventory(); enderChest.setActiveChest(enderChestTile); player.openMenu(new SimpleMenuProvider((containerCounter, playerInventory, ignored) -> { - MenuType containers = OpenContainerMenu.getContainers(enderChest.getContainerSize()); + MenuType containers = OpenChestMenu.getChestMenuType(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/container/OpenEnderChest.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChest.java index fa038e7e..eefaf3ed 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChest.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChest.java @@ -1,6 +1,8 @@ package com.lishid.openinv.internal.v1_21_R1.container; import com.lishid.openinv.internal.ISpecialEnderChest; +import com.lishid.openinv.internal.InternalOwned; +import com.lishid.openinv.internal.v1_21_R1.container.menu.OpenEnderChestMenu; import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import net.minecraft.core.NonNullList; import net.minecraft.network.chat.Component; @@ -25,7 +27,8 @@ import java.util.ArrayList; import java.util.List; -public class OpenEnderChest implements Container, StackedContentsCompatible, MenuProvider, ISpecialEnderChest { +public class OpenEnderChest implements Container, StackedContentsCompatible, MenuProvider, + InternalOwned, ISpecialEnderChest { private CraftInventory inventory; private @NotNull ServerPlayer owner; @@ -38,6 +41,7 @@ public OpenEnderChest(@NotNull org.bukkit.entity.Player player) { this.items = owner.getEnderChestInventory().items; } + @Override public @NotNull ServerPlayer getOwnerHandle() { return owner; } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChestMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChestMenu.java deleted file mode 100644 index cbd27eb9..00000000 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenEnderChestMenu.java +++ /dev/null @@ -1,147 +0,0 @@ -package com.lishid.openinv.internal.v1_21_R1.container; - -import com.lishid.openinv.internal.v1_21_R1.container.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; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -class OpenEnderChestMenu extends OpenContainerMenu { - - private final OpenEnderChest enderChest; - private final int topSize; - private CraftInventoryView view; - - OpenEnderChestMenu(OpenEnderChest enderChest, ServerPlayer viewer, int containerId) { - super(getMenuType(enderChest), containerId, enderChest.getOwnerHandle(), viewer); - this.enderChest = enderChest; - 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 - protected boolean checkViewOnly() { - return !(ownContainer ? Permissions.ENDERCHEST_EDIT_SELF : Permissions.ENDERCHEST_OPEN_OTHER) - .hasPermission(viewer.getBukkitEntity()); - } - - @Override - public CraftInventoryView getBukkitView() { - if (view == null) { - Inventory top; - if (viewOnly) { - top = new OpenViewInventory(enderChest); - } else { - top = enderChest.getBukkitInventory(); - } - view = new CraftInventoryView(viewer.getBukkitEntity(), top, this) { - @Override - public @Nullable Inventory getInventory(int rawSlot) { - if (viewOnly) { - return null; - } - return super.getInventory(rawSlot); - } - - @Override - public int convertSlot(int rawSlot) { - if (viewOnly) { - return InventoryView.OUTSIDE; - } - return super.convertSlot(rawSlot); - } - - @Override - public @NotNull InventoryType.SlotType getSlotType(int slot) { - if (viewOnly) { - return InventoryType.SlotType.OUTSIDE; - } - return super.getSlotType(slot); - } - }; - } - return view; - } - - @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/container/OpenInventory.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventory.java index bec7a8a5..8461901c 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventory.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventory.java @@ -1,6 +1,9 @@ package com.lishid.openinv.internal.v1_21_R1.container; import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.InternalOwned; +import com.lishid.openinv.internal.v1_21_R1.container.bukkit.OpenPlayerInventory; +import com.lishid.openinv.internal.v1_21_R1.container.menu.OpenInventoryMenu; import com.lishid.openinv.internal.v1_21_R1.player.PlayerManager; import com.lishid.openinv.internal.v1_21_R1.container.slot.Content; import com.lishid.openinv.internal.v1_21_R1.container.slot.ContentCrafting; @@ -37,7 +40,7 @@ import java.util.ArrayList; import java.util.List; -public class OpenInventory implements Container, MenuProvider, ISpecialPlayerInventory { +public class OpenInventory implements Container, MenuProvider, InternalOwned, ISpecialPlayerInventory { private final List slots; private final int size; @@ -203,10 +206,6 @@ public InventoryType.SlotType getSlotType(int index) { return slots.get(index).getSlotType(); } - public ServerPlayer getOwnerHandle() { - return owner; - } - public @NotNull Component getTitle(@Nullable ServerPlayer viewer) { MutableComponent component = Component.empty(); // Prefix for use with custom bitmap image fonts. @@ -230,6 +229,11 @@ public ServerPlayer getOwnerHandle() { return component; } + @Override + public ServerPlayer getOwnerHandle() { + return owner; + } + @Override public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { if (bukkitEntity == null) { diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenViewInventory.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenDummyInventory.java similarity index 89% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenViewInventory.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenDummyInventory.java index b714a287..c0eb1a38 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenViewInventory.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenDummyInventory.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.container; +package com.lishid.openinv.internal.v1_21_R1.container.bukkit; +import com.lishid.openinv.internal.ViewOnly; import net.minecraft.world.Container; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory; @@ -14,9 +15,9 @@ /** * A locked down "empty" inventory that rejects plugin interaction. */ -public class OpenViewInventory extends CraftInventory { +public class OpenDummyInventory extends CraftInventory implements ViewOnly { - public OpenViewInventory(Container inventory) { + public OpenDummyInventory(Container inventory) { super(inventory); } @@ -30,16 +31,19 @@ public void setItem(int index, @Nullable ItemStack item) { } + @SuppressWarnings("NonApiType") @Override public @NotNull HashMap addItem(@NotNull ItemStack... items) throws IllegalArgumentException { return arrayToHashMap(items); } + @SuppressWarnings("NonApiType") @Override public @NotNull HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException { return arrayToHashMap(items); } + @SuppressWarnings("NonApiType") private static @NotNull HashMap arrayToHashMap(@NotNull ItemStack[] items) { HashMap ignored = new HashMap<>(); for (int index = 0; index < items.length; ++index) { @@ -93,12 +97,14 @@ public boolean containsAtLeast(@Nullable ItemStack item, int amount) { return false; } + @SuppressWarnings("NonApiType") @Override public @NotNull HashMap all( @NotNull Material material) throws IllegalArgumentException { return new HashMap<>(); } + @SuppressWarnings("NonApiType") @Override public @NotNull HashMap all(@Nullable ItemStack item) { return new HashMap<>(); diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventory.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventory.java similarity index 98% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventory.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventory.java index 196ee7d1..de323f5a 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventory.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventory.java @@ -1,6 +1,7 @@ -package com.lishid.openinv.internal.v1_21_R1.container; +package com.lishid.openinv.internal.v1_21_R1.container.bukkit; import com.google.common.base.Preconditions; +import com.lishid.openinv.internal.v1_21_R1.container.OpenInventory; import net.minecraft.core.NonNullList; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Inventory; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventorySelf.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventorySelf.java similarity index 79% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventorySelf.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventorySelf.java index a64b61d8..f9826ed1 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenPlayerInventorySelf.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/bukkit/OpenPlayerInventorySelf.java @@ -1,5 +1,6 @@ -package com.lishid.openinv.internal.v1_21_R1.container; +package com.lishid.openinv.internal.v1_21_R1.container.bukkit; +import com.lishid.openinv.internal.v1_21_R1.container.OpenInventory; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenContainerMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java similarity index 67% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenContainerMenu.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java index 64a42e8c..ca969983 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenContainerMenu.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenChestMenu.java @@ -1,13 +1,18 @@ -package com.lishid.openinv.internal.v1_21_R1.container; +package com.lishid.openinv.internal.v1_21_R1.container.menu; import com.google.common.base.Suppliers; +import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InternalOwned; +import com.lishid.openinv.internal.v1_21_R1.container.bukkit.OpenDummyInventory; import com.lishid.openinv.internal.v1_21_R1.container.slot.SlotPlaceholder; import com.lishid.openinv.internal.v1_21_R1.container.slot.SlotViewOnly; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.inventory.ContainerListener; @@ -16,6 +21,10 @@ 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; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,11 +35,17 @@ /** * An extension of {@link AbstractContainerMenu} that supports {@link SlotPlaceholder placeholders}. */ -public abstract class OpenContainerMenu extends AbstractContainerMenu { +public abstract class OpenChestMenu> + extends AbstractContainerMenu { + protected static final int BOTTOM_INVENTORY_SIZE = 36; + + protected final T container; protected final ServerPlayer viewer; protected final boolean viewOnly; protected final boolean ownContainer; + protected final int topSize; + private CraftInventoryView bukkitEntity; // Syncher fields private @Nullable ContainerSynchronizer synchronizer; private final List dataSlots = new ArrayList<>(); @@ -39,25 +54,142 @@ public abstract class OpenContainerMenu extends AbstractContainerMenu { private ItemStack remoteCarried = ItemStack.EMPTY; private boolean suppressRemoteUpdates; - protected OpenContainerMenu(@Nullable MenuType containers, int containerCounter,ServerPlayer owner, ServerPlayer viewer) { - super(containers, containerCounter); + protected OpenChestMenu(MenuType type, int containerCounter, T container, ServerPlayer viewer) { + super(type, containerCounter); + this.container = container; this.viewer = viewer; - ownContainer = owner.equals(viewer); + ownContainer = container.getOwnerHandle().equals(viewer); + topSize = getTopSize(viewer); viewOnly = checkViewOnly(); + + preSlotSetup(); + + int upperRows = topSize / 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 >= container.getContainerSize()) { + addSlot(new SlotViewOnly(container, index, x, y)); + continue; + } + + Slot slot = getUpperSlot(index, x, y); + + addSlot(slot); + } + } + + // 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)); + } + } + + public static @NotNull MenuType getChestMenuType(int inventorySize) { + inventorySize = ((int) Math.ceil(inventorySize / 9.0)) * 9; + return switch (inventorySize) { + case 9 -> MenuType.GENERIC_9x1; + case 18 -> MenuType.GENERIC_9x2; + case 27 -> MenuType.GENERIC_9x3; + case 36 -> MenuType.GENERIC_9x4; + case 45 -> MenuType.GENERIC_9x5; + case 54 -> MenuType.GENERIC_9x6; + default -> throw new IllegalArgumentException("Inventory size unsupported: " + inventorySize); + }; } protected abstract boolean checkViewOnly(); - 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; - }; + protected void preSlotSetup() {} + + protected @NotNull Slot getUpperSlot(int index, int x, int y) { + if (viewOnly) { + return new SlotViewOnly(container, index, x, y); + } + return new Slot(container, index, x, y); + } + + + @Override + public final @NotNull CraftInventoryView getBukkitView() { + if (bukkitEntity == null) { + bukkitEntity = createBukkitEntity(); + } + + return bukkitEntity; + } + + protected @NotNull CraftInventoryView createBukkitEntity() { + Inventory top; + if (viewOnly) { + top = new OpenDummyInventory(container); + } else { + top = container.getBukkitInventory(); + } + return new CraftInventoryView(viewer.getBukkitEntity(), top, this) { + @Override + public @Nullable Inventory getInventory(int rawSlot) { + if (viewOnly) { + return null; + } + return super.getInventory(rawSlot); + } + + @Override + public int convertSlot(int rawSlot) { + if (viewOnly) { + return InventoryView.OUTSIDE; + } + return super.convertSlot(rawSlot); + } + + @Override + public @NotNull InventoryType.SlotType getSlotType(int slot) { + if (viewOnly) { + return InventoryType.SlotType.OUTSIDE; + } + return super.getSlotType(slot); + } + }; + } + + private int getTopSize(ServerPlayer viewer) { + MenuType menuType = getType(); + if (menuType == null) { + throw new IllegalStateException("MenuType cannot be null!"); + } else if (menuType == MenuType.GENERIC_9x1) { + return 9; + } else if (menuType == MenuType.GENERIC_9x2) { + return 18; + } else if (menuType == MenuType.GENERIC_9x3) { + return 27; + } else if (menuType == MenuType.GENERIC_9x4) { + return 36; + } else if (menuType == MenuType.GENERIC_9x5) { + return 45; + } else if (menuType == MenuType.GENERIC_9x6) { + return 54; + } + // This is a bit gross, but allows us a safe fallthrough. + return menuType.create(-1, viewer.getInventory()).slots.size() - BOTTOM_INVENTORY_SIZE; } /** @@ -152,19 +284,21 @@ public void clicked(int i, int j, ClickType clickType, Player player) { super.clicked(i, j, clickType, player); } + @Override + public boolean stillValid(Player player) { + return true; + } + + // Overrides from here on are purely to modify the sync process to send placeholder items. @Override protected Slot addSlot(Slot slot) { slot.index = this.slots.size(); - if (viewOnly && !(slot instanceof SlotViewOnly)) { - slot = SlotViewOnly.wrap(slot); - } this.slots.add(slot); this.lastSlots.add(ItemStack.EMPTY); this.remoteSlots.add(ItemStack.EMPTY); return slot; } - // Overrides from here on are purely to modify the sync process to send placeholder items. @Override protected DataSlot addDataSlot(DataSlot dataSlot) { this.dataSlots.add(dataSlot); diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenEnderChestMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenEnderChestMenu.java new file mode 100644 index 00000000..2f65b8af --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenEnderChestMenu.java @@ -0,0 +1,55 @@ +package com.lishid.openinv.internal.v1_21_R1.container.menu; + +import com.lishid.openinv.internal.v1_21_R1.container.OpenEnderChest; +import com.lishid.openinv.util.Permissions; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +public class OpenEnderChestMenu extends OpenChestMenu { + + public OpenEnderChestMenu(OpenEnderChest enderChest, ServerPlayer viewer, int containerId) { + super(getChestMenuType(enderChest.getContainerSize()), containerId, enderChest, viewer); + } + + @Override + protected boolean checkViewOnly() { + return !(ownContainer ? Permissions.ENDERCHEST_EDIT_SELF : Permissions.ENDERCHEST_OPEN_OTHER) + .hasPermission(viewer.getBukkitEntity()); + } + + @Override + public ItemStack quickMoveStack(Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + + // 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; + } + +} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventoryMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java similarity index 50% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventoryMenu.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java index 15bc17a8..c80af6e2 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/OpenInventoryMenu.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/container/menu/OpenInventoryMenu.java @@ -1,5 +1,8 @@ -package com.lishid.openinv.internal.v1_21_R1.container; +package com.lishid.openinv.internal.v1_21_R1.container.menu; +import com.lishid.openinv.internal.v1_21_R1.container.OpenInventory; +import com.lishid.openinv.internal.v1_21_R1.container.bukkit.OpenDummyInventory; +import com.lishid.openinv.internal.v1_21_R1.container.bukkit.OpenPlayerInventorySelf; import com.lishid.openinv.internal.v1_21_R1.container.slot.ContentDrop; import com.lishid.openinv.internal.v1_21_R1.container.slot.ContentEquipment; import com.lishid.openinv.internal.v1_21_R1.container.slot.SlotViewOnly; @@ -7,6 +10,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; @@ -18,81 +22,36 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class OpenInventoryMenu extends OpenContainerMenu { +public class OpenInventoryMenu extends OpenChestMenu { - private final OpenInventory inventory; - private final int topSize; - private final int offset; - private CraftInventoryView bukkitEntity; + private int offset; - protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) { - super(getMenuType(inventory, viewer), i, inventory.getOwnerHandle(), viewer); - this.inventory = inventory; - - int upperRows; - if (ownContainer) { - // Disallow duplicate access to own main inventory contents. - offset = viewer.getInventory().items.size(); - upperRows = ((int) Math.ceil((inventory.getContainerSize() - offset) / 9.0)); - } else { - offset = 0; - upperRows = inventory.getContainerSize() / 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 = offset + row * 9 + col; - - // Guard against weird inventory sizes. - if (index >= inventory.getContainerSize()) { - addSlot(new SlotViewOnly(inventory, index, x, y)); - continue; - } - - Slot slot = getUpperSlot(index, x, y); - - addSlot(slot); - } - } - - // 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)); - } - - this.topSize = slots.size() - 36; + public OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) { + super(getMenuType(inventory, viewer), i, inventory, viewer); } - private static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { + private static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { int size = inventory.getContainerSize(); + // Disallow duplicate access to own main inventory contents. if (inventory.getOwnerHandle().equals(viewer)) { size -= viewer.getInventory().items.size(); size = ((int) Math.ceil(size / 9.0)) * 9; } - return OpenContainerMenu.getContainers(size); + return getChestMenuType(size); } - private Slot getUpperSlot(int index, int x, int y) { - Slot slot = inventory.getMenuSlot(index, x, y); + @Override + protected void preSlotSetup() { + offset = ownContainer ? viewer.getInventory().items.size() : 0; + } - // If the slot is cannot be interacted with there's nothing to configure. + @Override + protected @NotNull Slot getUpperSlot(int index, int x, int y) { + index += offset; + Slot slot = container.getMenuSlot(index, x, y); + + // If the slot cannot be interacted with there's nothing to configure. if (slot.getClass().equals(SlotViewOnly.class)) { return slot; } @@ -100,7 +59,7 @@ private Slot getUpperSlot(int index, int x, int y) { // Remove drop slot if viewer is not allowed to use it. if (slot instanceof ContentDrop.SlotDrop && (viewOnly || !Permissions.INVENTORY_SLOT_DROP.hasPermission(viewer.getBukkitEntity()))) { - return new SlotViewOnly(inventory, index, x, y); + return new SlotViewOnly(container, index, x, y); } if (slot instanceof ContentEquipment.SlotEquipment equipment) { @@ -119,7 +78,7 @@ private Slot getUpperSlot(int index, int x, int y) { // 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.onlyEquipmentFor(container.getOwnerHandle()); } // Equipment slots are a core part of the inventory, so they will always be shown. @@ -128,7 +87,7 @@ private Slot getUpperSlot(int index, int x, int y) { // When viewing own inventory, only allow access to equipment and drop slots (equipment allowed above). if (ownContainer && !(slot instanceof ContentDrop.SlotDrop)) { - return new SlotViewOnly(inventory, index, x, y); + return new SlotViewOnly(container, index, x, y); } if (viewOnly) { @@ -145,91 +104,92 @@ protected boolean checkViewOnly() { } @Override - public CraftInventoryView getBukkitView() { - if (bukkitEntity == null) { - org.bukkit.inventory.Inventory bukkitInventory; - if (viewOnly) { - bukkitInventory = new OpenViewInventory(inventory); - } else if (ownContainer) { - bukkitInventory = new OpenPlayerInventorySelf(inventory, offset); - } else { - bukkitInventory = inventory.getBukkitInventory(); + protected @NotNull CraftInventoryView createBukkitEntity() { + org.bukkit.inventory.Inventory bukkitInventory; + if (viewOnly) { + bukkitInventory = new OpenDummyInventory(container); + } else if (ownContainer) { + bukkitInventory = new OpenPlayerInventorySelf(container, offset); + } else { + bukkitInventory = container.getBukkitInventory(); + } + + return new CraftInventoryView(viewer.getBukkitEntity(), bukkitInventory, this) { + @Override + public org.bukkit.inventory.ItemStack getItem(int index) { + if (viewOnly || index < 0) { + return null; + } + + Slot slot = slots.get(index); + return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); } - bukkitEntity = new CraftInventoryView(viewer.getBukkitEntity(), bukkitInventory, this) { - @Override - public org.bukkit.inventory.ItemStack getItem(int index) { - if (viewOnly || index < 0) { - return null; - } + @Override + public boolean isInTop(int rawSlot) { + return rawSlot < topSize; + } - Slot slot = slots.get(index); - return CraftItemStack.asCraftMirror(slot.hasItem() ? slot.getItem() : ItemStack.EMPTY); + @Override + public @Nullable Inventory getInventory(int rawSlot) { + if (viewOnly) { + return null; } - - @Override - public boolean isInTop(int rawSlot) { - return rawSlot < topSize; + if (rawSlot < 0) { + return super.getInventory(rawSlot); + } + if (rawSlot > topSize) { + return super.getInventory(offset + rawSlot); + } + Slot slot = slots.get(rawSlot); + if (slot.isFake()) { + return null; } + return getTopInventory(); + } - @Override - public @Nullable Inventory getInventory(int rawSlot) { - if (viewOnly) { - return null; - } - if (rawSlot < 0) { - return super.getInventory(rawSlot); - } - if (rawSlot > topSize) { - return super.getInventory(offset + rawSlot); - } + @Override + public int convertSlot(int rawSlot) { + if (viewOnly) { + return InventoryView.OUTSIDE; + } + if (rawSlot < 0) { + return rawSlot; + } + if (rawSlot < topSize) { Slot slot = slots.get(rawSlot); if (slot.isFake()) { - return null; - } - return getTopInventory(); - } - - @Override - public int convertSlot(int rawSlot) { - if (viewOnly) { return InventoryView.OUTSIDE; } - if (rawSlot < 0) { - return rawSlot; - } - if (rawSlot < topSize) { - Slot slot = slots.get(rawSlot); - if (slot.isFake()) { - return InventoryView.OUTSIDE; - } - return rawSlot; - } - return super.convertSlot(offset + rawSlot); + return rawSlot; } + return super.convertSlot(offset + rawSlot); + } - @Override - public @NotNull InventoryType.SlotType getSlotType(int slot) { - if (viewOnly || slot < 0) { - return InventoryType.SlotType.OUTSIDE; - } - if (slot >= topSize) { - return super.getSlotType(offset + slot); - } - return inventory.getSlotType(offset + slot); + @Override + public @NotNull InventoryType.SlotType getSlotType(int slot) { + if (viewOnly || slot < 0) { + return InventoryType.SlotType.OUTSIDE; } - - @Override - public int countSlots() { - return topSize + getBottomInventory().getSize(); + if (slot >= topSize) { + return super.getSlotType(offset + slot); } - }; - } - return bukkitEntity; + return container.getSlotType(offset + slot); + } + + @Override + public int countSlots() { + return topSize + getBottomInventory().getSize(); + } + }; } @Override public ItemStack quickMoveStack(Player player, int index) { + if (viewOnly) { + return ItemStack.EMPTY; + } + // See ChestMenu and InventoryMenu Slot slot = this.slots.get(index); @@ -251,7 +211,7 @@ public ItemStack quickMoveStack(Player player, int index) { // If this is gear, try to move it to the correct slot first. case OFFHAND, FEET, LEGS, CHEST, HEAD -> { // Locate the correct slot in the contents following the main inventory. - for (int extra = inventory.getOwnerHandle().getInventory().items.size() - offset; extra < topSize; ++extra) { + for (int extra = container.getOwnerHandle().getInventory().items.size() - offset; extra < topSize; ++extra) { Slot extraSlot = getSlot(extra); if (extraSlot instanceof ContentEquipment.SlotEquipment equipSlot && equipSlot.getEquipmentSlot() == equipmentSlot) { @@ -274,7 +234,7 @@ public ItemStack quickMoveStack(Player player, int index) { } } else { // If we didn't move to a gear slot, try to move to a main inventory slot. - if (!movedGear && !this.moveItemStackTo(itemStack, 0, inventory.getOwnerHandle().getInventory().items.size(), true)) { + if (!movedGear && !this.moveItemStackTo(itemStack, 0, container.getOwnerHandle().getInventory().items.size(), true)) { return ItemStack.EMPTY; } } @@ -289,14 +249,4 @@ public ItemStack quickMoveStack(Player player, int index) { return originalStack; } - @Override - public boolean stillValid(Player player) { - return true; - } - - @Override - public boolean canDragTo(Slot slot) { - return !(slot instanceof ContentDrop.SlotDrop || slot instanceof SlotViewOnly); - } - } diff --git a/plugin/src/main/java/com/lishid/openinv/InventoryListener.java b/plugin/src/main/java/com/lishid/openinv/InventoryListener.java index 390277b2..1a0b29d9 100644 --- a/plugin/src/main/java/com/lishid/openinv/InventoryListener.java +++ b/plugin/src/main/java/com/lishid/openinv/InventoryListener.java @@ -17,9 +17,8 @@ package com.lishid.openinv; import com.google.errorprone.annotations.Keep; -import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.ViewOnly; import com.lishid.openinv.util.InventoryAccess; import com.lishid.openinv.util.Permissions; import org.bukkit.GameMode; @@ -36,8 +35,6 @@ import org.bukkit.inventory.InventoryHolder; import org.jetbrains.annotations.NotNull; -import java.util.Objects; - /** * Listener for inventory-related events to prevent modification of inventories where not allowed. * @@ -100,34 +97,8 @@ private void handleInventoryInteract(@NotNull final InventoryInteractEvent event } Inventory inventory = event.getView().getTopInventory(); - ISpecialInventory backing = InventoryAccess.getInventory(inventory); - - // Not a special inventory. - if (backing == null) { - return; - } - - Permissions editSelf; - Permissions editOther; - if (backing instanceof ISpecialEnderChest) { - editSelf = Permissions.ENDERCHEST_EDIT_SELF; - editOther = Permissions.ENDERCHEST_EDIT_OTHER; - } else if (backing instanceof ISpecialPlayerInventory) { - editSelf = Permissions.INVENTORY_EDIT_SELF; - editOther = Permissions.INVENTORY_EDIT_OTHER; - } else { - // Unknown implementation. - return; - } - - if (Objects.equals(entity, backing.getPlayer())) { - if (!editSelf.hasPermission(entity)) { - event.setCancelled(true); - } - } else { - if (!editOther.hasPermission(entity)) { - event.setCancelled(true); - } + if (inventory instanceof ViewOnly) { + event.setCancelled(true); } }