Persistent BlockEntity Lore and DisplayName

Makes it so that when a BlockEntity is placed in the world and then broken, the dropped ItemStack retains any original custom display name/lore.
This commit is contained in:
Jason Penilla
2025-01-12 13:25:06 -08:00
committed by granny
parent 2949506adb
commit eb7d596b45
5 changed files with 128 additions and 164 deletions

View File

@@ -1,5 +1,23 @@
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -152,7 +_,16 @@
}
protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, @Nullable Player player, ItemStack stack, BlockState state) {
- return updateCustomBlockEntityTag(level, player, pos, stack);
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ boolean handled = updateCustomBlockEntityTag(level, player, pos, stack);
+ if (level.purpurConfig.persistentTileEntityLore) {
+ BlockEntity blockEntity1 = level.getBlockEntity(pos);
+ if (blockEntity1 != null) {
+ blockEntity1.setPersistentLore(stack.getOrDefault(DataComponents.LORE, net.minecraft.world.item.component.ItemLore.EMPTY));
+ }
+ }
+ return handled;
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
}
@Nullable
@@ -217,6 +_,7 @@
}

View File

@@ -1,5 +1,55 @@
--- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java
@@ -299,7 +_,7 @@
event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
- popResource(serverLevel, pos, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop));
+ popResource(serverLevel, pos, applyLoreFromTile(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(drop), blockEntity)); // Purpur - Persistent BlockEntity Lore and DisplayName
}
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
@@ -317,7 +_,7 @@
public static void dropResources(BlockState state, LevelAccessor level, BlockPos pos, @Nullable BlockEntity blockEntity) {
if (level instanceof ServerLevel) {
- getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(itemStack -> popResource((ServerLevel)level, pos, itemStack));
+ getDrops(state, (ServerLevel)level, pos, blockEntity).forEach(itemStack -> popResource((ServerLevel)level, pos, applyLoreFromTile(itemStack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName
state.spawnAfterBreak((ServerLevel)level, pos, ItemStack.EMPTY, true);
}
}
@@ -329,11 +_,30 @@
public static void dropResources(BlockState state, Level level, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool, boolean dropExperience) {
// Paper end - Properly handle xp dropping
if (level instanceof ServerLevel) {
- getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, itemStack));
+ getDrops(state, (ServerLevel)level, pos, blockEntity, entity, tool).forEach(itemStack -> popResource(level, pos, applyLoreFromTile(itemStack, blockEntity))); // Purpur - Persistent BlockEntity Lore and DisplayName
state.spawnAfterBreak((ServerLevel) level, pos, tool, dropExperience); // Paper - Properly handle xp dropping
}
}
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ private static ItemStack applyLoreFromTile(ItemStack stack, @Nullable BlockEntity blockEntity) {
+ if (stack.getItem() instanceof BlockItem) {
+ if (blockEntity != null && blockEntity.getLevel() instanceof ServerLevel) {
+ net.minecraft.world.item.component.ItemLore lore = blockEntity.getPersistentLore();
+ net.minecraft.core.component.DataComponentPatch.Builder builder = net.minecraft.core.component.DataComponentPatch.builder();
+ if (blockEntity.getLevel().purpurConfig.persistentTileEntityLore && lore != null) {
+ builder.set(net.minecraft.core.component.DataComponents.LORE, lore);
+ }
+ if (!blockEntity.getLevel().purpurConfig.persistentTileEntityDisplayName) {
+ builder.remove(net.minecraft.core.component.DataComponents.CUSTOM_NAME);
+ }
+ stack.applyComponents(builder.build());
+ }
+ }
+ return stack;
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
+
public static void popResource(Level level, BlockPos pos, ItemStack stack) {
double d = EntityType.ITEM.getHeight() / 2.0;
double d1 = pos.getX() + 0.5 + Mth.nextDouble(level.random, -0.25, 0.25);
@@ -412,7 +_,15 @@
}

View File

@@ -0,0 +1,50 @@
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -84,6 +_,14 @@
this.persistentDataContainer.putAll((CompoundTag) persistentDataTag);
}
// Paper end - read persistent data container
+
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ if (tag.contains("Purpur.persistentLore")) {
+ net.minecraft.world.item.component.ItemLore.CODEC.decode(net.minecraft.nbt.NbtOps.INSTANCE, tag.getCompound("Purpur.persistentLore")).result()
+ .ifPresent(tag1 -> this.persistentLore = tag1.getFirst());
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
+
}
public final void loadWithComponents(CompoundTag tag, HolderLookup.Provider registries) {
@@ -98,6 +_,15 @@
this.loadAdditional(tag, registries);
}
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ protected void saveAdditional(CompoundTag nbt) {
+ if (this.persistentLore != null) {
+ net.minecraft.world.item.component.ItemLore.CODEC.encodeStart(net.minecraft.nbt.NbtOps.INSTANCE, this.persistentLore).result()
+ .ifPresent(tag -> nbt.put("Purpur.persistentLore", tag));
+ }
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
+
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
}
@@ -378,4 +_,16 @@
<T> T getOrDefault(DataComponentType<? extends T> component, T defaultValue);
}
+ // Purpur start - Persistent BlockEntity Lore and DisplayName
+ @Nullable
+ private net.minecraft.world.item.component.ItemLore persistentLore = null;
+
+ public void setPersistentLore(net.minecraft.world.item.component.ItemLore lore) {
+ this.persistentLore = lore;
+ }
+
+ public @org.jetbrains.annotations.Nullable net.minecraft.world.item.component.ItemLore getPersistentLore() {
+ return this.persistentLore;
+ }
+ // Purpur end - Persistent BlockEntity Lore and DisplayName
}

View File

@@ -141,6 +141,8 @@ public class PurpurWorldConfig {
public boolean mobsIgnoreRails = false;
public boolean rainStopsAfterSleep = true;
public boolean thunderStopsAfterSleep = true;
public boolean persistentTileEntityLore = false;
public boolean persistentTileEntityDisplayName = true;
private void miscGameplayMechanicsSettings() {
useBetterMending = getBoolean("gameplay-mechanics.use-better-mending", useBetterMending);
alwaysTameInCreative = getBoolean("gameplay-mechanics.always-tame-in-creative", alwaysTameInCreative);
@@ -165,6 +167,14 @@ public class PurpurWorldConfig {
mobsIgnoreRails = getBoolean("gameplay-mechanics.mobs-ignore-rails", mobsIgnoreRails);
rainStopsAfterSleep = getBoolean("gameplay-mechanics.rain-stops-after-sleep", rainStopsAfterSleep);
thunderStopsAfterSleep = getBoolean("gameplay-mechanics.thunder-stops-after-sleep", thunderStopsAfterSleep);
if (PurpurConfig.version < 35) {
boolean oldVal = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityLore);
set("gameplay-mechanics.persistent-tileentity-display-names-and-lore", null);
set("gameplay-mechanics.persistent-tileentity-lore", oldVal);
set("gameplay-mechanics.persistent-tileentity-display-name", !oldVal);
}
persistentTileEntityLore = getBoolean("gameplay-mechanics.persistent-tileentity-lore", persistentTileEntityLore);
persistentTileEntityDisplayName = getBoolean("gameplay-mechanics.persistent-tileentity-display-name", persistentTileEntityDisplayName);
}
public int daytimeTicks = 12000;