From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Thu, 9 May 2019 14:27:37 -0500
Subject: [PATCH] Silk touch spawners


diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java
index c45d48cef53476fa1602cebaa57c72894bba10d3..8a8ad2a0dc50de1f7f911d0547480b65d03fee0c 100644
--- a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java
+++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java
@@ -82,6 +82,7 @@ public final class PaperAdventure {
         .build();
     public static final LegacyComponentSerializer LEGACY_SECTION_UXRC = LegacyComponentSerializer.builder().flattener(FLATTENER).hexColors().useUnusualXRepeatedCharacterHexFormat().build();
     public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build();
+    public static final LegacyComponentSerializer LEGACY_AMPERSAND = LegacyComponentSerializer.builder().character(LegacyComponentSerializer.AMPERSAND_CHAR).hexColors().build(); // Purpur
     static final GsonComponentSerializer GSON = GsonComponentSerializer.builder()
         .legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.INSTANCE)
         .build();
diff --git a/src/main/java/net/minecraft/server/BlockMobSpawner.java b/src/main/java/net/minecraft/server/BlockMobSpawner.java
index 81e145ff0759322f74888c81df8d2133fece7144..567a6a064254d99ae6a931b91e6bdd94badb19fc 100644
--- a/src/main/java/net/minecraft/server/BlockMobSpawner.java
+++ b/src/main/java/net/minecraft/server/BlockMobSpawner.java
@@ -1,5 +1,17 @@
 package net.minecraft.server;
 
+// Purpur start
+import io.papermc.paper.adventure.PaperAdventure;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextReplacementConfig;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+
+import java.util.List;
+
+import static net.kyori.adventure.text.format.TextDecoration.ITALIC;
+// Purpur end
+
 public class BlockMobSpawner extends BlockTileEntity {
 
     protected BlockMobSpawner(BlockBase.Info blockbase_info) {
@@ -11,6 +23,59 @@ public class BlockMobSpawner extends BlockTileEntity {
         return new TileEntityMobSpawner();
     }
 
+    // Purpur start
+    @Override
+    public void a(World world, EntityHuman entityhuman, BlockPosition blockposition, IBlockData iblockdata, TileEntity tileentity, ItemStack itemstack) {
+        if (world.purpurConfig.silkTouchEnabled && entityhuman.getBukkitEntity().hasPermission("purpur.drop.spawners") && isSilkTouch(world, itemstack)) {
+            MinecraftKey type = ((TileEntityMobSpawner) tileentity).getSpawner().getMobName();
+            if (type != null) {
+                final Component mobName = PaperAdventure.asAdventure(EntityTypes.getFromKey(type).getNameComponent());
+                final TextReplacementConfig config = TextReplacementConfig.builder()
+                        .matchLiteral("{mob}")
+                        .replacement(mobName)
+                        .build();
+
+                NBTTagCompound display = new NBTTagCompound();
+                boolean customDisplay = false;
+
+                String name = world.purpurConfig.silkTouchSpawnerName;
+                if (name != null && !name.isEmpty() && !name.equals("Spawner")) {
+                    final Component displayName = PaperAdventure.LEGACY_AMPERSAND.deserialize(name).replaceText(config).decoration(ITALIC, false);
+                    display.set("Name", NBTTagString.create(GsonComponentSerializer.gson().serialize(displayName)));
+                    customDisplay = true;
+                }
+
+                List<String> lore = world.purpurConfig.silkTouchSpawnerLore;
+                if (lore != null && !lore.isEmpty()) {
+                    NBTTagList list = new NBTTagList();
+                    for (String line : lore) {
+                        final Component lineComponent = PaperAdventure.LEGACY_AMPERSAND.deserialize(line).replaceText(config).decoration(ITALIC, false);
+                        list.add(NBTTagString.create(GsonComponentSerializer.gson().serialize(lineComponent)));
+                    }
+                    display.set("Lore", list);
+                    customDisplay = true;
+                }
+
+                NBTTagCompound tag = new NBTTagCompound();
+                if (customDisplay) {
+                    tag.set("display", display);
+                }
+                tag.setString("Purpur.mob_type", type.toString());
+
+                ItemStack item = new ItemStack(Blocks.SPAWNER.getItem());
+                item.setTag(tag);
+
+                dropItem(world, blockposition, item);
+            }
+        }
+        super.a(world, entityhuman, blockposition, iblockdata, tileentity, itemstack);
+    }
+
+    private boolean isSilkTouch(World world, ItemStack itemstack) {
+        return itemstack != null && world.purpurConfig.silkTouchTools.contains(itemstack.getItem()) && EnchantmentManager.getEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) > 0;
+    }
+    // Purpur end
+
     @Override
     public void dropNaturally(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack) {
         super.dropNaturally(iblockdata, worldserver, blockposition, itemstack);
@@ -23,6 +88,7 @@ public class BlockMobSpawner extends BlockTileEntity {
 
     @Override
     public int getExpDrop(IBlockData iblockdata, WorldServer worldserver, BlockPosition blockposition, ItemStack itemstack) {
+        if (isSilkTouch(worldserver, itemstack)) return 0; // Purpur
         int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15);
 
         return i;
diff --git a/src/main/java/net/minecraft/server/ItemSpawner.java b/src/main/java/net/minecraft/server/ItemSpawner.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c7f73918542bbdbc8d8f97671f24091fc6cb83b
--- /dev/null
+++ b/src/main/java/net/minecraft/server/ItemSpawner.java
@@ -0,0 +1,23 @@
+package net.minecraft.server;
+
+public class ItemSpawner extends ItemBlock {
+    public ItemSpawner(Block block, Info info) {
+        super(block, info);
+    }
+
+    @Override
+    protected boolean a(BlockPosition blockposition, World world, EntityHuman entityhuman, ItemStack itemstack, IBlockData iblockdata) {
+        boolean handled = super.a(blockposition, world, entityhuman, itemstack, iblockdata);
+        if (world.purpurConfig.silkTouchEnabled && entityhuman.getBukkitEntity().hasPermission("purpur.place.spawners")) {
+            TileEntity spawner = world.getTileEntity(blockposition);
+            if (spawner instanceof TileEntityMobSpawner && itemstack.hasTag()) {
+                NBTTagCompound tag = itemstack.getTag();
+                if (tag.hasKey("Purpur.mob_type")) {
+                    EntityTypes.getByName(tag.getString("Purpur.mob_type")).ifPresent(type ->
+                            ((TileEntityMobSpawner) spawner).getSpawner().setMobName(type));
+                }
+            }
+        }
+        return handled;
+    }
+}
diff --git a/src/main/java/net/minecraft/server/Items.java b/src/main/java/net/minecraft/server/Items.java
index 1c861bccc2652057cb154667a5bf7269092b2db4..67ebcbe4daa1ef3cef6ca43ec92befbe4156842e 100644
--- a/src/main/java/net/minecraft/server/Items.java
+++ b/src/main/java/net/minecraft/server/Items.java
@@ -180,7 +180,7 @@ public class Items {
     public static final Item ct = a(Blocks.PURPUR_BLOCK, CreativeModeTab.b);
     public static final Item cu = a(Blocks.PURPUR_PILLAR, CreativeModeTab.b);
     public static final Item cv = a(Blocks.PURPUR_STAIRS, CreativeModeTab.b);
-    public static final Item cw = a(Blocks.SPAWNER);
+    public static final Item cw = a(Blocks.SPAWNER, new ItemSpawner(Blocks.SPAWNER, new Item.Info().a(EnumItemRarity.EPIC))); // Purpur
     public static final Item cx = a(Blocks.OAK_STAIRS, CreativeModeTab.b);
     public static final Item cy = a(Blocks.CHEST, CreativeModeTab.c);
     public static final Item cz = a(Blocks.DIAMOND_ORE, CreativeModeTab.b);
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index c7fb5a737cab0083c39732247acb8f4e87562894..ba89efb3159ab04a6239865967f93055cb6be7a9 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
@@ -1,6 +1,12 @@
 package net.pl3x.purpur;
 
+import net.minecraft.server.IRegistry;
+import net.minecraft.server.Item;
+import net.minecraft.server.Items;
+import net.minecraft.server.MinecraftKey;
 import org.bukkit.configuration.ConfigurationSection;
+
+import java.util.ArrayList;
 import java.util.List;
 import static net.pl3x.purpur.PurpurConfig.log;
 
@@ -75,6 +81,29 @@ public class PurpurWorldConfig {
         playerInvulnerableWhileAcceptingResourcePack = getBoolean("gameplay-mechanics.player.invulnerable-while-accepting-resource-pack", playerInvulnerableWhileAcceptingResourcePack);
     }
 
+    public boolean silkTouchEnabled = false;
+    public String silkTouchSpawnerName = "Spawner";
+    public List<String> silkTouchSpawnerLore = new ArrayList<>();
+    public List<Item> silkTouchTools = new ArrayList<>();
+    private void silkTouchSettings() {
+        silkTouchEnabled = getBoolean("gameplay-mechanics.silk-touch.enabled", silkTouchEnabled);
+        silkTouchSpawnerName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName);
+        silkTouchSpawnerLore.clear();
+        getList("gameplay-mechanics.silk-touch.spawner-lore", new ArrayList<String>(){{
+            add("Spawns a {mob}");
+        }}).forEach(line -> silkTouchSpawnerLore.add(line.toString()));
+        silkTouchTools.clear();
+        getList("gameplay-mechanics.silk-touch.tools", new ArrayList<String>(){{
+            add("minecraft:iron_pickaxe");
+            add("minecraft:golden_pickaxe");
+            add("minecraft:diamond_pickaxe");
+            add("minecraft:netherite_pickaxe");
+        }}).forEach(key -> {
+            Item item = IRegistry.ITEM.get(new MinecraftKey(key.toString()));
+            if (item != Items.AIR) silkTouchTools.add(item);
+        });
+    }
+
     public int villagerBrainTicks = 1;
     public boolean villagerUseBrainTicksOnlyWhenLagging = true;
     private void villagerSettings() {
