From ef4bcec26c749d7cf1527a7edcd874344347ca9e Mon Sep 17 00:00:00 2001 From: MrJeremyFisher Date: Mon, 5 Jan 2026 02:12:56 -0500 Subject: [PATCH 1/3] rename locking --- .../simpleadminhacks-paper/build.gradle.kts | 1 + .../hacks/basic/NameLocker.java | 85 +++++++++++++++++++ .../hacks/basic/NameLockerFMListener.java | 43 ++++++++++ .../src/main/resources/config.yml | 2 + .../src/main/resources/plugin.yml | 2 +- 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java create mode 100644 plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java diff --git a/plugins/simpleadminhacks-paper/build.gradle.kts b/plugins/simpleadminhacks-paper/build.gradle.kts index dc4276170..bbdad3400 100644 --- a/plugins/simpleadminhacks-paper/build.gradle.kts +++ b/plugins/simpleadminhacks-paper/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { compileOnly(project(":plugins:banstick-paper")) compileOnly(project(":plugins:bastion-paper")) compileOnly(project(":plugins:exilepearl-paper")) + compileOnly(project(":plugins:factorymod-paper")) compileOnly("me.clip:placeholderapi:2.11.6") compileOnly(libs.protocollib) diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java new file mode 100644 index 000000000..6acd64596 --- /dev/null +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java @@ -0,0 +1,85 @@ +package com.programmerdan.minecraft.simpleadminhacks.hacks.basic; + +import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks; +import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack; +import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig; +import java.util.List; +import java.util.Objects; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class NameLocker extends BasicHack { + + final NamespacedKey lockedKey = new NamespacedKey(plugin, "name-locked"); + + public NameLocker(SimpleAdminHacks plugin, BasicHackConfig config) { + super(plugin, config); + } + + @Override + public void onEnable() { + super.onEnable(); + if (plugin.getServer().getPluginManager().getPlugin("FactoryMod") != null) { + plugin.getServer() + .getPluginManager() + .registerEvents( + new NameLockerFMListener(lockedKey), plugin); + } + } + + @Override + public void onDisable() { + super.onDisable(); + } + + @EventHandler + public void onPrepareLock(PrepareAnvilEvent event) { + if (event.getInventory().getSecondItem() == null || !event.getInventory().getSecondItem().getType().equals(Material.HONEYCOMB)) + return; + + ItemStack itemToBeLocked = event.getInventory().getFirstItem(); + + if (itemToBeLocked == null) return; + + ItemMeta itemMeta = itemToBeLocked.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getView().setRepairCost(Integer.MAX_VALUE); // Cheap trick to get the X because it's nice. + event.setResult(ItemStack.empty()); + } else if (!pdc.has(lockedKey)) { + // We can't put honeycomb on anything so we have to manually do the result setup. + ItemStack result = event.getInventory().getFirstItem().clone(); + result.editMeta(meta -> { + meta.setDisplayName(event.getView().getRenameText()); + meta.getPersistentDataContainer().set(lockedKey, PersistentDataType.BOOLEAN, true); + meta.lore(List.of(Component.text().content("Name-locked").build())); // Just to make it clear. If we can change the message in the anvil this should be removed. + }); + event.getView().setRepairCost(1); // We need to do this so the client will let the user withdraw the item + event.setResult(result); + } + } + + @EventHandler + public void onTryRename(PrepareAnvilEvent event) { + ItemStack itemToBeRenamed = event.getInventory().getFirstItem(); + if (itemToBeRenamed == null || Objects.equals(event.getView().getRenameText(), itemToBeRenamed.displayName().toString())) + return; // Not renaming + + ItemMeta itemMeta = itemToBeRenamed.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getView().setRepairCost(999); // Cheap trick to get the X because it's nice. If there is a better way it should be done that way + event.setResult(ItemStack.empty()); + // Can we change the text? Like "Too Expensive!" - > "Can't Rename!"? + } + } +} diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java new file mode 100644 index 000000000..bad488fe3 --- /dev/null +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java @@ -0,0 +1,43 @@ +package com.programmerdan.minecraft.simpleadminhacks.hacks.basic; + +import com.github.igotyou.FactoryMod.events.FactoryActivateEvent; +import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.NamespacedKey; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class NameLockerFMListener implements Listener { + + NamespacedKey lockedKey; + + public NameLockerFMListener(NamespacedKey lockedKey) { + this.lockedKey = lockedKey; + } + + @EventHandler + public void onTryWordbank(FactoryActivateEvent event) { + if (!(event.getFactory() instanceof FurnCraftChestFactory fac)) return; + if (!fac.getCurrentRecipe().getTypeIdentifier().equals("WORDBANK")) return; + + ItemStack itemToBeRenamed = fac.getInputInventory().getItem(0); + + if (itemToBeRenamed == null) + return; + + ItemMeta itemMeta = itemToBeRenamed.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getActivator().sendMessage(Component.text() + .color(NamedTextColor.RED) + .content("You cannot wordbank name-locked items")); + event.setCancelled(true); + } + } +} diff --git a/plugins/simpleadminhacks-paper/src/main/resources/config.yml b/plugins/simpleadminhacks-paper/src/main/resources/config.yml index e12345259..e8af4434f 100644 --- a/plugins/simpleadminhacks-paper/src/main/resources/config.yml +++ b/plugins/simpleadminhacks-paper/src/main/resources/config.yml @@ -138,6 +138,8 @@ hacks: enabled: true MapCopyProtection: enabled: true + NameLocker: + enabled: true OldEnchanting: enabled: true # Hides what enchantment will be granted within the Enchanting Table diff --git a/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml b/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml index b2c7fddb6..72f7b14a1 100644 --- a/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml +++ b/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ author: ProgrammerDan authors: [ ProgrammerDan, Maxopoly ] version: ${version} depend: [ CivModCore ] -softdepend: [ CombatTagPlus, NameLayer, Citadel, ProtocolLib, BanStick, ExilePearl, PlaceholderAPI ] +softdepend: [ CombatTagPlus, NameLayer, Citadel, ProtocolLib, BanStick, ExilePearl, PlaceholderAPI, FactoryMod ] api-version: 1.21.3 commands: hacks: From 295a96735f069496d69a1500719ac31f4498ab24 Mon Sep 17 00:00:00 2001 From: MrJeremyFisher Date: Mon, 5 Jan 2026 02:12:56 -0500 Subject: [PATCH 2/3] rename locking --- .../simpleadminhacks-paper/build.gradle.kts | 1 + .../hacks/basic/NameLocker.java | 85 +++++++++++++++++++ .../hacks/basic/NameLockerFMListener.java | 43 ++++++++++ .../src/main/resources/config.yml | 2 + .../src/main/resources/plugin.yml | 2 +- 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java create mode 100644 plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java diff --git a/plugins/simpleadminhacks-paper/build.gradle.kts b/plugins/simpleadminhacks-paper/build.gradle.kts index dc4276170..bbdad3400 100644 --- a/plugins/simpleadminhacks-paper/build.gradle.kts +++ b/plugins/simpleadminhacks-paper/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { compileOnly(project(":plugins:banstick-paper")) compileOnly(project(":plugins:bastion-paper")) compileOnly(project(":plugins:exilepearl-paper")) + compileOnly(project(":plugins:factorymod-paper")) compileOnly("me.clip:placeholderapi:2.11.6") compileOnly(libs.protocollib) diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java new file mode 100644 index 000000000..d83c00c1d --- /dev/null +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java @@ -0,0 +1,85 @@ +package com.programmerdan.minecraft.simpleadminhacks.hacks.basic; + +import com.programmerdan.minecraft.simpleadminhacks.SimpleAdminHacks; +import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHack; +import com.programmerdan.minecraft.simpleadminhacks.framework.BasicHackConfig; +import java.util.List; +import java.util.Objects; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.PrepareAnvilEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class NameLocker extends BasicHack { + + final NamespacedKey lockedKey = new NamespacedKey(plugin, "name-locked"); + + public NameLocker(SimpleAdminHacks plugin, BasicHackConfig config) { + super(plugin, config); + } + + @Override + public void onEnable() { + super.onEnable(); + if (plugin.getServer().getPluginManager().getPlugin("FactoryMod") != null) { + plugin.getServer() + .getPluginManager() + .registerEvents( + new NameLockerFMListener(lockedKey), plugin); + } + } + + @Override + public void onDisable() { + super.onDisable(); + } + + @EventHandler + public void onPrepareLock(PrepareAnvilEvent event) { + if (event.getInventory().getSecondItem() == null || !event.getInventory().getSecondItem().getType().equals(Material.HONEYCOMB)) + return; + + ItemStack itemToBeLocked = event.getInventory().getFirstItem(); + + if (itemToBeLocked == null) return; + + ItemMeta itemMeta = itemToBeLocked.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getView().setRepairCost(Integer.MAX_VALUE); // Cheap trick to get the X because it's nice. + event.setResult(ItemStack.empty()); + } else if (!pdc.has(lockedKey)) { + // We can't put honeycomb on anything so we have to manually do the result setup. + ItemStack result = event.getInventory().getFirstItem().clone(); + result.editMeta(meta -> { + meta.setDisplayName(event.getView().getRenameText()); + meta.getPersistentDataContainer().set(lockedKey, PersistentDataType.BOOLEAN, true); + meta.lore(List.of(Component.text().content("Name-locked").build())); // Just to make it clear. If we can change the message in the anvil this should be removed. + }); + event.getView().setRepairCost(1); // We need to do this so the client will let the user withdraw the item + event.setResult(result); + } + } + + @EventHandler + public void onTryRename(PrepareAnvilEvent event) { + ItemStack itemToBeRenamed = event.getInventory().getFirstItem(); + if (itemToBeRenamed == null || Objects.equals(event.getView().getRenameText(), itemToBeRenamed.displayName().toString())) + return; // Not renaming + + ItemMeta itemMeta = itemToBeRenamed.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getView().setRepairCost(Integer.MAX_VALUE); + event.setResult(ItemStack.empty()); + // Can we change the text? Like "Too Expensive!" - > "Can't Rename!"? + } + } +} diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java new file mode 100644 index 000000000..bad488fe3 --- /dev/null +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLockerFMListener.java @@ -0,0 +1,43 @@ +package com.programmerdan.minecraft.simpleadminhacks.hacks.basic; + +import com.github.igotyou.FactoryMod.events.FactoryActivateEvent; +import com.github.igotyou.FactoryMod.factories.FurnCraftChestFactory; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.NamespacedKey; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class NameLockerFMListener implements Listener { + + NamespacedKey lockedKey; + + public NameLockerFMListener(NamespacedKey lockedKey) { + this.lockedKey = lockedKey; + } + + @EventHandler + public void onTryWordbank(FactoryActivateEvent event) { + if (!(event.getFactory() instanceof FurnCraftChestFactory fac)) return; + if (!fac.getCurrentRecipe().getTypeIdentifier().equals("WORDBANK")) return; + + ItemStack itemToBeRenamed = fac.getInputInventory().getItem(0); + + if (itemToBeRenamed == null) + return; + + ItemMeta itemMeta = itemToBeRenamed.getItemMeta(); + PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + + if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked + event.getActivator().sendMessage(Component.text() + .color(NamedTextColor.RED) + .content("You cannot wordbank name-locked items")); + event.setCancelled(true); + } + } +} diff --git a/plugins/simpleadminhacks-paper/src/main/resources/config.yml b/plugins/simpleadminhacks-paper/src/main/resources/config.yml index e12345259..e8af4434f 100644 --- a/plugins/simpleadminhacks-paper/src/main/resources/config.yml +++ b/plugins/simpleadminhacks-paper/src/main/resources/config.yml @@ -138,6 +138,8 @@ hacks: enabled: true MapCopyProtection: enabled: true + NameLocker: + enabled: true OldEnchanting: enabled: true # Hides what enchantment will be granted within the Enchanting Table diff --git a/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml b/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml index b2c7fddb6..72f7b14a1 100644 --- a/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml +++ b/plugins/simpleadminhacks-paper/src/main/resources/plugin.yml @@ -4,7 +4,7 @@ author: ProgrammerDan authors: [ ProgrammerDan, Maxopoly ] version: ${version} depend: [ CivModCore ] -softdepend: [ CombatTagPlus, NameLayer, Citadel, ProtocolLib, BanStick, ExilePearl, PlaceholderAPI ] +softdepend: [ CombatTagPlus, NameLayer, Citadel, ProtocolLib, BanStick, ExilePearl, PlaceholderAPI, FactoryMod ] api-version: 1.21.3 commands: hacks: From 9c71a0820363dd7d77f94caef068a36b3f9f42ba Mon Sep 17 00:00:00 2001 From: MrJeremyFisher Date: Mon, 5 Jan 2026 14:53:24 -0500 Subject: [PATCH 3/3] Fix a few other things --- .../hacks/basic/NameLocker.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java index d83c00c1d..56d6842ca 100644 --- a/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java +++ b/plugins/simpleadminhacks-paper/src/main/java/com/programmerdan/minecraft/simpleadminhacks/hacks/basic/NameLocker.java @@ -6,9 +6,14 @@ import java.util.List; import java.util.Objects; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minecraft.world.inventory.AnvilMenu; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -52,7 +57,7 @@ public void onPrepareLock(PrepareAnvilEvent event) { PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked - event.getView().setRepairCost(Integer.MAX_VALUE); // Cheap trick to get the X because it's nice. + event.getView().setRepairCost(AnvilMenu.DEFAULT_DENIED_COST); // Cheap trick to get the X because it's nice. event.setResult(ItemStack.empty()); } else if (!pdc.has(lockedKey)) { // We can't put honeycomb on anything so we have to manually do the result setup. @@ -67,17 +72,48 @@ public void onPrepareLock(PrepareAnvilEvent event) { } } + @EventHandler + public void onExecuteLock(InventoryClickEvent event) { + if (event.getInventory().getType() != InventoryType.ANVIL || event.getRawSlot() != 2) return; + ItemStack honeyComb = event.getInventory().getItem(1); + if (honeyComb == null || !honeyComb.getType().equals(Material.HONEYCOMB)) + return; + + if (honeyComb.getAmount() > 1) { + honeyComb.setAmount(honeyComb.getAmount() - 1); + ((Player) event.getWhoClicked()).give(honeyComb); // Items in the second slot of an anvil are deleted AFTER InventoryClickEvent so we can't decrement the stack size + } + } + @EventHandler public void onTryRename(PrepareAnvilEvent event) { ItemStack itemToBeRenamed = event.getInventory().getFirstItem(); - if (itemToBeRenamed == null || Objects.equals(event.getView().getRenameText(), itemToBeRenamed.displayName().toString())) - return; // Not renaming + ItemStack resultItem = event.getInventory().getResult(); + if (itemToBeRenamed == null + || resultItem == null) + return; ItemMeta itemMeta = itemToBeRenamed.getItemMeta(); PersistentDataContainer pdc = itemMeta.getPersistentDataContainer(); + checkItem(event, itemToBeRenamed, resultItem, pdc); + + // Now check the other way. This only applies for tools where you can combine them + itemToBeRenamed = event.getInventory().getSecondItem(); + if (itemToBeRenamed == null) + return; + + itemMeta = itemToBeRenamed.getItemMeta(); + pdc = itemMeta.getPersistentDataContainer(); + checkItem(event, itemToBeRenamed, resultItem, pdc); + } + private void checkItem(PrepareAnvilEvent event, ItemStack itemToBeRenamed, ItemStack resultItem, PersistentDataContainer pdc) { if (pdc.has(lockedKey) && Boolean.TRUE.equals(pdc.get(lockedKey, PersistentDataType.BOOLEAN))) { // Item is locked - event.getView().setRepairCost(Integer.MAX_VALUE); + if (Objects.equals(itemToBeRenamed.effectiveName().compact(), resultItem.effectiveName().compact())) + return; // No name change, no enchant change (text colour white->aqua) + if (Objects.equals(itemToBeRenamed.effectiveName().compact().color(NamedTextColor.AQUA).compact(), resultItem.effectiveName().compact())) + return; // No name change, but we are adding an enchantment so the text colour changes + event.getView().setRepairCost(AnvilMenu.DEFAULT_DENIED_COST); event.setResult(ItemStack.empty()); // Can we change the text? Like "Too Expensive!" - > "Can't Rename!"? }