1
0
Fork 0
mirror of https://github.com/PaperMC/Paper.git synced 2025-03-23 23:39:34 +01:00

Allow For Default Titles in InventoryView Builders ()

This commit is contained in:
Miles 2025-02-16 22:07:00 +00:00 committed by GitHub
parent 84609dc046
commit 8eb8e44ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 201 additions and 70 deletions

View file

@ -1,5 +1,6 @@
package org.bukkit.inventory;
import net.kyori.adventure.text.Component;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
@ -18,12 +19,14 @@ import org.bukkit.inventory.view.builder.InventoryViewBuilder;
import org.bukkit.inventory.view.builder.LocationInventoryViewBuilder;
import org.bukkit.inventory.view.builder.MerchantInventoryViewBuilder;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Represents different kinds of views, also known as menus, which can be
* created and viewed by the player.
*/
@NullMarked
@ApiStatus.Experimental
public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDependant { // Paper - make FeatureDependant
@ -138,6 +141,20 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
*/
interface Typed<V extends InventoryView, B extends InventoryViewBuilder<V>> extends MenuType {
/**
* Creates a view of the specified menu type.
* <p>
* The player provided to create this view must be the player the view
* is opened for. See {@link HumanEntity#openInventory(InventoryView)}
* for more information.
*
* @param player the player the view belongs to
* @return the created {@link InventoryView}
*/
default V create(HumanEntity player) {
return create(player, (Component) null);
}
/**
* Creates a view of the specified menu type.
* <p>
@ -148,11 +165,10 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
* @param player the player the view belongs to
* @param title the title of the view
* @return the created {@link InventoryView}
* @deprecated Use {@link #create(HumanEntity, net.kyori.adventure.text.Component)} instead.
* @deprecated Use {@link #create(HumanEntity, Component)} instead.
*/
@NotNull
@Deprecated(since = "1.21") // Paper - adventure
V create(@NotNull HumanEntity player, @NotNull String title);
V create(HumanEntity player, @Nullable String title);
// Paper start - adventure
/**
@ -166,11 +182,9 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
* @param title the title of the view
* @return the created {@link InventoryView}
*/
@NotNull
V create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
V create(HumanEntity player, @Nullable Component title);
// Paper end - adventure
@NotNull
B builder();
}
@ -186,8 +200,7 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
* @param title the title of the view
* @return the created {@link InventoryView}
*/
@NotNull
InventoryView create(@NotNull HumanEntity player, @NotNull net.kyori.adventure.text.Component title);
InventoryView create(HumanEntity player, @Nullable Component title);
// Paper end - adventure
/**
@ -196,7 +209,6 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
*
* @return the typed MenuType.
*/
@NotNull
MenuType.Typed<InventoryView, InventoryViewBuilder<InventoryView>> typed();
/**
@ -213,19 +225,16 @@ public interface MenuType extends Keyed, io.papermc.paper.world.flag.FeatureDepe
* @throws IllegalArgumentException if the provided viewClass cannot be
* typed to this MenuType
*/
@NotNull
<V extends InventoryView, B extends InventoryViewBuilder<V>> MenuType.Typed<V, B> typed(@NotNull final Class<V> viewClass) throws IllegalArgumentException;
<V extends InventoryView, B extends InventoryViewBuilder<V>> MenuType.Typed<V, B> typed(final Class<V> viewClass) throws IllegalArgumentException;
/**
* Gets the {@link InventoryView} class of this MenuType.
*
* @return the {@link InventoryView} class of this MenuType
*/
@NotNull
Class<? extends InventoryView> getInventoryViewClass();
@NotNull
private static <T extends MenuType> T get(@NotNull final String key) {
private static <T extends MenuType> T get(final String key) {
return (T) Registry.MENU.getOrThrow(NamespacedKey.minecraft(key));
}
}

View file

@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.Nullable;
/**
* Generic Builder for InventoryView's with no special attributes or parameters
@ -23,10 +24,10 @@ public interface InventoryViewBuilder<V extends InventoryView> {
/**
* Sets the title of the builder
*
* @param title the title
* @param title the title, or null for a default title
* @return this builder
*/
InventoryViewBuilder<V> title(final Component title);
InventoryViewBuilder<V> title(@Nullable final Component title);
/**
* Builds this builder into a InventoryView

View file

@ -4,7 +4,7 @@ import net.kyori.adventure.text.Component;
import org.bukkit.Location;
import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.Nullable;
/**
* An InventoryViewBuilder that can be bound by location within the world
@ -18,7 +18,7 @@ public interface LocationInventoryViewBuilder<V extends InventoryView> extends I
LocationInventoryViewBuilder<V> copy();
@Override
LocationInventoryViewBuilder<V> title(final @NotNull Component title);
LocationInventoryViewBuilder<V> title(final @Nullable Component title);
/**
* Determines whether or not the server should check if the player can reach

View file

@ -5,7 +5,7 @@ import org.bukkit.Server;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.Merchant;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.Nullable;
/**
* An InventoryViewBuilder for creating merchant views
@ -19,7 +19,7 @@ public interface MerchantInventoryViewBuilder<V extends InventoryView> extends I
MerchantInventoryViewBuilder<V> copy();
@Override
MerchantInventoryViewBuilder<V> title(final @NotNull Component title);
MerchantInventoryViewBuilder<V> title(final @Nullable Component title);
/**
* Adds a merchant to this builder

View file

@ -9,8 +9,12 @@
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
@@ -106,7 +_,7 @@
return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble"));
@@ -103,10 +_,10 @@
if (first.hasCustomName()) {
return first.getDisplayName();
} else {
- return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble"));
+ return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble")); // Paper - diff on change - CraftDoubleChestInventoryViewBuilder.defaultTitle
}
}
- });

View file

@ -37,3 +37,12 @@
protected ChestBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
super(type, pos, blockState);
}
@@ -71,7 +_,7 @@
@Override
protected Component getDefaultName() {
- return Component.translatable("container.chest");
+ return Component.translatable("container.chest"); // Paper - diff on change - CraftStandardInventoryViewBuilder.defaultTitle
}
@Override

View file

@ -2479,7 +2479,7 @@ public final class CraftServer implements Server {
@Override
public @NotNull Merchant createMerchant() {
return new CraftMerchantCustom(net.kyori.adventure.text.Component.empty());
return new CraftMerchantCustom();
}
@Override

View file

@ -38,7 +38,7 @@ public class CraftMenuType<V extends InventoryView, B extends InventoryViewBuild
@Override
public V create(final HumanEntity player, final String title) {
// Paper start - adventure
return builder().title(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(title)).build(player);
return builder().title(title != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(title) : null).build(player);
}
@Override
public V create(final HumanEntity player, final net.kyori.adventure.text.Component title) {

View file

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.trading.Merchant;
@ -25,6 +26,11 @@ public class CraftMerchantCustom implements CraftMerchant {
this.merchant = new MinecraftMerchant(title);
getMerchant().craftMerchant = this;
}
public CraftMerchantCustom() {
this.merchant = new MinecraftMerchant();
getMerchant().craftMerchant = this;
}
// Paper end
@Override
@ -54,6 +60,10 @@ public class CraftMerchantCustom implements CraftMerchant {
Preconditions.checkArgument(title != null, "Title cannot be null");
this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title);
}
public MinecraftMerchant() {
this.title = EntityType.VILLAGER.getDescription();
}
// Paper end
@Override

View file

@ -17,6 +17,7 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BeaconBlockEntity;
import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.entity.CrafterBlockEntity;
import net.minecraft.world.level.block.entity.DispenserBlockEntity;
import net.minecraft.world.level.block.entity.FurnaceBlockEntity;
@ -29,6 +30,7 @@ import org.bukkit.craftbukkit.inventory.CraftMerchant;
import org.bukkit.craftbukkit.inventory.view.builder.CraftAccessLocationInventoryViewBuilder;
import org.bukkit.craftbukkit.inventory.view.builder.CraftBlockEntityInventoryViewBuilder;
import org.bukkit.craftbukkit.inventory.view.builder.CraftDoubleChestInventoryViewBuilder;
import org.bukkit.craftbukkit.inventory.view.builder.CraftEnchantmentInventoryViewBuilder;
import org.bukkit.craftbukkit.inventory.view.builder.CraftMerchantInventoryViewBuilder;
import org.bukkit.craftbukkit.inventory.view.builder.CraftStandardInventoryViewBuilder;
import org.bukkit.inventory.InventoryView;
@ -87,7 +89,7 @@ public final class CraftMenus {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftDoubleChestInventoryViewBuilder<>(handle)));
}
if (menuType == MenuType.GENERIC_9X3) {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.CHEST, null)));
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.CHEST, ChestBlockEntity::new, false)));
}
// this isn't ideal as both dispenser and dropper are 3x3, InventoryType can't currently handle generic 3x3s with size 9
// this needs to be removed when inventory creation is overhauled
@ -98,7 +100,7 @@ public final class CraftMenus {
return asType(new MenuTypeData<>(CrafterView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.CRAFTER, CrafterBlockEntity::new)));
}
if (menuType == MenuType.ANVIL) {
return asType(new MenuTypeData<>(AnvilView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, AnvilMenu::new)));
return asType(new MenuTypeData<>(AnvilView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.ANVIL)));
}
if (menuType == MenuType.BEACON) {
return asType(new MenuTypeData<>(BeaconView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.BEACON, BeaconBlockEntity::new)));
@ -110,16 +112,16 @@ public final class CraftMenus {
return asType(new MenuTypeData<>(BrewingStandView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.BREWING_STAND, BrewingStandBlockEntity::new)));
}
if (menuType == MenuType.CRAFTING) {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, CraftingMenu::new)));
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.CRAFTING_TABLE)));
}
if (menuType == MenuType.ENCHANTMENT) {
return asType(new MenuTypeData<>(EnchantmentView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, EnchantmentMenu::new)));
return asType(new MenuTypeData<>(EnchantmentView.class, () -> new CraftEnchantmentInventoryViewBuilder(handle)));
}
if (menuType == MenuType.FURNACE) {
return asType(new MenuTypeData<>(FurnaceView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.FURNACE, FurnaceBlockEntity::new)));
}
if (menuType == MenuType.GRINDSTONE) {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, GrindstoneMenu::new)));
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.GRINDSTONE)));
}
// We really don't need to be creating a tile entity for hopper but currently InventoryType doesn't have capacity
// to understand otherwise
@ -131,7 +133,7 @@ public final class CraftMenus {
return asType(new MenuTypeData<>(LecternView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.LECTERN, LecternBlockEntity::new)));
}
if (menuType == MenuType.LOOM) {
return asType(new MenuTypeData<>(LoomView.class, () -> new CraftStandardInventoryViewBuilder<>(handle)));
return asType(new MenuTypeData<>(LoomView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.LOOM)));
}
if (menuType == MenuType.MERCHANT) {
return asType(new MenuTypeData<>(MerchantView.class, () -> new CraftMerchantInventoryViewBuilder<>(handle)));
@ -140,16 +142,16 @@ public final class CraftMenus {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.SHULKER_BOX, ShulkerBoxBlockEntity::new)));
}
if (menuType == MenuType.SMITHING) {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, SmithingMenu::new)));
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.SMITHING_TABLE)));
}
if (menuType == MenuType.SMOKER) {
return asType(new MenuTypeData<>(FurnaceView.class, () -> new CraftBlockEntityInventoryViewBuilder<>(handle, Blocks.SMOKER, SmokerBlockEntity::new)));
}
if (menuType == MenuType.CARTOGRAPHY_TABLE) {
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, CartographyTableMenu::new)));
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.CARTOGRAPHY_TABLE)));
}
if (menuType == MenuType.STONECUTTER) {
return asType(new MenuTypeData<>(StonecutterView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, StonecutterMenu::new)));
return asType(new MenuTypeData<>(StonecutterView.class, () -> new CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.STONECUTTER)));
}
return asType(new MenuTypeData<>(InventoryView.class, () -> new CraftStandardInventoryViewBuilder<>(handle)));

View file

@ -10,21 +10,22 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.view.builder.InventoryViewBuilder;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.jspecify.annotations.Nullable;
public abstract class CraftAbstractInventoryViewBuilder<V extends InventoryView> implements InventoryViewBuilder<V> {
protected final MenuType<?> handle;
protected boolean checkReachable = false;
protected @MonotonicNonNull Component title = null;
protected @Nullable Component title = null;
protected net.minecraft.network.chat.Component defaultTitle = null;
public CraftAbstractInventoryViewBuilder(final MenuType<?> handle) {
this.handle = handle;
}
@Override
public InventoryViewBuilder<V> title(final Component title) {
public InventoryViewBuilder<V> title(final @Nullable Component title) {
this.title = title;
return this;
}
@ -33,14 +34,14 @@ public abstract class CraftAbstractInventoryViewBuilder<V extends InventoryView>
@Override
public V build(final HumanEntity player) {
Preconditions.checkArgument(player != null, "The given player must not be null");
Preconditions.checkArgument(this.title != null, "The given title must not be null");
Preconditions.checkArgument(player instanceof CraftHumanEntity, "The given player must be a CraftHumanEntity");
final CraftHumanEntity craftHuman = (CraftHumanEntity) player;
Preconditions.checkArgument(craftHuman.getHandle() instanceof ServerPlayer, "The given player must be an EntityPlayer");
Preconditions.checkArgument(craftHuman.getHandle() instanceof ServerPlayer, "The given player must be an ServerPlayer");
final ServerPlayer serverPlayer = (ServerPlayer) craftHuman.getHandle();
final AbstractContainerMenu container = buildContainer(serverPlayer);
container.checkReachable = this.checkReachable;
container.setTitle(PaperAdventure.asVanilla(this.title));
container.setTitle(this.title != null ? PaperAdventure.asVanilla(this.title) : this.defaultTitle);
return (V) container.getBukkitView();
}

View file

@ -22,7 +22,7 @@ public abstract class CraftAbstractLocationInventoryViewBuilder<V extends Invent
}
@Override
public LocationInventoryViewBuilder<V> title(final Component title) {
public LocationInventoryViewBuilder<V> title(final @Nullable Component title) {
return (LocationInventoryViewBuilder<V>) super.title(title);
}

View file

@ -1,37 +1,50 @@
package org.bukkit.craftbukkit.inventory.view.builder;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.view.builder.LocationInventoryViewBuilder;
public class CraftAccessLocationInventoryViewBuilder<V extends InventoryView> extends CraftAbstractLocationInventoryViewBuilder<V> {
private final CraftAccessContainerObjectBuilder containerBuilder;
private final Block block;
public CraftAccessLocationInventoryViewBuilder(final MenuType<?> handle, final CraftAccessContainerObjectBuilder containerBuilder) {
public CraftAccessLocationInventoryViewBuilder(final MenuType<?> handle, final Block block) {
super(handle);
this.containerBuilder = containerBuilder;
this.block = block;
}
@Override
protected AbstractContainerMenu buildContainer(final ServerPlayer player) {
final ContainerLevelAccess access;
if (super.position == null) {
access = ContainerLevelAccess.create(player.level(), player.blockPosition());
final BlockState effectiveBlockState;
final BlockPos effectiveBlockPos;
final Level effectiveLevel;
if (super.position != null) {
effectiveBlockPos = super.position;
effectiveLevel = super.world;
effectiveBlockState = super.world.getBlockState(position);
} else {
access = ContainerLevelAccess.create(super.world, super.position);
effectiveBlockPos = player.blockPosition();
effectiveLevel = player.level();
effectiveBlockState = block.defaultBlockState();
}
return this.containerBuilder.build(player.nextContainerCounter(), player.getInventory(), access);
final MenuProvider provider = block.getMenuProvider(effectiveBlockState, effectiveLevel, effectiveBlockPos);
super.defaultTitle = provider.getDisplayName();
return provider.createMenu(player.nextContainerCounter(), player.getInventory(), player);
}
@Override
public LocationInventoryViewBuilder<V> copy() {
final CraftAccessLocationInventoryViewBuilder<V> copy = new CraftAccessLocationInventoryViewBuilder<>(this.handle, this.containerBuilder);
final CraftAccessLocationInventoryViewBuilder<V> copy = new CraftAccessLocationInventoryViewBuilder<>(this.handle, this.block);
copy.world = super.world;
copy.position = super.position;
copy.checkReachable = super.checkReachable;

View file

@ -16,10 +16,25 @@ import org.jspecify.annotations.Nullable;
public class CraftBlockEntityInventoryViewBuilder<V extends InventoryView> extends CraftAbstractLocationInventoryViewBuilder<V> {
private final Block block;
private final @Nullable CraftTileInventoryBuilder builder;
private final boolean useFakeBlockEntity;
private final @Nullable CraftBlockInventoryBuilder builder;
public CraftBlockEntityInventoryViewBuilder(final MenuType<?> handle, final Block block, final @Nullable CraftTileInventoryBuilder builder) {
public CraftBlockEntityInventoryViewBuilder(
final MenuType<?> handle,
final Block block,
final @Nullable CraftBlockInventoryBuilder builder
) {
this(handle, block, builder, true);
}
public CraftBlockEntityInventoryViewBuilder(
final MenuType<?> handle,
final Block block,
final @Nullable CraftBlockInventoryBuilder builder,
final boolean useFakeBlockEntity
) {
super(handle);
this.useFakeBlockEntity = useFakeBlockEntity;
this.block = block;
this.builder = builder;
}
@ -32,35 +47,44 @@ public class CraftBlockEntityInventoryViewBuilder<V extends InventoryView> exten
if (this.position == null) {
this.position = player.blockPosition();
return buildFakeBlockEntity(player);
}
final BlockEntity entity = this.world.getBlockEntity(position);
if (!(entity instanceof final MenuConstructor container)) {
return buildFakeTile(player);
return buildFakeBlockEntity(player);
}
final AbstractContainerMenu atBlock = container.createMenu(player.nextContainerCounter(), player.getInventory(), player);
if (atBlock.getType() != super.handle) {
return buildFakeTile(player);
return buildFakeBlockEntity(player);
}
if (!(entity instanceof final MenuProvider provider)) {
throw new IllegalStateException("Provided blockEntity during MenuType creation can not find a default title! This is a bug!");
}
super.defaultTitle = provider.getDisplayName();
return atBlock;
}
private AbstractContainerMenu buildFakeTile(final ServerPlayer player) {
if (this.builder == null) {
private AbstractContainerMenu buildFakeBlockEntity(final ServerPlayer player) {
final MenuProvider inventory = this.builder.build(this.position, this.block.defaultBlockState());
if (inventory instanceof final BlockEntity blockEntity) {
blockEntity.setLevel(this.world);
super.defaultTitle = inventory.getDisplayName();
}
if (!this.useFakeBlockEntity) { // gets around open noise for chest
return handle.create(player.nextContainerCounter(), player.getInventory());
}
final MenuProvider inventory = this.builder.build(this.position, this.block.defaultBlockState());
if (inventory instanceof final BlockEntity tile) {
tile.setLevel(this.world);
}
return inventory.createMenu(player.nextContainerCounter(), player.getInventory(), player);
}
@Override
public LocationInventoryViewBuilder<V> copy() {
final CraftBlockEntityInventoryViewBuilder<V> copy = new CraftBlockEntityInventoryViewBuilder<>(super.handle, this.block, this.builder);
final CraftBlockEntityInventoryViewBuilder<V> copy = new CraftBlockEntityInventoryViewBuilder<>(super.handle, this.block, this.builder, this.useFakeBlockEntity);
copy.world = this.world;
copy.position = this.position;
copy.checkReachable = super.checkReachable;
@ -68,7 +92,7 @@ public class CraftBlockEntityInventoryViewBuilder<V extends InventoryView> exten
return copy;
}
public interface CraftTileInventoryBuilder {
public interface CraftBlockInventoryBuilder {
MenuProvider build(BlockPos blockPosition, BlockState blockData);
}
}

View file

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.inventory.view.builder;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.inventory.AbstractContainerMenu;
@ -15,6 +16,7 @@ public class CraftDoubleChestInventoryViewBuilder<V extends InventoryView> exten
public CraftDoubleChestInventoryViewBuilder(final MenuType<?> handle) {
super(handle);
super.defaultTitle = Component.translatable("container.chestDouble");
}
@Override
@ -24,7 +26,9 @@ public class CraftDoubleChestInventoryViewBuilder<V extends InventoryView> exten
}
final ChestBlock chest = (ChestBlock) Blocks.CHEST;
final DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> result = chest.combine(super.world.getBlockState(super.position), super.world, super.position, false);
final DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> result = chest.combine(
super.world.getBlockState(super.position), super.world, super.position, false
);
if (result instanceof DoubleBlockCombiner.NeighborCombineResult.Single<? extends ChestBlockEntity>) {
return handle.create(player.nextContainerCounter(), player.getInventory());
}
@ -33,6 +37,7 @@ public class CraftDoubleChestInventoryViewBuilder<V extends InventoryView> exten
if (combined == null) {
return handle.create(player.nextContainerCounter(), player.getInventory());
}
return combined.createMenu(player.nextContainerCounter(), player.getInventory(), player);
}

View file

@ -0,0 +1,40 @@
package org.bukkit.craftbukkit.inventory.view.builder;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.EnchantingTableBlockEntity;
import org.bukkit.inventory.view.EnchantmentView;
public class CraftEnchantmentInventoryViewBuilder extends CraftAbstractLocationInventoryViewBuilder<EnchantmentView> {
public CraftEnchantmentInventoryViewBuilder(final MenuType<?> handle) {
super(handle);
}
@Override
protected AbstractContainerMenu buildContainer(final ServerPlayer player) {
if (this.world == null) {
this.world = player.level();
}
if (this.position == null) {
this.position = player.blockPosition();
super.defaultTitle = new EnchantingTableBlockEntity(this.position, Blocks.ENCHANTING_TABLE.defaultBlockState()).getDisplayName();
return new EnchantmentMenu(player.nextContainerCounter(), player.getInventory(), ContainerLevelAccess.create(this.world, this.position));
}
final BlockEntity entity = this.world.getBlockEntity(position);
if (entity instanceof final EnchantingTableBlockEntity enchantingBlockEntity) {
super.defaultTitle = enchantingBlockEntity.getDisplayName();
} else {
super.defaultTitle = new EnchantingTableBlockEntity(this.position, Blocks.ENCHANTING_TABLE.defaultBlockState()).getDisplayName();
}
return new EnchantmentMenu(player.nextContainerCounter(), player.getInventory(), ContainerLevelAccess.create(this.world, this.position));
}
}

View file

@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
import io.papermc.paper.adventure.PaperAdventure;
import net.kyori.adventure.text.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.MerchantMenu;
@ -25,7 +26,7 @@ public class CraftMerchantInventoryViewBuilder<V extends InventoryView> extends
}
@Override
public MerchantInventoryViewBuilder<V> title(final Component title) {
public MerchantInventoryViewBuilder<V> title(final @Nullable Component title) {
return (MerchantInventoryViewBuilder<V>) super.title(title);
}
@ -44,24 +45,34 @@ public class CraftMerchantInventoryViewBuilder<V extends InventoryView> extends
@Override
public V build(final HumanEntity player) {
Preconditions.checkArgument(player != null, "The given player must not be null");
Preconditions.checkArgument(this.title != null, "The given title must not be null");
Preconditions.checkArgument(player instanceof CraftHumanEntity, "The given player must be a CraftHumanEntity");
final CraftHumanEntity craftHuman = (CraftHumanEntity) player;
Preconditions.checkArgument(craftHuman.getHandle() instanceof ServerPlayer, "The given player must be an EntityPlayer");
Preconditions.checkArgument(craftHuman.getHandle() instanceof ServerPlayer, "The given player must be an ServerPlayer");
final ServerPlayer serverPlayer = (ServerPlayer) craftHuman.getHandle();
final MerchantMenu container;
if (this.merchant == null) {
container = new MerchantMenu(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(), new CraftMerchantCustom(title).getMerchant());
} else {
container = new MerchantMenu(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(), this.merchant);
this.merchant = this.title == null ? new CraftMerchantCustom().getMerchant() : new CraftMerchantCustom(title).getMerchant();
}
container = new MerchantMenu(serverPlayer.nextContainerCounter(), serverPlayer.getInventory(), this.merchant);
container.checkReachable = super.checkReachable;
container.setTitle(PaperAdventure.asVanilla(this.title));
setDefaultTitle(this.merchant);
container.setTitle(super.title != null ? PaperAdventure.asVanilla(this.title) : super.defaultTitle);
return (V) container.getBukkitView();
}
private void setDefaultTitle(final net.minecraft.world.item.trading.Merchant merchant) {
if (merchant instanceof final AbstractVillager villager) {
super.defaultTitle = villager.getDisplayName();
} else if (merchant instanceof final CraftMerchantCustom.MinecraftMerchant custom) {
super.defaultTitle = custom.getScoreboardDisplayName();
} else {
throw new IllegalStateException("Provided merchant during MenuType creation can not find a default title! This is a bug!");
}
}
@Override
protected AbstractContainerMenu buildContainer(final ServerPlayer player) {
throw new UnsupportedOperationException("buildContainer is not supported for CraftMerchantInventoryViewBuilder");

View file

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.inventory.view.builder;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
@ -10,6 +11,7 @@ public class CraftStandardInventoryViewBuilder<V extends InventoryView> extends
public CraftStandardInventoryViewBuilder(final MenuType<?> handle) {
super(handle);
super.defaultTitle = Component.translatable("container.chest");
}
@Override