Skip to content

Commit e97ac3d

Browse files
authored
Fix inventory view construction on 1.21 (#208)
1 parent f72b674 commit e97ac3d

8 files changed

Lines changed: 143 additions & 107 deletions

File tree

api/src/main/java/com/lishid/openinv/internal/IAnySilentContainer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ default boolean isAnyContainerNeeded(@NotNull Block block) {
9595
}
9696

9797
BlockData blockData = block.getBlockData();
98-
if (!(blockData instanceof Chest chest) || ((Chest) blockData).getType() == Chest.Type.SINGLE) {
98+
if (!(blockData instanceof Chest chest) || chest.getType() == Chest.Type.SINGLE) {
9999
return false;
100100
}
101101

internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/AnySilentContainer.java

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,10 @@
2121
import com.lishid.openinv.util.ReflectionHelper;
2222
import net.minecraft.core.BlockPos;
2323
import net.minecraft.network.chat.Component;
24-
import net.minecraft.server.level.ServerLevel;
2524
import net.minecraft.server.level.ServerPlayer;
2625
import net.minecraft.server.level.ServerPlayerGameMode;
2726
import net.minecraft.world.MenuProvider;
2827
import net.minecraft.world.SimpleMenuProvider;
29-
import net.minecraft.world.entity.monster.Shulker;
3028
import net.minecraft.world.inventory.ChestMenu;
3129
import net.minecraft.world.inventory.MenuType;
3230
import net.minecraft.world.inventory.PlayerEnderChestContainer;
@@ -39,15 +37,10 @@
3937
import net.minecraft.world.level.block.entity.BlockEntity;
4038
import net.minecraft.world.level.block.entity.EnderChestBlockEntity;
4139
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
42-
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
4340
import net.minecraft.world.level.block.state.BlockState;
44-
import net.minecraft.world.phys.AABB;
45-
import org.bukkit.Bukkit;
4641
import org.bukkit.GameMode;
4742
import org.bukkit.Material;
4843
import org.bukkit.Statistic;
49-
import org.bukkit.block.ShulkerBox;
50-
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
5144
import org.bukkit.entity.Player;
5245
import org.jetbrains.annotations.NotNull;
5346
import org.jetbrains.annotations.Nullable;
@@ -79,37 +72,6 @@ public AnySilentContainer() {
7972
}
8073
}
8174

82-
@Override
83-
public boolean isShulkerBlocked(@NotNull ShulkerBox shulkerBox) {
84-
org.bukkit.World bukkitWorld = shulkerBox.getWorld();
85-
if (!(bukkitWorld instanceof CraftWorld)) {
86-
bukkitWorld = Bukkit.getWorld(bukkitWorld.getUID());
87-
}
88-
89-
if (!(bukkitWorld instanceof CraftWorld craftWorld)) {
90-
Exception exception = new IllegalStateException("AnySilentContainer access attempted on an unknown world!");
91-
OpenInv.getPlugin(OpenInv.class).getLogger().log(java.util.logging.Level.WARNING, exception.getMessage(), exception);
92-
return false;
93-
}
94-
95-
final ServerLevel world = craftWorld.getHandle();
96-
final BlockPos blockPosition = new BlockPos(shulkerBox.getX(), shulkerBox.getY(), shulkerBox.getZ());
97-
final BlockEntity tile = world.getBlockEntity(blockPosition);
98-
99-
if (!(tile instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity)
100-
|| shulkerBoxBlockEntity.getAnimationStatus() != ShulkerBoxBlockEntity.AnimationStatus.CLOSED) {
101-
return false;
102-
}
103-
104-
BlockState blockState = world.getBlockState(blockPosition);
105-
106-
// See net.minecraft.world.level.block.ShulkerBoxBlock#canOpen
107-
AABB boundingBox = Shulker.getProgressDeltaAabb(blockState.getValue(ShulkerBoxBlock.FACING), 0.0F, 0.5F)
108-
.move(blockPosition)
109-
.deflate(1.0E-6D);
110-
return !world.noCollision(boundingBox);
111-
}
112-
11375
@Override
11476
public boolean activateContainer(
11577
@NotNull final Player bukkitPlayer,

internal/v1_20_R3/src/main/java/com/lishid/openinv/internal/v1_20_R3/PlayerDataManager.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.lishid.openinv.OpenInv;
2020
import com.lishid.openinv.internal.IPlayerDataManager;
2121
import com.lishid.openinv.internal.ISpecialInventory;
22+
import com.lishid.openinv.internal.InventoryViewTitle;
2223
import com.lishid.openinv.internal.OpenInventoryView;
2324
import com.mojang.authlib.GameProfile;
2425
import com.mojang.serialization.Dynamic;
@@ -250,20 +251,21 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException {
250251
return null;
251252
}
252253

253-
InventoryView view = getView(player, inventory);
254+
InventoryViewTitle title = InventoryViewTitle.of(inventory);
254255

255-
if (view == null) {
256+
if (title == null) {
256257
return player.openInventory(inventory.getBukkitInventory());
257258
}
258259

260+
InventoryView view = new OpenInventoryView(player, inventory, title.getTitle(player, inventory));
259261
AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) {
260262
@Override
261263
public MenuType<?> getType() {
262264
return getContainers(inventory.getBukkitInventory().getSize());
263265
}
264266
};
265267

266-
container.setTitle(Component.literal(view.getTitle()));
268+
container.setTitle(Component.literal(view.getOriginalTitle()));
267269
container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container);
268270

269271
if (container == null) {
@@ -279,16 +281,6 @@ public MenuType<?> getType() {
279281

280282
}
281283

282-
private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) {
283-
if (inventory instanceof SpecialEnderChest) {
284-
return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest");
285-
} else if (inventory instanceof SpecialPlayerInventory) {
286-
return new OpenInventoryView(player, inventory, "container.player", "'s Inventory");
287-
} else {
288-
return null;
289-
}
290-
}
291-
292284
static @NotNull MenuType<?> getContainers(int inventorySize) {
293285

294286
return switch (inventorySize) {

internal/v1_20_R4/src/main/java/com/lishid/openinv/internal/v1_20_R4/PlayerDataManager.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.lishid.openinv.OpenInv;
2020
import com.lishid.openinv.internal.IPlayerDataManager;
2121
import com.lishid.openinv.internal.ISpecialInventory;
22+
import com.lishid.openinv.internal.InventoryViewTitle;
2223
import com.lishid.openinv.internal.OpenInventoryView;
2324
import com.mojang.authlib.GameProfile;
2425
import com.mojang.serialization.Dynamic;
@@ -250,20 +251,21 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException {
250251
return null;
251252
}
252253

253-
InventoryView view = getView(player, inventory);
254+
InventoryViewTitle title = InventoryViewTitle.of(inventory);
254255

255-
if (view == null) {
256+
if (title == null) {
256257
return player.openInventory(inventory.getBukkitInventory());
257258
}
258259

260+
InventoryView view = new OpenInventoryView(player, inventory, title.getTitle(player, inventory));
259261
AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) {
260262
@Override
261263
public MenuType<?> getType() {
262264
return getContainers(inventory.getBukkitInventory().getSize());
263265
}
264266
};
265267

266-
container.setTitle(Component.literal(view.getTitle()));
268+
container.setTitle(Component.literal(view.getOriginalTitle()));
267269
container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container);
268270

269271
if (container == null) {
@@ -279,16 +281,6 @@ public MenuType<?> getType() {
279281

280282
}
281283

282-
private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) {
283-
if (inventory instanceof SpecialEnderChest) {
284-
return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest");
285-
} else if (inventory instanceof SpecialPlayerInventory) {
286-
return new OpenInventoryView(player, inventory, "container.player", "'s Inventory");
287-
} else {
288-
return null;
289-
}
290-
}
291-
292284
static @NotNull MenuType<?> getContainers(int inventorySize) {
293285

294286
return switch (inventorySize) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.lishid.openinv.internal.v1_21_R1;
2+
3+
import com.lishid.openinv.internal.ISpecialInventory;
4+
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftAbstractInventoryView;
5+
import org.bukkit.entity.HumanEntity;
6+
import org.bukkit.entity.Player;
7+
import org.bukkit.event.inventory.InventoryType;
8+
import org.bukkit.inventory.Inventory;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
class OpenCraftView extends CraftAbstractInventoryView {
12+
13+
private final @NotNull Player player;
14+
private final @NotNull ISpecialInventory inventory;
15+
private final @NotNull String originalTitle;
16+
private String title = null;
17+
18+
OpenCraftView(@NotNull Player player, @NotNull ISpecialInventory inventory, @NotNull String originalTitle) {
19+
this.player = player;
20+
this.inventory = inventory;
21+
this.originalTitle = originalTitle;
22+
}
23+
24+
@Override
25+
public @NotNull Inventory getTopInventory() {
26+
return inventory.getBukkitInventory();
27+
}
28+
29+
@Override
30+
public @NotNull Inventory getBottomInventory() {
31+
return player.getInventory();
32+
}
33+
34+
@Override
35+
public @NotNull HumanEntity getPlayer() {
36+
return player;
37+
}
38+
39+
@Override
40+
public @NotNull InventoryType getType() {
41+
return inventory.getBukkitInventory().getType();
42+
}
43+
44+
@Override
45+
public @NotNull String getTitle() {
46+
return title == null ? originalTitle : title;
47+
}
48+
49+
@Override
50+
public @NotNull String getOriginalTitle() {
51+
return originalTitle;
52+
}
53+
54+
@Override
55+
public void setTitle(@NotNull String title) {
56+
this.title = title;
57+
}
58+
59+
}

internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
package com.lishid.openinv.internal.v1_21_R1;
1818

19+
import com.github.jikoo.planarwrappers.function.TriFunction;
1920
import com.lishid.openinv.OpenInv;
2021
import com.lishid.openinv.internal.IPlayerDataManager;
2122
import com.lishid.openinv.internal.ISpecialInventory;
23+
import com.lishid.openinv.internal.InventoryViewTitle;
2224
import com.lishid.openinv.internal.OpenInventoryView;
2325
import com.mojang.authlib.GameProfile;
2426
import com.mojang.serialization.Dynamic;
@@ -58,6 +60,7 @@
5860
public class PlayerDataManager implements IPlayerDataManager {
5961

6062
private static boolean paper;
63+
private static TriFunction<Player, ISpecialInventory, String, InventoryView> viewProvider;
6164

6265
static {
6366
try {
@@ -66,6 +69,12 @@ public class PlayerDataManager implements IPlayerDataManager {
6669
} catch (ClassNotFoundException ignored) {
6770
paper = false;
6871
}
72+
try {
73+
Class.forName(Bukkit.getServer().getClass().getPackageName() + ".inventory.CraftAbstractInventoryView");
74+
viewProvider = OpenCraftView::new;
75+
} catch (ClassNotFoundException ignored) {
76+
viewProvider = OpenInventoryView::new;
77+
}
6978
}
7079

7180
private @Nullable Field bukkitEntity;
@@ -250,52 +259,47 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException {
250259
return null;
251260
}
252261

253-
InventoryView view = getView(player, inventory);
262+
InventoryViewTitle viewTitle = InventoryViewTitle.of(inventory);
254263

255-
if (view == null) {
264+
if (viewTitle == null) {
256265
return player.openInventory(inventory.getBukkitInventory());
257266
}
258267

268+
String originalTitle = viewTitle.getTitle(player, inventory);
269+
InventoryView view = viewProvider.apply(player, inventory, originalTitle);
270+
Component title = Component.literal(originalTitle);
259271
AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) {
260272
@Override
261273
public MenuType<?> getType() {
262274
return getContainers(inventory.getBukkitInventory().getSize());
263275
}
264276
};
277+
container.setTitle(title);
265278

266-
container.setTitle(Component.literal(view.getTitle()));
267279
container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container);
268280

269281
if (container == null) {
270282
return null;
271283
}
272284

273-
nmsPlayer.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(),
274-
Component.literal(container.getBukkitView().getTitle())));
285+
// Note: Reusing component prevents plugins from changing title during InventoryOpenEvent, but there's not much
286+
// we can do about that - we can't call InventoryView#getTitle on older versions without causing an
287+
// IncompatibleClassChangeError due to the fact that InventoryView is now an interface.
288+
nmsPlayer.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title));
275289
nmsPlayer.containerMenu = container;
276290
nmsPlayer.initMenu(container);
277291

278292
return container.getBukkitView();
279293

280294
}
281295

282-
private @Nullable InventoryView getView(Player player, ISpecialInventory inventory) {
283-
if (inventory instanceof SpecialEnderChest) {
284-
return new OpenInventoryView(player, inventory, "container.enderchest", "'s Ender Chest");
285-
} else if (inventory instanceof SpecialPlayerInventory) {
286-
return new OpenInventoryView(player, inventory, "container.player", "'s Inventory");
287-
} else {
288-
return null;
289-
}
290-
}
291-
292296
static @NotNull MenuType<?> getContainers(int inventorySize) {
293297

294298
return switch (inventorySize) {
295299
case 9 -> MenuType.GENERIC_9x1;
296300
case 18 -> MenuType.GENERIC_9x2;
297-
case 36 -> MenuType.GENERIC_9x4; // PLAYER
298-
case 41, 45 -> MenuType.GENERIC_9x5;
301+
case 36 -> MenuType.GENERIC_9x4;
302+
case 41, 45 -> MenuType.GENERIC_9x5; // PLAYER
299303
case 54 -> MenuType.GENERIC_9x6;
300304
default -> MenuType.GENERIC_9x3; // Default 27-slot inventory
301305
};
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.lishid.openinv.internal;
2+
3+
import com.lishid.openinv.OpenInv;
4+
import com.lishid.openinv.util.lang.Replacement;
5+
import org.bukkit.entity.HumanEntity;
6+
import org.bukkit.entity.Player;
7+
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
9+
10+
import java.util.Objects;
11+
12+
public enum InventoryViewTitle {
13+
14+
PLAYER_INVENTORY("container.player", "'s Inventory"),
15+
ENDER_CHEST("container.enderchest", "'s Ender Chest");
16+
17+
private final String localizationKey;
18+
private final String defaultSuffix;
19+
20+
InventoryViewTitle(String localizationKey, String defaultSuffix) {
21+
this.localizationKey = localizationKey;
22+
this.defaultSuffix = defaultSuffix;
23+
}
24+
25+
public @NotNull String getTitle(@NotNull Player viewer, @NotNull ISpecialInventory inventory) {
26+
HumanEntity owner = inventory.getPlayer();
27+
28+
String localTitle = OpenInv.getPlugin(OpenInv.class)
29+
.getLocalizedMessage(
30+
viewer,
31+
localizationKey,
32+
new Replacement("%player%", owner.getName()));
33+
return Objects.requireNonNullElseGet(localTitle, () -> owner.getName() + defaultSuffix);
34+
}
35+
36+
public static @Nullable InventoryViewTitle of(@NotNull ISpecialInventory inventory) {
37+
if (inventory instanceof ISpecialPlayerInventory) {
38+
return PLAYER_INVENTORY;
39+
} else if (inventory instanceof ISpecialEnderChest) {
40+
return ENDER_CHEST;
41+
} else {
42+
return null;
43+
}
44+
}
45+
46+
}

0 commit comments

Comments
 (0)