diff --git a/paper-server/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java b/paper-server/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java new file mode 100644 index 0000000000..224d4b2cc4 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/inventory/PaperInventoryCustomHolderContainer.java @@ -0,0 +1,141 @@ +package io.papermc.paper.inventory; + +import io.papermc.paper.adventure.PaperAdventure; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.InventoryHolder; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; + +import java.util.List; + +@DefaultQualifier(NonNull.class) +public final class PaperInventoryCustomHolderContainer implements Container { + + private final InventoryHolder owner; + private final Container delegate; + private final InventoryType type; + private final String title; + private final Component adventure$title; + + public PaperInventoryCustomHolderContainer(InventoryHolder owner, Container delegate, InventoryType type) { + this.owner = owner; + this.delegate = delegate; + this.type = type; + @Nullable Component adventure$title = null; + if (delegate instanceof BaseContainerBlockEntity blockEntity) { + adventure$title = blockEntity.getCustomName() != null ? PaperAdventure.asAdventure(blockEntity.getCustomName()) : null; + } + if (adventure$title == null) { + adventure$title = type.defaultTitle(); + } + this.adventure$title = adventure$title; + this.title = LegacyComponentSerializer.legacySection().serialize(this.adventure$title); + } + + public Component title() { + return this.adventure$title; + } + + public String getTitle() { + return this.title; + } + + public InventoryType getType() { + return this.type; + } + + @Override + public int getContainerSize() { + return this.delegate.getContainerSize(); + } + + @Override + public boolean isEmpty() { + return this.delegate.isEmpty(); + } + + @Override + public ItemStack getItem(int slot) { + return this.delegate.getItem(slot); + } + + @Override + public ItemStack removeItem(int slot, int amount) { + return this.delegate.removeItem(slot, amount); + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + return this.delegate.removeItemNoUpdate(slot); + } + + @Override + public void setItem(int slot, ItemStack stack) { + this.delegate.setItem(slot, stack); + } + + @Override + public int getMaxStackSize() { + return this.delegate.getMaxStackSize(); + } + + @Override + public void setChanged() { + this.delegate.setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return this.delegate.stillValid(player); + } + + @Override + public List getContents() { + return this.delegate.getContents(); + } + + @Override + public void onOpen(CraftHumanEntity who) { + this.delegate.onOpen(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + this.delegate.onClose(who); + } + + @Override + public List getViewers() { + return this.delegate.getViewers(); + } + + @Override + public InventoryHolder getOwner() { + return this.owner; + } + + @Override + public void setMaxStackSize(int size) { + this.delegate.setMaxStackSize(size); + } + + @Override + public Location getLocation() { + return this.delegate.getLocation(); + } + + @Override + public void clearContent() { + this.delegate.clearContent(); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java index 1a2329021a..674e3a827f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -49,7 +49,7 @@ public class CraftContainer extends AbstractContainerMenu { public CraftContainer(final Inventory inventory, final Player player, int id) { this(new CraftAbstractInventoryView() { - private final String originalTitle = (inventory instanceof CraftInventoryCustom) ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).getTitle() : inventory.getType().getDefaultTitle(); + private final String originalTitle = inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom) inventory).getTitle() : inventory.getType().getDefaultTitle(); // Paper private String title = this.originalTitle; @Override @@ -75,7 +75,7 @@ public class CraftContainer extends AbstractContainerMenu { // Paper start @Override public net.kyori.adventure.text.Component title() { - return inventory instanceof CraftInventoryCustom ? ((CraftInventoryCustom.MinecraftInventory) ((CraftInventory) inventory).getInventory()).title() : net.kyori.adventure.text.Component.text(inventory.getType().getDefaultTitle()); + return inventory instanceof CraftInventoryCustom custom ? custom.title() : inventory.getType().defaultTitle(); // Paper } // Paper end @@ -214,6 +214,10 @@ public class CraftContainer extends AbstractContainerMenu { this.lastSlots = this.delegate.lastSlots; this.slots = this.delegate.slots; this.remoteSlots = this.delegate.remoteSlots; + // Paper start - copy data slots for InventoryView#set/getProperty + this.dataSlots = this.delegate.dataSlots; + this.remoteDataSlots = this.delegate.remoteDataSlots; + // Paper end } // SPIGOT-4598 - we should still delegate the shift click handler diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java index 54ce9218c1..628e0cffa6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java @@ -485,6 +485,10 @@ public class CraftInventory implements Inventory { return InventoryType.BREWING; } else if (this.inventory instanceof CraftInventoryCustom.MinecraftInventory) { return ((CraftInventoryCustom.MinecraftInventory) this.inventory).getType(); + // Paper start + } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer holderContainer) { + return holderContainer.getType(); + // Paper end } else if (this.inventory instanceof PlayerEnderChestContainer) { return InventoryType.ENDER_CHEST; } else if (this.inventory instanceof MerchantContainer) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java index fc0e121202..da1c1fe0fa 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java @@ -15,6 +15,11 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.InventoryHolder; public class CraftInventoryCustom extends CraftInventory { + // Paper start + public CraftInventoryCustom(InventoryHolder owner, InventoryType type, Container delegate) { + super(new io.papermc.paper.inventory.PaperInventoryCustomHolderContainer(owner, delegate, type)); + } + // Paper end public CraftInventoryCustom(InventoryHolder owner, InventoryType type) { super(new MinecraftInventory(owner, type)); } @@ -42,6 +47,27 @@ public class CraftInventoryCustom extends CraftInventory { public CraftInventoryCustom(InventoryHolder owner, int size, String title) { super(new MinecraftInventory(owner, size, title)); } + // Paper start + public String getTitle() { + if (this.inventory instanceof MinecraftInventory minecraftInventory) { + return minecraftInventory.getTitle(); + } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer customHolderContainer) { + return customHolderContainer.getTitle(); + } else { + throw new UnsupportedOperationException(this.inventory.getClass() + " isn't a recognized Container type here"); + } + } + + public net.kyori.adventure.text.Component title() { + if (this.inventory instanceof MinecraftInventory minecraftInventory) { + return minecraftInventory.title(); + } else if (this.inventory instanceof io.papermc.paper.inventory.PaperInventoryCustomHolderContainer customHolderContainer) { + return customHolderContainer.title(); + } else { + throw new UnsupportedOperationException(this.inventory.getClass() + " isn't a recognized Container type here"); + } + } + // Paper end static class MinecraftInventory implements Container { private final NonNullList items; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java index 7bc082d08a..a6c758c5c5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/util/CraftTileInventoryConverter.java @@ -28,7 +28,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat @Override public Inventory createInventory(InventoryHolder holder, InventoryType type) { - return this.getInventory(this.getTileEntity()); + return this.getInventory(holder, type, this.getTileEntity()); // Paper } // Paper start @@ -39,7 +39,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat ((RandomizableContainerBlockEntity) te).name = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); } - return getInventory(te); + return this.getInventory(owner, type, te); // Paper } // Paper end @@ -50,10 +50,18 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat ((RandomizableContainerBlockEntity) te).name = CraftChatMessage.fromStringOrNull(title); } - return this.getInventory(te); + return this.getInventory(holder, type, te); // Paper } + @Deprecated // Paper - use getInventory with owner and type public Inventory getInventory(Container tileEntity) { + // Paper start + return this.getInventory(null, null, tileEntity); + } + + public Inventory getInventory(InventoryHolder owner, InventoryType type, Container tileEntity) { // Paper + if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper + // Paper end return new CraftInventory(tileEntity); } @@ -69,8 +77,8 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat @Override public Inventory createInventory(InventoryHolder owner, InventoryType type, net.kyori.adventure.text.Component title) { Container tileEntity = getTileEntity(); - ((AbstractFurnaceBlockEntity) tileEntity).setCustomName(io.papermc.paper.adventure.PaperAdventure.asVanilla(title)); - return getInventory(tileEntity); + ((AbstractFurnaceBlockEntity) tileEntity).name = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); + return this.getInventory(owner, type, tileEntity); // Paper } // Paper end @@ -78,11 +86,19 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat public Inventory createInventory(InventoryHolder owner, InventoryType type, String title) { Container tileEntity = this.getTileEntity(); ((AbstractFurnaceBlockEntity) tileEntity).name = CraftChatMessage.fromStringOrNull(title); - return this.getInventory(tileEntity); + return this.getInventory(owner, type, tileEntity); // Paper } @Override public Inventory getInventory(Container tileEntity) { + // Paper start + return getInventory(null, null, tileEntity); + } + + @Override + public Inventory getInventory(InventoryHolder owner, InventoryType type, net.minecraft.world.Container tileEntity) { // Paper + if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper + // Paper end return new CraftInventoryFurnace((AbstractFurnaceBlockEntity) tileEntity); } } @@ -102,7 +118,7 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat if (tileEntity instanceof BrewingStandBlockEntity) { ((BrewingStandBlockEntity) tileEntity).name = io.papermc.paper.adventure.PaperAdventure.asVanilla(title); } - return getInventory(tileEntity); + return this.getInventory(owner, type, tileEntity); // Paper } // Paper end @@ -113,11 +129,19 @@ public abstract class CraftTileInventoryConverter implements CraftInventoryCreat if (tileEntity instanceof BrewingStandBlockEntity) { ((BrewingStandBlockEntity) tileEntity).name = CraftChatMessage.fromStringOrNull(title); } - return this.getInventory(tileEntity); + return this.getInventory(holder, type, tileEntity); // Paper } @Override public Inventory getInventory(Container tileEntity) { + // Paper start + return getInventory(null, null, tileEntity); + } + + @Override + public Inventory getInventory(InventoryHolder owner, InventoryType type, net.minecraft.world.Container tileEntity) { // Paper + if (owner != null) return new org.bukkit.craftbukkit.inventory.CraftInventoryCustom(owner, type, tileEntity); // Paper + // Paper end return new CraftInventoryBrewer(tileEntity); } }