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/AnySilentContainer.java index 15faeff8..637c6bc4 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/AnySilentContainer.java @@ -74,6 +74,18 @@ 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, @@ -102,7 +114,7 @@ public boolean activateContainer( PlayerEnderChestContainer enderChest = player.getEnderChestInventory(); enderChest.setActiveChest(enderChestTile); player.openMenu(new SimpleMenuProvider((containerCounter, playerInventory, ignored) -> { - MenuType containers = PlayerManager.getContainers(enderChest.getContainerSize()); + MenuType containers = 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/InternalAccessor.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/InternalAccessor.java index 59f3481a..a70af0af 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,6 +5,7 @@ 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.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.util.lang.LanguageManager; @@ -27,7 +28,7 @@ public class InternalAccessor implements Accessor { public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { this.logger = logger; - manager = new PlayerManager(logger, lang); + manager = new PlayerManager(logger); anySilentContainer = new AnySilentContainer(logger, lang); } @@ -48,7 +49,7 @@ public InternalAccessor(@NotNull Logger logger, @NotNull LanguageManager lang) { @Override public @NotNull ISpecialEnderChest createEnderChest(@NotNull Player player) { - return new SpecialEnderChest(player, player.isOnline()); + return new OpenEnderChest(player); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenCraftView.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenCraftView.java deleted file mode 100644 index d2a003ed..00000000 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenCraftView.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lishid.openinv.internal.v1_21_R1; - -import com.lishid.openinv.internal.ISpecialInventory; -import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftAbstractInventoryView; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.jetbrains.annotations.NotNull; - -class OpenCraftView extends CraftAbstractInventoryView { - - private final @NotNull Player player; - private final @NotNull ISpecialInventory inventory; - private final @NotNull String originalTitle; - private String title = null; - - OpenCraftView(@NotNull Player player, @NotNull ISpecialInventory inventory, @NotNull String originalTitle) { - this.player = player; - this.inventory = inventory; - this.originalTitle = originalTitle; - } - - @Override - public @NotNull Inventory getTopInventory() { - return inventory.getBukkitInventory(); - } - - @Override - public @NotNull Inventory getBottomInventory() { - return player.getInventory(); - } - - @Override - public @NotNull HumanEntity getPlayer() { - return player; - } - - @Override - public @NotNull InventoryType getType() { - return inventory.getBukkitInventory().getType(); - } - - @Override - public @NotNull String getTitle() { - return title == null ? originalTitle : title; - } - - @Override - public @NotNull String getOriginalTitle() { - return originalTitle; - } - - @Override - public void setTitle(@NotNull String title) { - this.title = title; - } - -} 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/PlayerManager.java index 2c81a192..e40eade4 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/PlayerManager.java @@ -17,10 +17,8 @@ package com.lishid.openinv.internal.v1_21_R1; import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.InventoryViewTitle; -import com.lishid.openinv.internal.OpenInventoryView; +import com.lishid.openinv.internal.v1_21_R1.inventory.OpenEnderChest; import com.lishid.openinv.internal.v1_21_R1.inventory.OpenInventory; -import com.lishid.openinv.util.lang.LanguageManager; import com.mojang.authlib.GameProfile; import com.mojang.serialization.Dynamic; import net.minecraft.nbt.CompoundTag; @@ -31,13 +29,12 @@ import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.ChatVisiblity; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.MenuType; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; -import org.apache.commons.lang3.function.TriFunction; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.Server; @@ -46,7 +43,6 @@ import org.bukkit.craftbukkit.v1_21_R1.CraftWorld; import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_21_R1.event.CraftEventFactory; -import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftContainer; import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; @@ -59,31 +55,22 @@ public class PlayerManager implements com.lishid.openinv.internal.PlayerManager { private static boolean paper; - private static TriFunction viewProvider; - static { + static { try { Class.forName("io.papermc.paper.configuration.Configuration"); paper = true; } catch (ClassNotFoundException ignored) { paper = false; } - try { - Class.forName(Bukkit.getServer().getClass().getPackageName() + ".inventory.CraftAbstractInventoryView"); - viewProvider = OpenCraftView::new; - } catch (ClassNotFoundException ignored) { - viewProvider = OpenInventoryView::new; - } } private final @NotNull Logger logger; - private final @NotNull LanguageManager lang; private @Nullable Field bukkitEntity; - public PlayerManager(@NotNull Logger logger, @NotNull LanguageManager lang) { + public PlayerManager(@NotNull Logger logger) { this.logger = logger; - this.lang = lang; - try { + try { bukkitEntity = Entity.class.getDeclaredField("bukkitEntity"); } catch (NoSuchFieldException e) { logger.warning("Unable to obtain field to inject custom save process - certain player data may be lost when saving!"); @@ -260,76 +247,42 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException { return null; } - if (inventory instanceof OpenInventory container) { - // See net.minecraft.server.level.ServerPlayer#openMenu(MenuProvider) - AbstractContainerMenu menu = container.createMenu(player.nextContainerCounter(), player.getInventory(), player); - - // Should never happen, player is a ServerPlayer with an active connection. - if (menu == null) { - return null; - } - - // Set up title (the whole reason we're not just using Player#openInventory(Inventory)). - // Title can only be set once for a menu, and is set during the open process. - menu.setTitle(container.getTitle(player)); - - menu = CraftEventFactory.callInventoryOpenEvent(player, menu, false); - - // Menu is null if event is cancelled. - if (menu == null) { - return null; - } - - player.containerMenu = menu; - player.connection.send(new ClientboundOpenScreenPacket(menu.containerId, menu.getType(), menu.getTitle())); - player.initMenu(menu); - - return menu.getBukkitView(); + MenuProvider provider; + Component title; + if (inventory instanceof OpenInventory playerInv) { + provider = playerInv; + title = playerInv.getTitle(player); + } else if (inventory instanceof OpenEnderChest enderChest) { + provider = enderChest; + title = enderChest.getDisplayName(); + } else { + return null; } - InventoryViewTitle viewTitle = InventoryViewTitle.of(inventory); + // See net.minecraft.server.level.ServerPlayer#openMenu(MenuProvider) + AbstractContainerMenu menu = provider.createMenu(player.nextContainerCounter(), player.getInventory(), player); - if (viewTitle == null) { - return bukkitPlayer.openInventory(inventory.getBukkitInventory()); + // Should never happen, player is a ServerPlayer with an active connection. + if (menu == null) { + return null; } - String originalTitle = viewTitle.getTitle(lang, bukkitPlayer, inventory); - InventoryView view = viewProvider.apply(bukkitPlayer, inventory, originalTitle); - Component title = Component.literal(originalTitle); - AbstractContainerMenu container = new CraftContainer(view, player, player.nextContainerCounter()) { - @Override - public MenuType getType() { - return getContainers(inventory.getBukkitInventory().getSize()); - } - }; - container.setTitle(title); + // Set up title (the whole reason we're not just using Player#openInventory(Inventory)). + // Title can only be set once for a menu, and is set during the open process. + menu.setTitle(title); - container = CraftEventFactory.callInventoryOpenEvent(player, container); + menu = CraftEventFactory.callInventoryOpenEvent(player, menu, false); - if (container == null) { + // Menu is null if event is cancelled. + if (menu == null) { return null; } - // Note: Reusing component prevents plugins from changing title during InventoryOpenEvent, but there's not much - // we can do about that - we can't call InventoryView#getTitle on older versions without causing an - // IncompatibleClassChangeError due to the fact that InventoryView is now an interface. - player.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title)); - player.containerMenu = container; - player.initMenu(container); - - return container.getBukkitView(); - - } + player.containerMenu = menu; + player.connection.send(new ClientboundOpenScreenPacket(menu.containerId, menu.getType(), menu.getTitle())); + player.initMenu(menu); - 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 41, 45 -> MenuType.GENERIC_9x5; - case 54 -> MenuType.GENERIC_9x6; - default -> MenuType.GENERIC_9x3; // Default 27-slot inventory - }; + return menu.getBukkitView(); } } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/SpecialEnderChest.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/SpecialEnderChest.java deleted file mode 100644 index a7d74c49..00000000 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/SpecialEnderChest.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * 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; - -import com.lishid.openinv.internal.ISpecialEnderChest; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.ContainerListener; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.player.StackedContents; -import net.minecraft.world.inventory.PlayerEnderChestContainer; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.EnderChestBlockEntity; -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.entity.HumanEntity; -import org.bukkit.inventory.InventoryHolder; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -public class SpecialEnderChest extends PlayerEnderChestContainer implements ISpecialEnderChest { - - private final CraftInventory inventory; - private ServerPlayer owner; - private NonNullList items; - private boolean playerOnline; - - public SpecialEnderChest(final org.bukkit.entity.Player player, final Boolean online) { - super(PlayerManager.getHandle(player)); - this.inventory = new CraftInventory(this); - this.owner = PlayerManager.getHandle(player); - this.playerOnline = online; - this.items = this.owner.getEnderChestInventory().items; - } - - @Override - public @NotNull CraftInventory getBukkitInventory() { - return inventory; - } - - @Override - public void setPlayerOffline() { - this.playerOnline = false; - } - - @Override - public void setPlayerOnline(@NotNull final org.bukkit.entity.Player player) { - if (this.playerOnline) { - return; - } - - ServerPlayer offlinePlayer = this.owner; - ServerPlayer onlinePlayer = PlayerManager.getHandle(player); - - // Set owner to new player. - this.owner = onlinePlayer; - - // Set player's ender chest contents to our modified contents. - PlayerEnderChestContainer onlineEnderChest = onlinePlayer.getEnderChestInventory(); - for (int i = 0; i < onlineEnderChest.getContainerSize(); ++i) { - onlineEnderChest.setItem(i, this.items.get(i)); - } - - // Set our item array to the new inventory's array. - this.items = onlineEnderChest.items; - - // Add viewers to new inventory. - onlineEnderChest.transaction.addAll(offlinePlayer.getEnderChestInventory().transaction); - - this.playerOnline = true; - } - - @Override - public @NotNull org.bukkit.entity.Player getPlayer() { - return owner.getBukkitEntity(); - } - - @Override - public void setChanged() { - this.owner.getEnderChestInventory().setChanged(); - } - - @Override - public List getContents() { - return this.items; - } - - @Override - public void onOpen(CraftHumanEntity who) { - this.owner.getEnderChestInventory().onOpen(who); - } - - @Override - public void onClose(CraftHumanEntity who) { - this.owner.getEnderChestInventory().onClose(who); - } - - @Override - public List getViewers() { - return this.owner.getEnderChestInventory().getViewers(); - } - - @Override - public boolean stillValid(Player player) { - return true; - } - - @Override - public void setActiveChest(EnderChestBlockEntity enderChest) { - this.owner.getEnderChestInventory().setActiveChest(enderChest); - } - - @Override - public boolean isActiveChest(EnderChestBlockEntity enderChest) { - return this.owner.getEnderChestInventory().isActiveChest(enderChest); - } - - @Override - public int getMaxStackSize() { - return this.owner.getEnderChestInventory().getMaxStackSize(); - } - - @Override - public void setMaxStackSize(int i) { - this.owner.getEnderChestInventory().setMaxStackSize(i); - } - - @Override - public InventoryHolder getOwner() { - return this.owner.getEnderChestInventory().getOwner(); - } - - @Override - public @Nullable Location getLocation() { - return null; - } - - @Override - public void addListener(ContainerListener listener) { - this.owner.getEnderChestInventory().addListener(listener); - } - - @Override - public void removeListener(ContainerListener listener) { - this.owner.getEnderChestInventory().removeListener(listener); - } - - @Override - public ItemStack getItem(int i) { - return i >= 0 && i < this.items.size() ? this.items.get(i) : ItemStack.EMPTY; - } - - @Override - public ItemStack removeItem(int i, int j) { - ItemStack itemstack = ContainerHelper.removeItem(this.items, i, j); - if (!itemstack.isEmpty()) { - this.setChanged(); - } - - return itemstack; - } - - @Override - public ItemStack addItem(ItemStack itemstack) { - ItemStack localItem = itemstack.copy(); - this.moveItemToOccupiedSlotsWithSameType(localItem); - if (localItem.isEmpty()) { - return ItemStack.EMPTY; - } else { - this.moveItemToEmptySlots(localItem); - return localItem.isEmpty() ? ItemStack.EMPTY : localItem; - } - } - - @Override - public boolean canAddItem(ItemStack itemstack) { - for (ItemStack itemstack1 : this.items) { - if (itemstack1.isEmpty() || (ItemStack.isSameItemSameComponents(itemstack1, itemstack) && itemstack1.getCount() < itemstack1.getMaxStackSize())) { - return true; - } - } - - return false; - } - - private void moveItemToEmptySlots(ItemStack itemstack) { - for(int i = 0; i < this.getContainerSize(); ++i) { - ItemStack localItem = this.getItem(i); - if (localItem.isEmpty()) { - this.setItem(i, itemstack.copy()); - itemstack.setCount(0); - return; - } - } - } - - private void moveItemToOccupiedSlotsWithSameType(ItemStack itemstack) { - for(int i = 0; i < this.getContainerSize(); ++i) { - ItemStack localItem = this.getItem(i); - if (ItemStack.isSameItemSameComponents(localItem, itemstack)) { - this.moveItemsBetweenStacks(itemstack, localItem); - if (itemstack.isEmpty()) { - return; - } - } - } - } - - private void moveItemsBetweenStacks(ItemStack itemstack, ItemStack itemstack1) { - int i = Math.min(this.getMaxStackSize(), itemstack1.getMaxStackSize()); - int j = Math.min(itemstack.getCount(), i - itemstack1.getCount()); - if (j > 0) { - itemstack1.grow(j); - itemstack.shrink(j); - this.setChanged(); - } - } - - @Override - public ItemStack removeItemNoUpdate(int i) { - ItemStack itemstack = this.items.get(i); - if (itemstack.isEmpty()) { - return ItemStack.EMPTY; - } else { - this.items.set(i, ItemStack.EMPTY); - return itemstack; - } - } - - @Override - public void setItem(int i, ItemStack itemstack) { - this.items.set(i, itemstack); - if (!itemstack.isEmpty() && itemstack.getCount() > this.getMaxStackSize()) { - itemstack.setCount(this.getMaxStackSize()); - } - - this.setChanged(); - } - - @Override - public int getContainerSize() { - return this.owner.getEnderChestInventory().getContainerSize(); - } - - @Override - public boolean isEmpty() { - return this.items.stream().allMatch(ItemStack::isEmpty); - } - - @Override - public void startOpen(Player player) { - } - - @Override - public void stopOpen(Player player) { - } - - @Override - public boolean canPlaceItem(int i, ItemStack itemstack) { - return true; - } - - @Override - public void clearContent() { - this.items.clear(); - this.setChanged(); - } - - @Override - public void fillStackedContents(StackedContents stackedContents) { - for (ItemStack itemstack : this.items) { - stackedContents.accountStack(itemstack); - } - - } - - @Override - public List removeAllItems() { - List list = this.items.stream().filter(Predicate.not(ItemStack::isEmpty)).collect(Collectors.toList()); - this.clearContent(); - return list; - } - - @Override - public ItemStack removeItemType(Item item, int i) { - ItemStack itemstack = new ItemStack(item, 0); - - for(int j = this.getContainerSize() - 1; j >= 0; --j) { - ItemStack localItem = this.getItem(j); - if (localItem.getItem().equals(item)) { - int k = i - itemstack.getCount(); - ItemStack splitItem = localItem.split(k); - itemstack.grow(splitItem.getCount()); - if (itemstack.getCount() == i) { - break; - } - } - } - - if (!itemstack.isEmpty()) { - this.setChanged(); - } - - return itemstack; - } - - @Override - public String toString() { - return this.items.stream().filter((itemStack) -> !itemStack.isEmpty()).toList().toString(); - } - - @Override - public void fromTag(ListTag listTag, HolderLookup.Provider holderLookup) { - for (int i = 0; i < this.getContainerSize(); ++i) { - this.setItem(i, ItemStack.EMPTY); - } - - for (int i = 0; i < listTag.size(); ++i) { - CompoundTag compoundTag = listTag.getCompound(i); - int j = compoundTag.getByte("Slot") & 255; - if (j < this.getContainerSize()) { - this.setItem(j, ItemStack.parseOptional(holderLookup, compoundTag)); - } - } - - } - -} 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/ContainerSlot.java index 8c003095..a61b1549 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/ContainerSlot.java @@ -19,21 +19,21 @@ interface ContainerSlot { void setHolder(@NotNull ServerPlayer holder); /** - * Get the current item. May be fake for display purposes! + * Get the current item. * * @return the current item */ ItemStack get(); /** - * Remove the current item. Item removed is real. + * Remove the current item. * * @return the current item */ ItemStack remove(); /** - * Remove some of the current item. Item removed is real. + * Remove some of the current item. * * @return the current item */ 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 new file mode 100644 index 00000000..b9234690 --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenEnderChest.java @@ -0,0 +1,219 @@ +/* + * 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 net.minecraft.core.NonNullList; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; +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; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class OpenEnderChest implements Container, StackedContentsCompatible, MenuProvider, ISpecialEnderChest { + + private CraftInventory inventory; + private @NotNull ServerPlayer owner; + private NonNullList items; + private int maxStack = 64; + private final List transaction = new ArrayList<>(); + + public OpenEnderChest(@NotNull org.bukkit.entity.Player player) { + this.owner = PlayerManager.getHandle(player); + this.items = owner.getEnderChestInventory().items; + } + + @Override + public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { + if (inventory == null) { + inventory = new CraftInventory(this) { + @Override + public @NotNull InventoryType getType() { + return InventoryType.ENDER_CHEST; + } + }; + } + return inventory; + } + + @Override + public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { + owner = PlayerManager.getHandle(player); + NonNullList activeItems = owner.getEnderChestInventory().items; + + // Guard against size changing. Theoretically on Purpur all row variations still have 6 rows internally. + int max = Math.min(items.size(), activeItems.size()); + for (int index = 0; index < max; ++index) { + activeItems.set(index, items.get(index)); + } + + items = activeItems; + } + + @Override + public void setPlayerOffline() {} + + @Override + public @NotNull org.bukkit.entity.Player getPlayer() { + return owner.getBukkitEntity(); + } + + @Override + public int getContainerSize() { + return items.size(); + } + + @Override + public boolean isEmpty() { + return items.stream().allMatch(ItemStack::isEmpty); + } + + @Override + public ItemStack getItem(int index) { + return index >= 0 && index < items.size() ? items.get(index) : ItemStack.EMPTY; + } + + @Override + public ItemStack removeItem(int index, int amount) { + ItemStack itemstack = ContainerHelper.removeItem(items, index, amount); + + if (!itemstack.isEmpty()) { + setChanged(); + } + + return itemstack; + } + + @Override + public ItemStack removeItemNoUpdate(int index) { + return index >= 0 && index < items.size() ? items.set(index, ItemStack.EMPTY) : ItemStack.EMPTY; + } + + @Override + public void setItem(int index, ItemStack itemStack) { + if (index >= 0 && index < items.size()) { + items.set(index, itemStack); + } + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void setChanged() { + this.owner.getEnderChestInventory().setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return true; + } + + @Override + public List getContents() { + return items; + } + + @Override + public void onOpen(CraftHumanEntity craftHumanEntity) { + transaction.add(craftHumanEntity); + } + + @Override + public void onClose(CraftHumanEntity craftHumanEntity) { + transaction.remove(craftHumanEntity); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public org.bukkit.entity.Player getOwner() { + return getPlayer(); + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public @Nullable Location getLocation() { + return null; + } + + @Override + public void clearContent() { + items.clear(); + setChanged(); + } + + @Override + public void fillStackedContents(StackedContents stackedContents) { + for (ItemStack itemstack : items) { + stackedContents.accountStack(itemstack); + } + } + + @Override + public Component getDisplayName() { + return Component.translatableWithFallback("openinv.container.enderchest.prefix", "", owner.getName()) + .append(Component.translatable("container.enderchest")) + .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; + } + }; + } + +} 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 5bdea862..9d584eb5 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 @@ -10,7 +10,6 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; -import net.minecraft.world.Nameable; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -28,7 +27,7 @@ import java.util.ArrayList; import java.util.List; -public class OpenInventory implements Container, Nameable, MenuProvider, ISpecialPlayerInventory { +public class OpenInventory implements Container, MenuProvider, ISpecialPlayerInventory { private final List slots; private final int size; @@ -215,7 +214,8 @@ public ServerPlayer getOwnerHandle() { .withColor(ChatFormatting.WHITE))); } // Normal title: "Inventory - OwnerName" - component.append(Component.translatable("container.inventory")) + component.append(Component.translatableWithFallback("openinv.container.inventory.prefix", "", owner.getName())) + .append(Component.translatable("container.inventory")) .append(Component.translatableWithFallback("openinv.container.inventory.suffix", " - %s", owner.getName())); return component; } @@ -241,6 +241,11 @@ public void setPlayerOnline(@NotNull org.bukkit.entity.Player player) { @Override public void setPlayerOffline() {} + @Override + public boolean isInUse() { + return !transaction.isEmpty(); + } + @Override public @NotNull org.bukkit.entity.Player getPlayer() { return getOwner(); @@ -336,14 +341,9 @@ public void clearContent() { owner.containerMenu.setCarried(ItemStack.EMPTY); } - @Override - public Component getName() { - return getTitle(null); - } - @Override public Component getDisplayName() { - return getName(); + return getTitle(null); } @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 a0eef7ff..7e2e4a59 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,6 +1,7 @@ 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.util.Permissions; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; @@ -135,21 +136,13 @@ static MenuType getMenuType(OpenInventory inventory, ServerPlayer viewer) { size = ((int) Math.ceil(size / 9.0)) * 9; } - return switch (size) { - 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; - }; + return AnySilentContainer.getContainers(size); } @Override public CraftInventoryView getBukkitView() { if (bukkitEntity == null) { - bukkitEntity = new CraftInventoryView(viewer.getBukkitEntity(), new OpenPlayerInventory(inventory), this) { + bukkitEntity = new CraftInventoryView(viewer.getBukkitEntity(), inventory.getBukkitInventory(), this) { @Override public org.bukkit.inventory.ItemStack getItem(int index) { if (index < 0) {