diff --git a/api/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java b/api/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java index 9c53d825..99026bc3 100644 --- a/api/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java +++ b/api/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java @@ -95,7 +95,7 @@ default boolean isAnyContainerNeeded(@NotNull Block block) { } BlockData blockData = block.getBlockData(); - if (!(blockData instanceof Chest chest) || ((Chest) blockData).getType() == Chest.Type.SINGLE) { + if (!(blockData instanceof Chest chest) || chest.getType() == Chest.Type.SINGLE) { return false; } diff --git a/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/AnySilentContainer.java b/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/AnySilentContainer.java index 418abf35..eb6d8fef 100644 --- a/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/AnySilentContainer.java +++ b/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/AnySilentContainer.java @@ -21,12 +21,10 @@ import com.lishid.openinv.util.ReflectionHelper; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.MenuProvider; import net.minecraft.world.SimpleMenuProvider; -import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.inventory.ChestMenu; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.PlayerEnderChestContainer; @@ -39,15 +37,10 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.EnderChestBlockEntity; import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.Statistic; -import org.bukkit.block.ShulkerBox; -import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -79,37 +72,6 @@ public AnySilentContainer() { } } - @Override - public boolean isShulkerBlocked(@NotNull ShulkerBox shulkerBox) { - org.bukkit.World bukkitWorld = shulkerBox.getWorld(); - if (!(bukkitWorld instanceof CraftWorld)) { - bukkitWorld = Bukkit.getWorld(bukkitWorld.getUID()); - } - - if (!(bukkitWorld instanceof CraftWorld craftWorld)) { - Exception exception = new IllegalStateException("AnySilentContainer access attempted on an unknown world!"); - OpenInv.getPlugin(OpenInv.class).getLogger().log(java.util.logging.Level.WARNING, exception.getMessage(), exception); - return false; - } - - final ServerLevel world = craftWorld.getHandle(); - final BlockPos blockPosition = new BlockPos(shulkerBox.getX(), shulkerBox.getY(), shulkerBox.getZ()); - final BlockEntity tile = world.getBlockEntity(blockPosition); - - if (!(tile instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity) - || shulkerBoxBlockEntity.getAnimationStatus() != ShulkerBoxBlockEntity.AnimationStatus.CLOSED) { - return false; - } - - BlockState blockState = world.getBlockState(blockPosition); - - // See net.minecraft.world.level.block.ShulkerBoxBlock#canOpen - AABB boundingBox = Shulker.getProgressDeltaAabb(blockState.getValue(ShulkerBoxBlock.FACING), 0.0F, 0.5F) - .move(blockPosition) - .deflate(1.0E-6D); - return !world.noCollision(boundingBox); - } - @Override public boolean activateContainer( @NotNull final Player bukkitPlayer, diff --git a/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/PlayerDataManager.java b/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/PlayerDataManager.java index 9d02c87b..bee0f2ea 100644 --- a/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/PlayerDataManager.java +++ b/internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/PlayerDataManager.java @@ -19,6 +19,7 @@ import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InventoryViewTitle; import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; import com.mojang.serialization.Dynamic; @@ -250,12 +251,13 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException { return null; } - InventoryView view = getView(player, inventory); + InventoryViewTitle title = InventoryViewTitle.of(inventory); - if (view == null) { + if (title == null) { return player.openInventory(inventory.getBukkitInventory()); } + InventoryView view = new OpenInventoryView(player, inventory, title.getTitle(player, inventory)); AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) { @Override public MenuType getType() { @@ -263,7 +265,7 @@ public MenuType getType() { } }; - container.setTitle(Component.literal(view.getTitle())); + container.setTitle(Component.literal(view.getOriginalTitle())); container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); if (container == null) { @@ -279,16 +281,6 @@ public MenuType getType() { } - private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) { - if (inventory instanceof SpecialEnderChest) { - return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest"); - } else if (inventory instanceof SpecialPlayerInventory) { - return new OpenInventoryView(player, inventory, "container.player", "'s Inventory"); - } else { - return null; - } - } - static @NotNull MenuType getContainers(int inventorySize) { return switch (inventorySize) { diff --git a/internal/v1_20_R4/src/main/java/com/lishid/openinv/internal/v1_20_R4/PlayerDataManager.java b/internal/v1_20_R4/src/main/java/com/lishid/openinv/internal/v1_20_R4/PlayerDataManager.java index d058c5b8..1e906f9d 100644 --- a/internal/v1_20_R4/src/main/java/com/lishid/openinv/internal/v1_20_R4/PlayerDataManager.java +++ b/internal/v1_20_R4/src/main/java/com/lishid/openinv/internal/v1_20_R4/PlayerDataManager.java @@ -19,6 +19,7 @@ import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InventoryViewTitle; import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; import com.mojang.serialization.Dynamic; @@ -250,12 +251,13 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException { return null; } - InventoryView view = getView(player, inventory); + InventoryViewTitle title = InventoryViewTitle.of(inventory); - if (view == null) { + if (title == null) { return player.openInventory(inventory.getBukkitInventory()); } + InventoryView view = new OpenInventoryView(player, inventory, title.getTitle(player, inventory)); AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) { @Override public MenuType getType() { @@ -263,7 +265,7 @@ public MenuType getType() { } }; - container.setTitle(Component.literal(view.getTitle())); + container.setTitle(Component.literal(view.getOriginalTitle())); container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); if (container == null) { @@ -279,16 +281,6 @@ public MenuType getType() { } - private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) { - if (inventory instanceof SpecialEnderChest) { - return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest"); - } else if (inventory instanceof SpecialPlayerInventory) { - return new OpenInventoryView(player, inventory, "container.player", "'s Inventory"); - } else { - return null; - } - } - static @NotNull MenuType getContainers(int inventorySize) { return switch (inventorySize) { 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 new file mode 100644 index 00000000..d2a003ed --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/OpenCraftView.java @@ -0,0 +1,59 @@ +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/PlayerDataManager.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java index a66f3ddf..7709679e 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java @@ -16,9 +16,11 @@ package com.lishid.openinv.internal.v1_21_R1; +import com.github.jikoo.planarwrappers.function.TriFunction; import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; +import com.lishid.openinv.internal.InventoryViewTitle; import com.lishid.openinv.internal.OpenInventoryView; import com.mojang.authlib.GameProfile; import com.mojang.serialization.Dynamic; @@ -58,6 +60,7 @@ public class PlayerDataManager implements IPlayerDataManager { private static boolean paper; + private static TriFunction viewProvider; static { try { @@ -66,6 +69,12 @@ public class PlayerDataManager implements IPlayerDataManager { } catch (ClassNotFoundException ignored) { paper = false; } + try { + Class.forName(Bukkit.getServer().getClass().getPackageName() + ".inventory.CraftAbstractInventoryView"); + viewProvider = OpenCraftView::new; + } catch (ClassNotFoundException ignored) { + viewProvider = OpenInventoryView::new; + } } private @Nullable Field bukkitEntity; @@ -250,28 +259,33 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException { return null; } - InventoryView view = getView(player, inventory); + InventoryViewTitle viewTitle = InventoryViewTitle.of(inventory); - if (view == null) { + if (viewTitle == null) { return player.openInventory(inventory.getBukkitInventory()); } + String originalTitle = viewTitle.getTitle(player, inventory); + InventoryView view = viewProvider.apply(player, inventory, originalTitle); + Component title = Component.literal(originalTitle); AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) { @Override public MenuType getType() { return getContainers(inventory.getBukkitInventory().getSize()); } }; + container.setTitle(title); - container.setTitle(Component.literal(view.getTitle())); container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); if (container == null) { return null; } - nmsPlayer.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), - Component.literal(container.getBukkitView().getTitle()))); + // 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. + nmsPlayer.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title)); nmsPlayer.containerMenu = container; nmsPlayer.initMenu(container); @@ -279,23 +293,13 @@ public MenuType getType() { } - private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) { - if (inventory instanceof SpecialEnderChest) { - return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest"); - } else if (inventory instanceof SpecialPlayerInventory) { - return new OpenInventoryView(player, inventory, "container.player", "'s Inventory"); - } else { - return null; - } - } - static @NotNull MenuType getContainers(int inventorySize) { return switch (inventorySize) { case 9 -> MenuType.GENERIC_9x1; case 18 -> MenuType.GENERIC_9x2; - case 36 -> MenuType.GENERIC_9x4; // PLAYER - case 41, 45 -> MenuType.GENERIC_9x5; + case 36 -> MenuType.GENERIC_9x4; + case 41, 45 -> MenuType.GENERIC_9x5; // PLAYER case 54 -> MenuType.GENERIC_9x6; default -> MenuType.GENERIC_9x3; // Default 27-slot inventory }; diff --git a/plugin/src/main/java/com/lishid/openinv/internal/InventoryViewTitle.java b/plugin/src/main/java/com/lishid/openinv/internal/InventoryViewTitle.java new file mode 100644 index 00000000..7bff29a1 --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/internal/InventoryViewTitle.java @@ -0,0 +1,46 @@ +package com.lishid.openinv.internal; + +import com.lishid.openinv.OpenInv; +import com.lishid.openinv.util.lang.Replacement; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public enum InventoryViewTitle { + + PLAYER_INVENTORY("container.player", "'s Inventory"), + ENDER_CHEST("container.enderchest", "'s Ender Chest"); + + private final String localizationKey; + private final String defaultSuffix; + + InventoryViewTitle(String localizationKey, String defaultSuffix) { + this.localizationKey = localizationKey; + this.defaultSuffix = defaultSuffix; + } + + public @NotNull String getTitle(@NotNull Player viewer, @NotNull ISpecialInventory inventory) { + HumanEntity owner = inventory.getPlayer(); + + String localTitle = OpenInv.getPlugin(OpenInv.class) + .getLocalizedMessage( + viewer, + localizationKey, + new Replacement("%player%", owner.getName())); + return Objects.requireNonNullElseGet(localTitle, () -> owner.getName() + defaultSuffix); + } + + public static @Nullable InventoryViewTitle of(@NotNull ISpecialInventory inventory) { + if (inventory instanceof ISpecialPlayerInventory) { + return PLAYER_INVENTORY; + } else if (inventory instanceof ISpecialEnderChest) { + return ENDER_CHEST; + } else { + return null; + } + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java b/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java index c5743a77..618cdc01 100644 --- a/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java +++ b/plugin/src/main/java/com/lishid/openinv/internal/OpenInventoryView.java @@ -16,8 +16,6 @@ package com.lishid.openinv.internal; -import com.lishid.openinv.OpenInv; -import com.lishid.openinv.util.lang.Replacement; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; @@ -25,25 +23,20 @@ import org.bukkit.inventory.InventoryView; import org.jetbrains.annotations.NotNull; -import java.util.Objects; - public class OpenInventoryView extends InventoryView { private final @NotNull Player player; private final @NotNull ISpecialInventory inventory; - private final @NotNull String titleKey; - private final @NotNull String titleDefaultSuffix; + private final @NotNull String originalTitle; private String title; public OpenInventoryView( @NotNull Player player, @NotNull ISpecialInventory inventory, - @NotNull String titleKey, - @NotNull String titleDefaultSuffix) { + @NotNull String originalTitle) { this.player = player; this.inventory = inventory; - this.titleKey = titleKey; - this.titleDefaultSuffix = titleDefaultSuffix; + this.originalTitle = originalTitle; } @Override @@ -68,24 +61,12 @@ public OpenInventoryView( @Override public @NotNull String getTitle() { - if (title == null) { - title = getOriginalTitle(); - } - - return title; + return title == null ? originalTitle : title; } - @NotNull @Override - public String getOriginalTitle() { - HumanEntity owner = inventory.getPlayer(); - - String localTitle = OpenInv.getPlugin(OpenInv.class) - .getLocalizedMessage( - player, - titleKey, - new Replacement("%player%", owner.getName())); - return Objects.requireNonNullElseGet(localTitle, () -> owner.getName() + titleDefaultSuffix); + public @NotNull String getOriginalTitle() { + return originalTitle; } @Override