diff --git a/patches/server/0019-Silk-touch-spawners.patch b/patches/server/0019-Silk-touch-spawners.patch deleted file mode 100644 index d308ccf74..000000000 --- a/patches/server/0019-Silk-touch-spawners.patch +++ /dev/null @@ -1,190 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -Date: Thu, 9 May 2019 14:27:37 -0500 -Subject: [PATCH] Silk touch spawners - - -diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java -index 4377fa2400c4320e0023ece230090a2a3b4b2ab6..ac5dc472337cd9613db5fc03f64763245129dfd9 100644 ---- a/net/minecraft/world/item/BlockItem.java -+++ b/net/minecraft/world/item/BlockItem.java -@@ -223,6 +223,7 @@ public class BlockItem extends Item { - } - - if (tileentitytypes1.onlyOpCanSetNbt() && (player == null || !(player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place"))))) { // Spigot - add permission -+ if (!(world.purpurConfig.silkTouchEnabled && tileentity instanceof net.minecraft.world.level.block.entity.SpawnerBlockEntity && player.getBukkitEntity().hasPermission("purpur.drop.spawners"))) - return false; - } - -diff --git a/net/minecraft/world/item/Items.java b/net/minecraft/world/item/Items.java -index 6d16b4433e79eca0ff8008941f0b9b807b1db9db..41fbe61268c0a16078b5f846ab12bde172872ff7 100644 ---- a/net/minecraft/world/item/Items.java -+++ b/net/minecraft/world/item/Items.java -@@ -367,7 +367,7 @@ public class Items { - public static final Item PURPUR_BLOCK = registerBlock(Blocks.PURPUR_BLOCK); - public static final Item PURPUR_PILLAR = registerBlock(Blocks.PURPUR_PILLAR); - public static final Item PURPUR_STAIRS = registerBlock(Blocks.PURPUR_STAIRS); -- public static final Item SPAWNER = registerBlock(Blocks.SPAWNER); -+ public static final Item SPAWNER = registerBlock(Blocks.SPAWNER, org.purpurmc.purpur.item.SpawnerItem::new, new Item.Properties().rarity(Rarity.EPIC)); // Purpur - public static final Item CREAKING_HEART = registerBlock(Blocks.CREAKING_HEART); - public static final Item CHEST = registerBlock(Blocks.CHEST, settings -> settings.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY)); - public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE); -diff --git a/net/minecraft/world/level/block/SpawnerBlock.java b/net/minecraft/world/level/block/SpawnerBlock.java -index d751b280a8bf2066d458f8eb548d7aa123fa69c9..fb88b5c1d9e764bf1211d601527133ea8e8268b3 100644 ---- a/net/minecraft/world/level/block/SpawnerBlock.java -+++ b/net/minecraft/world/level/block/SpawnerBlock.java -@@ -42,6 +42,57 @@ public class SpawnerBlock extends BaseEntityBlock { - return createTickerHelper(type, BlockEntityType.MOB_SPAWNER, world.isClientSide ? SpawnerBlockEntity::clientTick : SpawnerBlockEntity::serverTick); - } - -+ // Purpur start -+ @Override -+ public void playerDestroy(Level level, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack, boolean includeDrops, boolean dropExp) { -+ if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.drop.spawners") && isSilkTouch(level, stack)) { -+ ItemStack item = new ItemStack(Blocks.SPAWNER.asItem()); -+ -+ net.minecraft.world.level.SpawnData nextSpawnData = blockEntity instanceof SpawnerBlockEntity spawnerBlock ? spawnerBlock.getSpawner().nextSpawnData : null; -+ java.util.Optional> type = java.util.Optional.empty(); -+ if (nextSpawnData != null) { -+ type = net.minecraft.world.entity.EntityType.by(nextSpawnData.getEntityToSpawn()); -+ net.minecraft.world.level.SpawnData.CODEC.encodeStart(net.minecraft.nbt.NbtOps.INSTANCE, nextSpawnData).result().ifPresent(tag -> item.set(net.minecraft.core.component.DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY.update(compoundTag -> compoundTag.put("Purpur.SpawnData", tag)))); -+ } -+ -+ if (type.isPresent()) { -+ final net.kyori.adventure.text.Component mobName = io.papermc.paper.adventure.PaperAdventure.asAdventure(type.get().getDescription()); -+ -+ String name = level.purpurConfig.silkTouchSpawnerName; -+ if (name != null && !name.isEmpty() && !name.equals("Monster Spawner")) { -+ net.kyori.adventure.text.Component displayName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName)); -+ if (name.startsWith("")) { -+ displayName = displayName.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false); -+ } -+ item.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); -+ } -+ -+ List lore = level.purpurConfig.silkTouchSpawnerLore; -+ if (lore != null && !lore.isEmpty()) { -+ -+ List loreComponentList = new java.util.ArrayList<>(); -+ for (String line : lore) { -+ net.kyori.adventure.text.Component lineComponent = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(line, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName)); -+ if (line.startsWith("")) { -+ lineComponent = lineComponent.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false); -+ } -+ loreComponentList.add(io.papermc.paper.adventure.PaperAdventure.asVanilla(lineComponent)); -+ } -+ -+ item.set(net.minecraft.core.component.DataComponents.LORE, new net.minecraft.world.item.component.ItemLore(loreComponentList, loreComponentList)); -+ } -+ item.set(net.minecraft.core.component.DataComponents.HIDE_ADDITIONAL_TOOLTIP, net.minecraft.util.Unit.INSTANCE); -+ } -+ popResource(level, pos, item); -+ } -+ super.playerDestroy(level, player, pos, state, blockEntity, stack, includeDrops, dropExp); -+ } -+ -+ private boolean isSilkTouch(Level level, ItemStack stack) { -+ return stack != null && level.purpurConfig.silkTouchTools.contains(stack.getItem()) && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.SILK_TOUCH, stack) >= level.purpurConfig.minimumSilkTouchSpawnerRequire; -+ } -+ // Purpur end -+ - @Override - protected void spawnAfterBreak(BlockState state, ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) { - super.spawnAfterBreak(state, world, pos, tool, dropExperience); -@@ -50,6 +101,7 @@ public class SpawnerBlock extends BaseEntityBlock { - - @Override - public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { -+ if (worldserver.purpurConfig.silkTouchEnabled && isSilkTouch(worldserver, itemstack)) return 0; // Purpur - if (flag) { - int i = 15 + worldserver.random.nextInt(15) + worldserver.random.nextInt(15); - -diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -index 9b1a4502aa6c26c7524ec17697250317b7f381fd..d6b1b49102ae4421e273f6c781e25a3b18fe13f7 100644 ---- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java -@@ -109,6 +109,38 @@ public class PurpurWorldConfig { - idleTimeoutTargetPlayer = getBoolean("gameplay-mechanics.player.idle-timeout.mobs-target", idleTimeoutTargetPlayer); - } - -+ public boolean silkTouchEnabled = false; -+ public String silkTouchSpawnerName = "Monster Spawner"; -+ public List silkTouchSpawnerLore = new ArrayList<>(); -+ public List silkTouchTools = new ArrayList<>(); -+ public int minimumSilkTouchSpawnerRequire = 1; -+ private void silkTouchSettings() { -+ if (PurpurConfig.version < 21) { -+ String oldName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName); -+ set("gameplay-mechanics.silk-touch.spawner-name", "" + ChatColor.toMM(oldName.replace("{mob}", ""))); -+ List list = new ArrayList<>(); -+ getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a ")) -+ .forEach(line -> list.add("" + ChatColor.toMM(line.toString().replace("{mob}", "")))); -+ set("gameplay-mechanics.silk-touch.spawner-lore", list); -+ } -+ silkTouchEnabled = getBoolean("gameplay-mechanics.silk-touch.enabled", silkTouchEnabled); -+ silkTouchSpawnerName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName); -+ minimumSilkTouchSpawnerRequire = getInt("gameplay-mechanics.silk-touch.minimal-level", minimumSilkTouchSpawnerRequire); -+ silkTouchSpawnerLore.clear(); -+ getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a ")) -+ .forEach(line -> silkTouchSpawnerLore.add(line.toString())); -+ silkTouchTools.clear(); -+ getList("gameplay-mechanics.silk-touch.tools", List.of( -+ "minecraft:iron_pickaxe", -+ "minecraft:golden_pickaxe", -+ "minecraft:diamond_pickaxe", -+ "minecraft:netherite_pickaxe" -+ )).forEach(key -> { -+ Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); -+ if (item != Items.AIR) silkTouchTools.add(item); -+ }); -+ } -+ - public boolean babiesAreRidable = true; - public boolean untamedTamablesAreRidable = true; - public boolean useNightVisionWhenRiding = false; -diff --git a/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java b/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java -new file mode 100644 -index 0000000000000000000000000000000000000000..ed50cb2115401c9039df4136caf5a087a5f5991c ---- /dev/null -+++ b/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java -@@ -0,0 +1,40 @@ -+package org.purpurmc.purpur.item; -+ -+import net.minecraft.core.BlockPos; -+import net.minecraft.core.component.DataComponents; -+import net.minecraft.nbt.CompoundTag; -+import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.item.BlockItem; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.component.CustomData; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.BlockEntity; -+import net.minecraft.world.level.block.entity.SpawnerBlockEntity; -+import net.minecraft.world.level.block.state.BlockState; -+ -+public class SpawnerItem extends BlockItem { -+ -+ public SpawnerItem(Block block, Properties settings) { -+ super(block, settings); -+ } -+ -+ @Override -+ protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, Player player, ItemStack stack, BlockState state) { -+ boolean handled = super.updateCustomBlockEntityTag(pos, level, player, stack, state); -+ if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.place.spawners")) { -+ BlockEntity blockEntity = level.getBlockEntity(pos); -+ if (blockEntity instanceof SpawnerBlockEntity spawner) { -+ CompoundTag customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); -+ if (customData.contains("Purpur.mob_type")) { -+ EntityType.byString(customData.getString("Purpur.mob_type")).ifPresent(type -> spawner.getSpawner().setEntityId(type, level, level.random, pos)); -+ } else if (customData.contains("Purpur.SpawnData")) { -+ net.minecraft.world.level.SpawnData.CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, customData.getCompound("Purpur.SpawnData")).result() -+ .ifPresent(spawnData -> spawner.getSpawner().nextSpawnData = spawnData); -+ } -+ } -+ } -+ return handled; -+ } -+} diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/BlockItem.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/BlockItem.java.patch new file mode 100644 index 000000000..e801e1c56 --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/BlockItem.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/item/BlockItem.java ++++ b/net/minecraft/world/item/BlockItem.java +@@ -217,6 +_,7 @@ + } + + if (!type.onlyOpCanSetNbt() || player != null && (player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place")))) { // Spigot - add permission ++ if (!(level.purpurConfig.silkTouchEnabled && blockEntity instanceof net.minecraft.world.level.block.entity.SpawnerBlockEntity && player.getBukkitEntity().hasPermission("purpur.drop.spawners"))) // Purpur - Silk touch spawners + return customData.loadInto(blockEntity, level.registryAccess()); + } + diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch new file mode 100644 index 000000000..16a4ed57d --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/item/Items.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/Items.java ++++ b/net/minecraft/world/item/Items.java +@@ -367,7 +_,7 @@ + public static final Item PURPUR_BLOCK = registerBlock(Blocks.PURPUR_BLOCK); + public static final Item PURPUR_PILLAR = registerBlock(Blocks.PURPUR_PILLAR); + public static final Item PURPUR_STAIRS = registerBlock(Blocks.PURPUR_STAIRS); +- public static final Item SPAWNER = registerBlock(Blocks.SPAWNER); ++ public static final Item SPAWNER = registerBlock(Blocks.SPAWNER, org.purpurmc.purpur.item.SpawnerItem::new, new Item.Properties().rarity(Rarity.EPIC)); // Purpur - Silk touch spawners + public static final Item CREAKING_HEART = registerBlock(Blocks.CREAKING_HEART); + public static final Item CHEST = registerBlock(Blocks.CHEST, properties -> properties.component(DataComponents.CONTAINER, ItemContainerContents.EMPTY)); + public static final Item CRAFTING_TABLE = registerBlock(Blocks.CRAFTING_TABLE); diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/SpawnerBlock.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/SpawnerBlock.java.patch new file mode 100644 index 000000000..cf68daf1b --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/SpawnerBlock.java.patch @@ -0,0 +1,68 @@ +--- a/net/minecraft/world/level/block/SpawnerBlock.java ++++ b/net/minecraft/world/level/block/SpawnerBlock.java +@@ -43,6 +_,57 @@ + ); + } + ++ // Purpur start - Silk touch spawners ++ @Override ++ public void playerDestroy(Level level, net.minecraft.world.entity.player.Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack, boolean includeDrops, boolean dropExp) { ++ if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.drop.spawners") && isSilkTouch(level, stack)) { ++ ItemStack item = new ItemStack(Blocks.SPAWNER.asItem()); ++ ++ net.minecraft.world.level.SpawnData nextSpawnData = blockEntity instanceof SpawnerBlockEntity spawnerBlock ? spawnerBlock.getSpawner().nextSpawnData : null; ++ java.util.Optional> type = java.util.Optional.empty(); ++ if (nextSpawnData != null) { ++ type = net.minecraft.world.entity.EntityType.by(nextSpawnData.getEntityToSpawn()); ++ net.minecraft.world.level.SpawnData.CODEC.encodeStart(net.minecraft.nbt.NbtOps.INSTANCE, nextSpawnData).result().ifPresent(tag -> item.set(net.minecraft.core.component.DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY.update(compoundTag -> compoundTag.put("Purpur.SpawnData", tag)))); ++ } ++ ++ if (type.isPresent()) { ++ final net.kyori.adventure.text.Component mobName = io.papermc.paper.adventure.PaperAdventure.asAdventure(type.get().getDescription()); ++ ++ String name = level.purpurConfig.silkTouchSpawnerName; ++ if (name != null && !name.isEmpty() && !name.equals("Monster Spawner")) { ++ net.kyori.adventure.text.Component displayName = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(name, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName)); ++ if (name.startsWith("")) { ++ displayName = displayName.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false); ++ } ++ item.set(net.minecraft.core.component.DataComponents.CUSTOM_NAME, io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName)); ++ } ++ ++ List lore = level.purpurConfig.silkTouchSpawnerLore; ++ if (lore != null && !lore.isEmpty()) { ++ ++ List loreComponentList = new java.util.ArrayList<>(); ++ for (String line : lore) { ++ net.kyori.adventure.text.Component lineComponent = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserialize(line, net.kyori.adventure.text.minimessage.tag.resolver.Placeholder.component("mob", mobName)); ++ if (line.startsWith("")) { ++ lineComponent = lineComponent.decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false); ++ } ++ loreComponentList.add(io.papermc.paper.adventure.PaperAdventure.asVanilla(lineComponent)); ++ } ++ ++ item.set(net.minecraft.core.component.DataComponents.LORE, new net.minecraft.world.item.component.ItemLore(loreComponentList, loreComponentList)); ++ } ++ item.set(net.minecraft.core.component.DataComponents.HIDE_ADDITIONAL_TOOLTIP, net.minecraft.util.Unit.INSTANCE); ++ } ++ popResource(level, pos, item); ++ } ++ super.playerDestroy(level, player, pos, state, blockEntity, stack, includeDrops, dropExp); ++ } ++ ++ private boolean isSilkTouch(Level level, ItemStack stack) { ++ return stack != null && level.purpurConfig.silkTouchTools.contains(stack.getItem()) && net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.SILK_TOUCH, stack) >= level.purpurConfig.minimumSilkTouchSpawnerRequire; ++ } ++ // Purpur end - Silk touch spawners ++ + @Override + protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { + super.spawnAfterBreak(state, level, pos, stack, dropExperience); +@@ -51,6 +_,7 @@ + + @Override + public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { ++ if (level.purpurConfig.silkTouchEnabled && isSilkTouch(level, stack)) return 0; // Purpur - Silk touch spawners + if (dropExperience) { + int i = 15 + level.random.nextInt(15) + level.random.nextInt(15); + // this.popExperience(level, pos, i); diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java index 60179ffff..2efc228f8 100644 --- a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java @@ -1,8 +1,14 @@ package org.purpurmc.purpur; +import java.util.ArrayList; import java.util.HashMap; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.entity.monster.Shulker; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import org.bukkit.ChatColor; import org.bukkit.World; import org.bukkit.configuration.ConfigurationSection; import java.util.List; @@ -89,6 +95,38 @@ public class PurpurWorldConfig { idleTimeoutTargetPlayer = getBoolean("gameplay-mechanics.player.idle-timeout.mobs-target", idleTimeoutTargetPlayer); } + public boolean silkTouchEnabled = false; + public String silkTouchSpawnerName = "Monster Spawner"; + public List silkTouchSpawnerLore = new ArrayList<>(); + public List silkTouchTools = new ArrayList<>(); + public int minimumSilkTouchSpawnerRequire = 1; + private void silkTouchSettings() { + if (PurpurConfig.version < 21) { + String oldName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName); + set("gameplay-mechanics.silk-touch.spawner-name", "" + ChatColor.toMM(oldName.replace("{mob}", ""))); + List list = new ArrayList<>(); + getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a ")) + .forEach(line -> list.add("" + ChatColor.toMM(line.toString().replace("{mob}", "")))); + set("gameplay-mechanics.silk-touch.spawner-lore", list); + } + silkTouchEnabled = getBoolean("gameplay-mechanics.silk-touch.enabled", silkTouchEnabled); + silkTouchSpawnerName = getString("gameplay-mechanics.silk-touch.spawner-name", silkTouchSpawnerName); + minimumSilkTouchSpawnerRequire = getInt("gameplay-mechanics.silk-touch.minimal-level", minimumSilkTouchSpawnerRequire); + silkTouchSpawnerLore.clear(); + getList("gameplay-mechanics.silk-touch.spawner-lore", List.of("Spawns a ")) + .forEach(line -> silkTouchSpawnerLore.add(line.toString())); + silkTouchTools.clear(); + getList("gameplay-mechanics.silk-touch.tools", List.of( + "minecraft:iron_pickaxe", + "minecraft:golden_pickaxe", + "minecraft:diamond_pickaxe", + "minecraft:netherite_pickaxe" + )).forEach(key -> { + Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(key.toString())); + if (item != Items.AIR) silkTouchTools.add(item); + }); + } + public boolean babiesAreRidable = true; public boolean untamedTamablesAreRidable = true; public boolean useNightVisionWhenRiding = false; diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java b/purpur-server/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java new file mode 100644 index 000000000..ed50cb211 --- /dev/null +++ b/purpur-server/src/main/java/org/purpurmc/purpur/item/SpawnerItem.java @@ -0,0 +1,40 @@ +package org.purpurmc.purpur.item; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class SpawnerItem extends BlockItem { + + public SpawnerItem(Block block, Properties settings) { + super(block, settings); + } + + @Override + protected boolean updateCustomBlockEntityTag(BlockPos pos, Level level, Player player, ItemStack stack, BlockState state) { + boolean handled = super.updateCustomBlockEntityTag(pos, level, player, stack, state); + if (level.purpurConfig.silkTouchEnabled && player.getBukkitEntity().hasPermission("purpur.place.spawners")) { + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof SpawnerBlockEntity spawner) { + CompoundTag customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + if (customData.contains("Purpur.mob_type")) { + EntityType.byString(customData.getString("Purpur.mob_type")).ifPresent(type -> spawner.getSpawner().setEntityId(type, level, level.random, pos)); + } else if (customData.contains("Purpur.SpawnData")) { + net.minecraft.world.level.SpawnData.CODEC.parse(net.minecraft.nbt.NbtOps.INSTANCE, customData.getCompound("Purpur.SpawnData")).result() + .ifPresent(spawnData -> spawner.getSpawner().nextSpawnData = spawnData); + } + } + } + return handled; + } +}