Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow For Default Titles in InventoryView Builders #12013

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
- });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -2488,7 +2488,7 @@ public Merchant createMerchant(String title) {

@Override
public @NotNull Merchant createMerchant() {
return new CraftMerchantCustom(net.kyori.adventure.text.Component.empty());
return new CraftMerchantCustom();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public CraftMerchantCustom(net.kyori.adventure.text.Component title) {
this.merchant = new MinecraftMerchant(title);
getMerchant().craftMerchant = this;
}

public CraftMerchantCustom() {
this.merchant = new MinecraftMerchant();
getMerchant().craftMerchant = this;
}
// Paper end

@Override
Expand Down Expand Up @@ -54,6 +59,10 @@ public MinecraftMerchant(net.kyori.adventure.text.Component title) {
Preconditions.checkArgument(title != null, "Title cannot be null");
this.title = io.papermc.paper.adventure.PaperAdventure.asVanilla(title);
}

public MinecraftMerchant() {
this.title = Component.translatable("entity.minecraft.villager");
}
// Paper end

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
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;
Expand Down Expand Up @@ -87,7 +88,7 @@ public static <V extends InventoryView, B extends InventoryViewBuilder<V>> MenuT
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
Expand All @@ -98,7 +99,7 @@ public static <V extends InventoryView, B extends InventoryViewBuilder<V>> MenuT
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)));
Expand All @@ -110,16 +111,16 @@ public static <V extends InventoryView, B extends InventoryViewBuilder<V>> MenuT
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 CraftAccessLocationInventoryViewBuilder<>(handle, Blocks.ENCHANTING_TABLE)));
}
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
Expand All @@ -140,16 +141,16 @@ public static <V extends InventoryView, B extends InventoryViewBuilder<V>> MenuT
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)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.view.builder.InventoryViewBuilder;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;

public abstract class CraftAbstractInventoryViewBuilder<V extends InventoryView> implements InventoryViewBuilder<V> {

protected final MenuType<?> handle;

protected boolean checkReachable = false;
protected @MonotonicNonNull Component title = null;
protected Component title = null;
protected net.minecraft.network.chat.Component defaultTitle = null;

public CraftAbstractInventoryViewBuilder(final MenuType<?> handle) {
this.handle = handle;
Expand All @@ -33,14 +33,13 @@ public InventoryViewBuilder<V> title(final Component title) {
@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");
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();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,56 @@
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 ContainerLevelAccess access;
// if (super.position == null) {
// access = ContainerLevelAccess.create(player.level(), player.blockPosition());
// } else {
// access = ContainerLevelAccess.create(super.world, super.position);
// }
final BlockState state;
final BlockPos defPos;
final Level defLevel;
if (super.position != null) {
defPos = super.position;
defLevel = super.world;
state = super.world.getBlockState(position);
} else {
access = ContainerLevelAccess.create(super.world, super.position);
defPos = player.blockPosition();
defLevel = player.level();
state = block.defaultBlockState();
}

return this.containerBuilder.build(player.nextContainerCounter(), player.getInventory(), access);
final MenuProvider provider = block.getMenuProvider(state, defLevel, defPos);
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.Nameable;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuConstructor;
import net.minecraft.world.inventory.MenuType;
Expand All @@ -16,10 +17,16 @@
public class CraftBlockEntityInventoryViewBuilder<V extends InventoryView> extends CraftAbstractLocationInventoryViewBuilder<V> {

private final Block block;
private final boolean useFakeBlockEntity;
private final @Nullable CraftTileInventoryBuilder builder;

public CraftBlockEntityInventoryViewBuilder(final MenuType<?> handle, final Block block, final @Nullable CraftTileInventoryBuilder builder) {
this(handle, block, builder, true);
}

public CraftBlockEntityInventoryViewBuilder(final MenuType<?> handle, final Block block, final @Nullable CraftTileInventoryBuilder builder, boolean useFakeBlockEntity) {
super(handle);
this.useFakeBlockEntity = useFakeBlockEntity;
this.block = block;
this.builder = builder;
}
Expand All @@ -36,31 +43,43 @@ protected AbstractContainerMenu buildContainer(final ServerPlayer 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);
}

setDefaultTitle(entity);
return atBlock;
}

private AbstractContainerMenu buildFakeTile(final ServerPlayer player) {
if (this.builder == null) {
return handle.create(player.nextContainerCounter(), player.getInventory());
}
private AbstractContainerMenu buildFakeBlockEntity(final ServerPlayer player) {
final MenuProvider inventory = this.builder.build(this.position, this.block.defaultBlockState());
if (inventory instanceof final BlockEntity tile) {
tile.setLevel(this.world);
setDefaultTitle(tile);
}

if (!this.useFakeBlockEntity) { // gets around open noise for chest
return handle.create(player.nextContainerCounter(), player.getInventory());
}

return inventory.createMenu(player.nextContainerCounter(), player.getInventory(), player);
}

private void setDefaultTitle(BlockEntity blockEntity) {
if (!(blockEntity instanceof Nameable nameable)) {
throw new IllegalStateException("Provided blockEntity during MenuType creation can not find a default title! This is a bug!");
}

super.defaultTitle = nameable.getDisplayName();
}

@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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -15,6 +16,7 @@ public class CraftDoubleChestInventoryViewBuilder<V extends InventoryView> exten

public CraftDoubleChestInventoryViewBuilder(final MenuType<?> handle) {
super(handle);
super.defaultTitle = Component.translatable("container.chestDouble");
Y2Kwastaken marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
Expand Down
Loading
Loading