From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: jmp <jasonpenilla2@me.com>
Date: Wed, 30 Sep 2020 14:32:46 -0700
Subject: [PATCH] Persistent TileEntity Lore and DisplayName

Makes it so that when a TileEntity is placed in the world and then broken,
the dropped ItemStack retains any original custom display name/lore.

diff --git a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java
index 9c01ec42342cf0420bf5215604c24fbc89c1361b..3de0f21648ca60bdfcbc078bca896d51bf84e207 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/EntityPainting.java
@@ -15,6 +15,7 @@ import net.minecraft.sounds.SoundEffects;
 import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityTypes;
 import net.minecraft.world.entity.player.EntityHuman;
+import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.item.Items;
 import net.minecraft.world.level.GameRules;
 import net.minecraft.world.level.IMaterial;
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java
index 01839c7319e175477ded7001e00e5937734ff516..e5cda8c040c93639211dacbf5b0c7cd6a9df9e6d 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityBoat.java
@@ -34,6 +34,7 @@ import net.minecraft.world.entity.animal.EntityAnimal;
 import net.minecraft.world.entity.animal.EntityWaterAnimal;
 import net.minecraft.world.entity.player.EntityHuman;
 import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.item.Items;
 import net.minecraft.world.level.GameRules;
 import net.minecraft.world.level.IMaterial;
diff --git a/src/main/java/net/minecraft/world/item/ItemBlock.java b/src/main/java/net/minecraft/world/item/ItemBlock.java
index 59d52c252b2e59923b8e513dd4d2e1ec9ce34dc7..4be1c8ee85f411a8b01be50b8cc3dc3835f80a2e 100644
--- a/src/main/java/net/minecraft/world/item/ItemBlock.java
+++ b/src/main/java/net/minecraft/world/item/ItemBlock.java
@@ -119,7 +119,24 @@ public class ItemBlock extends Item {
     }
 
     protected boolean a(BlockPosition blockposition, World world, @Nullable EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) {
-        return a(world, entityhuman, blockposition, itemstack);
+        // Purpur start
+        boolean handled = a(world, entityhuman, blockposition, itemstack);
+        if (world.purpurConfig.persistentTileEntityDisplayNames && itemstack.hasTag()) {
+            NBTTagCompound display = itemstack.getSubTag("display");
+            if (display != null) {
+                TileEntity tile = world.getTileEntity(blockposition);
+                if (tile != null) {
+                    if (display.hasKeyOfType("Name", 8)) {
+                        tile.setPersistentDisplayName(display.getString("Name"));
+                    }
+                    if (display.hasKeyOfType("Lore", 9)) {
+                        tile.setPersistentLore(display.getList("Lore", 8));
+                    }
+                }
+            }
+        }
+        return handled;
+        // Purpur end
     }
 
     @Nullable
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
index 26cda907063f104fd4a3fbd2286b37fb539f741a..fab55929f72c5784291b3bc87f7717ac24b7806f 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -15,10 +15,15 @@ import net.minecraft.core.EnumDirection;
 import net.minecraft.core.IRegistry;
 import net.minecraft.core.NonNullList;
 import net.minecraft.core.RegistryBlockID;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
+import net.minecraft.network.chat.IChatBaseComponent;
 import net.minecraft.server.level.WorldServer;
 import net.minecraft.stats.StatisticList;
 import net.minecraft.tags.Tag;
 import net.minecraft.tags.TagsBlock;
+import net.minecraft.world.INamableTileEntity;
 import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityExperienceOrb;
 import net.minecraft.world.entity.EntityLiving;
@@ -248,7 +253,7 @@ public class Block extends BlockBase implements IMaterial {
     public static void a(IBlockData iblockdata, GeneratorAccess generatoraccess, BlockPosition blockposition, @Nullable TileEntity tileentity) {
         if (generatoraccess instanceof WorldServer) {
             a(iblockdata, (WorldServer) generatoraccess, blockposition, tileentity).forEach((itemstack) -> {
-                a((World) ((WorldServer) generatoraccess), blockposition, itemstack);
+                dropItem((WorldServer) generatoraccess, blockposition, applyDisplayNameAndLoreFromTile(itemstack, tileentity)); // Purpur
             });
             iblockdata.dropNaturally((WorldServer) generatoraccess, blockposition, ItemStack.b);
         }
@@ -257,14 +262,56 @@ public class Block extends BlockBase implements IMaterial {
 
     public static void dropItems(IBlockData iblockdata, World world, BlockPosition blockposition, @Nullable TileEntity tileentity, Entity entity, ItemStack itemstack) {
         if (world instanceof WorldServer) {
-            getDrops(iblockdata, (WorldServer) world, blockposition, tileentity, entity, itemstack).forEach((itemstack1) -> {
-                a(world, blockposition, itemstack1);
+            // Purpur start
+            getDrops(iblockdata, (WorldServer) world, blockposition, tileentity, entity, itemstack).forEach(stackToDrop -> {
+                dropItem(world, blockposition, applyDisplayNameAndLoreFromTile(stackToDrop, tileentity));
+                // Purpur end
             });
             iblockdata.dropNaturally((WorldServer) world, blockposition, itemstack);
         }
 
     }
 
+    // Purpur start
+    private static ItemStack applyDisplayNameAndLoreFromTile(ItemStack itemStack, TileEntity tile) {
+        if (itemStack.getItem() instanceof ItemBlock) {
+            if (tile != null && tile.getWorld() instanceof WorldServer && tile.getWorld().purpurConfig.persistentTileEntityDisplayNames) {
+                String name = tile.getPersistentDisplayName();
+                NBTTagList lore = tile.getPersistentLore();
+                if (tile instanceof INamableTileEntity) {
+                    INamableTileEntity namedTile = (INamableTileEntity) tile;
+                    if (namedTile.hasCustomName()) {
+                        name = IChatBaseComponent.ChatSerializer.componentToJson(namedTile.getCustomName());
+                    }
+                }
+
+                if (name != null || lore != null) {
+                    NBTTagCompound display = itemStack.getSubTag("display");
+                    if (display == null) {
+                        display = new NBTTagCompound();
+                    }
+
+                    if (name != null) {
+                        display.set("Name", NBTTagString.create(name));
+                    }
+                    if (lore != null) {
+                        display.set("Lore", lore);
+                    }
+
+                    NBTTagCompound tag = itemStack.getTag();
+                    if (tag == null) {
+                        tag = new NBTTagCompound();
+                    }
+                    tag.set("display", display);
+
+                    itemStack.setTag(tag);
+                }
+            }
+        }
+        return itemStack;
+    }
+    // Purpur end
+
     public static void a(World world, BlockPosition blockposition, ItemStack itemstack) { dropItem(world, blockposition, itemstack); } public static void dropItem(World world, BlockPosition blockposition, ItemStack itemstack) { // Paper - OBFHELPER
         if (!world.isClientSide && !itemstack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS)) {
             float f = 0.5F;
diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
index f1e586754396439dfb70a4d63e3b8b34fb36ebf4..8a049d3de8937a6c8afe178ccd134e2511fb3baf 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntity.java
@@ -5,6 +5,8 @@ import net.minecraft.CrashReportSystemDetails;
 import net.minecraft.core.BlockPosition;
 import net.minecraft.core.IRegistry;
 import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
 import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
 import net.minecraft.resources.MinecraftKey;
 import net.minecraft.world.level.World;
@@ -104,9 +106,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { /
             this.persistentDataContainer.putAll((NBTTagCompound) persistentDataTag);
         }
         // CraftBukkit end
+        // Purpur start
+        if (nbttagcompound.hasKey("Purpur.persistentDisplayName")) {
+            this.persistentDisplayName = nbttagcompound.getString("Purpur.persistentDisplayName");
+        }
+        if (nbttagcompound.hasKey("Purpur.persistentLore")) {
+            this.persistentLore = nbttagcompound.getList("Purpur.persistentLore", 8);
+        }
+        // Purpur end
     }
 
     public NBTTagCompound save(NBTTagCompound nbttagcompound) {
+        // Purpur start
+        if (this.persistentDisplayName != null) {
+            nbttagcompound.set("Purpur.persistentDisplayName", NBTTagString.create(this.persistentDisplayName));
+        }
+        if (this.persistentLore != null) {
+            nbttagcompound.set("Purpur.persistentLore", this.persistentLore);
+        }
+        // Purpur end
         return this.b(nbttagcompound);
     }
 
@@ -267,4 +285,25 @@ public abstract class TileEntity implements net.minecraft.server.KeyedObject { /
         return null;
     }
     // CraftBukkit end
+
+    // Purpur start
+    private String persistentDisplayName = null;
+    private NBTTagList persistentLore = null;
+
+    public void setPersistentDisplayName(String json) {
+        this.persistentDisplayName = json;
+    }
+
+    public void setPersistentLore(NBTTagList lore) {
+        this.persistentLore = lore;
+    }
+
+    public String getPersistentDisplayName() {
+        return this.persistentDisplayName;
+    }
+
+    public NBTTagList getPersistentLore() {
+        return this.persistentLore;
+    }
+    // Purpur end
 }
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index 93d934b020203dbcd20d01ee650a4a204a9ac201..abe5bc17ff209edbbcb3bb366669887b8d3c75f3 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -200,6 +200,7 @@ public class PurpurWorldConfig {
     public boolean entitiesPickUpLootBypassMobGriefing = false;
     public boolean entitiesCanUsePortals = true;
     public boolean milkCuresBadOmen = true;
+    public boolean persistentTileEntityDisplayNames = false;
     public double tridentLoyaltyVoidReturnHeight = 0.0D;
     public double voidDamageHeight = -64.0D;
     public int raidCooldownSeconds = 0;
@@ -210,6 +211,7 @@ public class PurpurWorldConfig {
         entitiesPickUpLootBypassMobGriefing = getBoolean("gameplay-mechanics.entities-pick-up-loot-bypass-mob-griefing", entitiesPickUpLootBypassMobGriefing);
         entitiesCanUsePortals = getBoolean("gameplay-mechanics.entities-can-use-portals", entitiesCanUsePortals);
         milkCuresBadOmen = getBoolean("gameplay-mechanics.milk-cures-bad-omen", milkCuresBadOmen);
+        persistentTileEntityDisplayNames = getBoolean("gameplay-mechanics.persistent-tileentity-display-names-and-lore", persistentTileEntityDisplayNames);
         tridentLoyaltyVoidReturnHeight = getDouble("gameplay-mechanics.trident-loyalty-void-return-height", tridentLoyaltyVoidReturnHeight);
         voidDamageHeight = getDouble("gameplay-mechanics.void-damage-height", voidDamageHeight);
         raidCooldownSeconds = getInt("gameplay-mechanics.raid-cooldown-seconds", raidCooldownSeconds);
