From 91871fd7de3c8ff794150ea59a1a19453a4d90af Mon Sep 17 00:00:00 2001 From: xGinko Date: Fri, 29 Sep 2023 17:42:10 +0200 Subject: [PATCH] better renaming logic --- .../villageroptimizer/VillagerOptimizer.java | 4 ++ .../villageroptimizer/WrappedVillager.java | 42 ++++++++++++ .../optimizevillagers/OptVillagersRadius.java | 32 +++------- .../UnOptVillagersRadius.java | 25 ++------ .../xginko/villageroptimizer/enums/Keys.java | 3 +- .../events/VillagerOptimizeEvent.java | 62 ++++++++++++++++++ .../events/VillagerUnoptimizeEvent.java | 42 ++++++++++++ .../modules/RenameOptimizedVillagers.java | 64 +++++++++++++++++++ .../modules/VillagerOptimizerModule.java | 5 +- .../optimizations/OptimizeByBlock.java | 44 ++++--------- .../optimizations/OptimizeByNametag.java | 28 +++++--- .../optimizations/OptimizeByWorkstation.java | 33 ++++------ 12 files changed, 279 insertions(+), 105 deletions(-) create mode 100644 src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java create mode 100644 src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java create mode 100644 src/main/java/me/xginko/villageroptimizer/modules/RenameOptimizedVillagers.java diff --git a/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java b/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java index a2cf2aa..07da4d8 100644 --- a/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java +++ b/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java @@ -13,6 +13,7 @@ import org.bukkit.NamespacedKey; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.entity.Player; +import org.bukkit.event.Event; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -93,6 +94,9 @@ public final class VillagerOptimizer extends JavaPlugin { public static LanguageCache getLang(String lang) { return config.auto_lang ? languageCacheMap.getOrDefault(lang.replace("-", "_"), languageCacheMap.get(config.default_lang.toString().toLowerCase())) : languageCacheMap.get(config.default_lang.toString().toLowerCase()); } + public static void callEvent(Event event) { + instance.getServer().getPluginManager().callEvent(event); + } public void reloadPlugin() { reloadLang(false); diff --git a/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java b/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java index 5dcf0fe..4debf95 100644 --- a/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java +++ b/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java @@ -2,10 +2,15 @@ package me.xginko.villageroptimizer; import me.xginko.villageroptimizer.enums.Keys; import me.xginko.villageroptimizer.enums.OptimizationType; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.entity.Villager; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; public final class WrappedVillager { @@ -24,6 +29,13 @@ public final class WrappedVillager { return villager; } + /** + * @return The data container inside the wrapper. + */ + public @NotNull PersistentDataContainer dataContainer() { + return dataContainer; + } + /** * @return True if the villager is optimized by this plugin, otherwise false. */ @@ -167,4 +179,34 @@ public final class WrappedVillager { public long getLevelCooldownMillis(final long cooldown_millis) { return dataContainer.has(Keys.LAST_LEVELUP.key(), PersistentDataType.LONG) ? (villager.getWorld().getFullTime() - (dataContainer.get(Keys.LAST_LEVELUP.key(), PersistentDataType.LONG) + cooldown_millis)) : cooldown_millis; } + + public void renameForOptimization(final @Nullable Component newName, final boolean replace_existing_name) { + if (replace_existing_name) { + villager.customName(newName); + if (newName == null) dataContainer.remove(Keys.LAST_OPTIMIZE_NAME.key()); + else saveOptimizeName(newName); + } else { + Component currentName = villager.customName(); + if (currentName == null) { + villager.customName(newName); + if (newName == null) dataContainer.remove(Keys.LAST_OPTIMIZE_NAME.key()); + else saveOptimizeName(newName); + } else { + Component lastName = getOptimizeName(); + if (Objects.equals(currentName, lastName)) { + villager.customName(newName); + if (newName == null) dataContainer.remove(Keys.LAST_OPTIMIZE_NAME.key()); + else saveOptimizeName(newName); + } + } + } + } + + public void saveOptimizeName(final Component customName) { + dataContainer.set(Keys.LAST_OPTIMIZE_NAME.key(), PersistentDataType.STRING, MiniMessage.miniMessage().serialize(customName)); + } + + public @Nullable Component getOptimizeName() { + return dataContainer.has(Keys.LAST_OPTIMIZE_NAME.key()) ? MiniMessage.miniMessage().deserialize(dataContainer.get(Keys.LAST_OPTIMIZE_NAME.key(), PersistentDataType.STRING)) : null; + } } diff --git a/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java b/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java index e6b368f..5e734bd 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java @@ -1,17 +1,17 @@ package me.xginko.villageroptimizer.commands.optimizevillagers; -import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerCache; +import me.xginko.villageroptimizer.VillagerOptimizer; +import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.Permissions; -import me.xginko.villageroptimizer.WrappedVillager; +import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; @@ -28,10 +28,8 @@ import java.util.List; public class OptVillagersRadius implements VillagerOptimizerCommand, TabCompleter { private final List tabCompletes = List.of("5", "10", "25", "50"); - private final Component optimizeName; private final long cooldown; private final int maxRadius; - private final boolean shouldRename, overwrite_name; public OptVillagersRadius() { Config config = VillagerOptimizer.getConfiguration(); @@ -39,12 +37,6 @@ public class OptVillagersRadius implements VillagerOptimizerCommand, TabComplete this.cooldown = config.getInt("optimization-methods.commands.optimizevillagers.cooldown-seconds", 600, """ Cooldown in seconds until a villager can be optimized again using the command.\s Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""") * 1000L; - this.shouldRename = config.getBoolean("optimization-methods.commands.rename-optimized-villagers.enable", true, - "Renames villagers to what you configure below when they're optimized."); - this.overwrite_name = config.getBoolean("optimization-methods.commands.rename-optimized-villagers.overwrite-previous-name", false, - "Whether to overwrite the previous name or not."); - this.optimizeName = MiniMessage.miniMessage().deserialize(config.getString("optimization-methods.commands.rename-optimized-villagers.name", "Optimized", - "The MiniMessage formatted name to give optimized villagers.")); } @Override @@ -96,19 +88,13 @@ public class OptVillagersRadius implements VillagerOptimizerCommand, TabComplete WrappedVillager wVillager = villagerCache.getOrAdd(villager); if (wVillager.canOptimize(cooldown)) { - wVillager.setOptimization(OptimizationType.COMMAND); - wVillager.saveOptimizeTime(); - - if (shouldRename) { - if (overwrite_name) { - villager.customName(optimizeName); - } else { - if (villager.customName() == null) - villager.customName(optimizeName); - } + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(wVillager, OptimizationType.COMMAND); + VillagerOptimizer.callEvent(optimizeEvent); + if (!optimizeEvent.isCancelled()) { + wVillager.setOptimization(optimizeEvent.getOptimizationType()); + wVillager.saveOptimizeTime(); + successCount++; } - - successCount++; } else { failCount++; } diff --git a/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java b/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java index d23429e..229790a 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java @@ -4,15 +4,13 @@ import me.xginko.villageroptimizer.VillagerCache; import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; -import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.Permissions; +import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; @@ -29,15 +27,10 @@ import java.util.List; public class UnOptVillagersRadius implements VillagerOptimizerCommand, TabCompleter { private final List tabCompletes = List.of("5", "10", "25", "50"); - private final String optimizeName; private final int maxRadius; - private final boolean shouldRename; public UnOptVillagersRadius() { - Config config = VillagerOptimizer.getConfiguration(); - this.maxRadius = config.getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100); - this.shouldRename = config.getBoolean("optimization-methods.commands.rename-optimized-villagers.enable", true); - this.optimizeName = MiniMessage.miniMessage().stripTags(config.getString("optimization-methods.commands.rename-optimized-villagers.name", "Optimized")); + this.maxRadius = VillagerOptimizer.getConfiguration().getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100); } @Override @@ -88,16 +81,12 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand, TabComple WrappedVillager wVillager = villagerCache.getOrAdd(villager); if (wVillager.isOptimized()) { - wVillager.setOptimization(OptimizationType.NONE); - - if (shouldRename) { - Component vilName = villager.customName(); - if (vilName != null && PlainTextComponentSerializer.plainText().serialize(vilName).equalsIgnoreCase(optimizeName)) { - villager.customName(null); - } + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(wVillager); + VillagerOptimizer.callEvent(unOptimizeEvent); + if (!unOptimizeEvent.isCancelled()) { + wVillager.setOptimization(OptimizationType.NONE); + successCount++; } - - successCount++; } } diff --git a/src/main/java/me/xginko/villageroptimizer/enums/Keys.java b/src/main/java/me/xginko/villageroptimizer/enums/Keys.java index 822cbd5..4c75d96 100644 --- a/src/main/java/me/xginko/villageroptimizer/enums/Keys.java +++ b/src/main/java/me/xginko/villageroptimizer/enums/Keys.java @@ -8,7 +8,8 @@ public enum Keys { OPTIMIZATION_TYPE(VillagerOptimizer.getKey("optimization-type")), LAST_OPTIMIZE(VillagerOptimizer.getKey("last-optimize")), LAST_LEVELUP(VillagerOptimizer.getKey("last-levelup")), - LAST_RESTOCK(VillagerOptimizer.getKey("last-restock")); + LAST_RESTOCK(VillagerOptimizer.getKey("last-restock")), + LAST_OPTIMIZE_NAME(VillagerOptimizer.getKey("last-optimize-name")); private final NamespacedKey key; diff --git a/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java b/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java new file mode 100644 index 0000000..bdf437d --- /dev/null +++ b/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java @@ -0,0 +1,62 @@ +package me.xginko.villageroptimizer.events; + +import me.xginko.villageroptimizer.WrappedVillager; +import me.xginko.villageroptimizer.enums.OptimizationType; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class VillagerOptimizeEvent extends Event implements Cancellable { + + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull WrappedVillager wrappedVillager; + private @NotNull OptimizationType type; + private boolean isCancelled = false; + + public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType type, boolean isAsync) throws IllegalArgumentException { + super(isAsync); + this.wrappedVillager = wrappedVillager; + this.type = type; + + if (type.equals(OptimizationType.NONE)) { + throw new IllegalArgumentException("Type can't be NONE."); + } + } + + public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType type) throws IllegalArgumentException { + this.wrappedVillager = wrappedVillager; + this.type = type; + + if (type.equals(OptimizationType.NONE)) { + throw new IllegalArgumentException("Type can't be NONE."); + } + } + + public @NotNull WrappedVillager getWrappedVillager() { + return wrappedVillager; + } + + public @NotNull OptimizationType getOptimizationType() { + return type; + } + + public void setOptimizationType(@NotNull OptimizationType type) { + this.type = type; + } + + @Override + public void setCancelled(boolean cancel) { + isCancelled = cancel; + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java b/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java new file mode 100644 index 0000000..973fb00 --- /dev/null +++ b/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java @@ -0,0 +1,42 @@ +package me.xginko.villageroptimizer.events; + +import me.xginko.villageroptimizer.WrappedVillager; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class VillagerUnoptimizeEvent extends Event implements Cancellable { + + private static final @NotNull HandlerList handlers = new HandlerList(); + private final @NotNull WrappedVillager wrappedVillager; + private boolean isCancelled = false; + + public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager, boolean isAsync) { + super(isAsync); + this.wrappedVillager = wrappedVillager; + } + + public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager) { + this.wrappedVillager = wrappedVillager; + } + + public @NotNull WrappedVillager getWrappedVillager() { + return wrappedVillager; + } + + @Override + public boolean isCancelled() { + return isCancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.isCancelled = cancel; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlers; + } +} diff --git a/src/main/java/me/xginko/villageroptimizer/modules/RenameOptimizedVillagers.java b/src/main/java/me/xginko/villageroptimizer/modules/RenameOptimizedVillagers.java new file mode 100644 index 0000000..3a04e5b --- /dev/null +++ b/src/main/java/me/xginko/villageroptimizer/modules/RenameOptimizedVillagers.java @@ -0,0 +1,64 @@ +package me.xginko.villageroptimizer.modules; + +import me.xginko.villageroptimizer.VillagerOptimizer; +import me.xginko.villageroptimizer.WrappedVillager; +import me.xginko.villageroptimizer.config.Config; +import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; +import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; + +public class RenameOptimizedVillagers implements VillagerOptimizerModule, Listener { + + private final VillagerOptimizer plugin; + private final Component optimized_name; + private final boolean overwrite_previous_name; + + protected RenameOptimizedVillagers() { + this.plugin = VillagerOptimizer.getInstance(); + Config config = VillagerOptimizer.getConfiguration(); + config.addComment("general.rename-villagers.enable", """ + Will change a villager's name to the name configured below when they are optimized.\s + These names will be removed when unoptimized again if they were not changed in the meantime. + """); + this.optimized_name = MiniMessage.miniMessage().deserialize(config.getString("general.rename-villagers.optimized-name", "Optimized", + "The name that will be used to mark optimized villagers. Uses MiniMessage format.")); + this.overwrite_previous_name = config.getBoolean("general.rename-villagers.overwrite-existing-name", false, + "If set to true, will rename even if the villager has already been named."); + } + + @Override + public void enable() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public void disable() { + HandlerList.unregisterAll(this); + } + + @Override + public boolean shouldEnable() { + return VillagerOptimizer.getConfiguration().getBoolean("general.rename-villagers.enable", true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onOptimize(VillagerOptimizeEvent event) { + WrappedVillager wVillager = event.getWrappedVillager(); + wVillager.villager().getScheduler().runDelayed(plugin, rename -> { + wVillager.renameForOptimization(optimized_name, overwrite_previous_name); + }, null, 10L); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onUnOptimize(VillagerUnoptimizeEvent event) { + WrappedVillager wVillager = event.getWrappedVillager(); + wVillager.villager().getScheduler().runDelayed(plugin, rename -> { + wVillager.renameForOptimization(null, overwrite_previous_name); + }, null, 10L); + } +} diff --git a/src/main/java/me/xginko/villageroptimizer/modules/VillagerOptimizerModule.java b/src/main/java/me/xginko/villageroptimizer/modules/VillagerOptimizerModule.java index 3f619ac..7f17ebe 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/VillagerOptimizerModule.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/VillagerOptimizerModule.java @@ -24,8 +24,6 @@ public interface VillagerOptimizerModule { modules.forEach(VillagerOptimizerModule::disable); modules.clear(); - modules.add(new VillagerChunkLimit()); - modules.add(new OptimizeByNametag()); modules.add(new OptimizeByBlock()); modules.add(new OptimizeByWorkstation()); @@ -38,6 +36,9 @@ public interface VillagerOptimizerModule { modules.add(new PreventVillagerDamage()); modules.add(new PreventVillagerTargetting()); + modules.add(new VillagerChunkLimit()); + modules.add(new RenameOptimizedVillagers()); + modules.forEach(module -> { if (module.shouldEnable()) module.enable(); }); diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByBlock.java b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByBlock.java index a63fe5a..6fcdd83 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByBlock.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByBlock.java @@ -6,13 +6,12 @@ import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.Permissions; +import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; +import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.utils.CommonUtil; import me.xginko.villageroptimizer.utils.LogUtil; -import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -34,10 +33,9 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { private final VillagerCache villagerCache; private final HashSet blocks_that_disable = new HashSet<>(4); - private final Component optimizeName; private final long cooldown; private final double search_radius; - private final boolean onlyWhileSneaking, shouldRename, overwrite_name, shouldLog, shouldNotifyPlayer; + private final boolean onlyWhileSneaking, shouldNotifyPlayer, shouldLog; public OptimizeByBlock() { shouldEnable(); @@ -67,12 +65,6 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { "Only optimize/unoptimize by workstation when player is sneaking during place or break."); this.shouldNotifyPlayer = config.getBoolean("optimization-methods.block-optimization.notify-player", true, "Sends players a message when they successfully optimized or unoptimized a villager."); - this.shouldRename = config.getBoolean("optimization-methods.block-optimization.rename-optimized-villagers.enable", true, - "Renames villagers to what you configure below when they're optimized."); - this.overwrite_name = config.getBoolean("optimization-methods.block-optimization.rename-optimized-villagers.overwrite-previous-name", false, - "Whether to overwrite the previous name or not."); - this.optimizeName = MiniMessage.miniMessage().deserialize(config.getString("optimization-methods.block-optimization.rename-optimized-villagers.name", "Block Optimized", - "The MiniMessage formatted name to give optimized villagers.")); this.shouldLog = config.getBoolean("optimization-methods.block-optimization.log", false); } @@ -122,17 +114,12 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { if (closestOptimizableVillager == null) return; if (closestOptimizableVillager.canOptimize(cooldown) || player.hasPermission(Permissions.Bypass.BLOCK_COOLDOWN.get())) { - closestOptimizableVillager.setOptimization(OptimizationType.BLOCK); - closestOptimizableVillager.saveOptimizeTime(); + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(closestOptimizableVillager, OptimizationType.BLOCK, event.isAsynchronous()); + VillagerOptimizer.callEvent(optimizeEvent); + if (optimizeEvent.isCancelled()) return; - if (shouldRename) { - if (overwrite_name) { - closestOptimizableVillager.villager().customName(optimizeName); - } else { - Villager villager = closestOptimizableVillager.villager(); - if (villager.customName() == null) villager.customName(optimizeName); - } - } + closestOptimizableVillager.setOptimization(optimizeEvent.getOptimizationType()); + closestOptimizableVillager.saveOptimizeTime(); if (shouldNotifyPlayer) { final TextReplacementConfig vilProfession = TextReplacementConfig.builder() @@ -189,21 +176,16 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { if (closestOptimizedVillager == null) return; + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, event.isAsynchronous()); + VillagerOptimizer.callEvent(unOptimizeEvent); + if (unOptimizeEvent.isCancelled()) return; + closestOptimizedVillager.setOptimization(OptimizationType.NONE); - Villager villager = closestOptimizedVillager.villager(); - - if (shouldRename) { - Component vilName = villager.customName(); - if (vilName != null && PlainTextComponentSerializer.plainText().serialize(vilName).equalsIgnoreCase(PlainTextComponentSerializer.plainText().serialize(optimizeName))) { - villager.customName(null); - } - } - if (shouldNotifyPlayer) { final TextReplacementConfig vilProfession = TextReplacementConfig.builder() .matchLiteral("%vil_profession%") - .replacement(villager.getProfession().toString().toLowerCase()) + .replacement(closestOptimizedVillager.villager().getProfession().toString().toLowerCase()) .build(); final TextReplacementConfig brokenMaterial = TextReplacementConfig.builder() .matchLiteral("%blocktype%") diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByNametag.java b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByNametag.java index 61369f2..e27d967 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByNametag.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByNametag.java @@ -6,6 +6,8 @@ import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.Permissions; +import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; +import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.utils.CommonUtil; import net.kyori.adventure.text.Component; @@ -31,7 +33,7 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { private final VillagerCache villagerCache; private final HashSet nametags = new HashSet<>(4); private final long cooldown; - private final boolean shouldLog, shouldNotifyPlayer, consumeNametag; + private final boolean consumeNametag, shouldNotifyPlayer, shouldLog; public OptimizeByNametag() { shouldEnable(); @@ -82,19 +84,22 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { // Get component name first, so we can manually name the villager when canceling the event to avoid item consumption. Component newVillagerName = meta.displayName(); assert newVillagerName != null; // Legitimate since we checked for hasDisplayName() - Villager villager = (Villager) event.getRightClicked(); - - if (!consumeNametag) { - event.setCancelled(true); - villager.customName(newVillagerName); - } - final String name = PlainTextComponentSerializer.plainText().serialize(newVillagerName); + Villager villager = (Villager) event.getRightClicked(); WrappedVillager wVillager = villagerCache.getOrAdd(villager); if (nametags.contains(name.toLowerCase())) { if (wVillager.canOptimize(cooldown) || player.hasPermission(Permissions.Bypass.NAMETAG_COOLDOWN.get())) { - wVillager.setOptimization(OptimizationType.NAMETAG); + if (!consumeNametag) { + event.setCancelled(true); + villager.customName(newVillagerName); + } + + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(wVillager, OptimizationType.NAMETAG, event.isAsynchronous()); + VillagerOptimizer.callEvent(optimizeEvent); + if (optimizeEvent.isCancelled()) return; + + wVillager.setOptimization(optimizeEvent.getOptimizationType()); wVillager.saveOptimizeTime(); if (shouldNotifyPlayer) @@ -114,7 +119,12 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { } } else { if (wVillager.isOptimized()) { + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(wVillager, event.isAsynchronous()); + VillagerOptimizer.callEvent(unOptimizeEvent); + if (unOptimizeEvent.isCancelled()) return; + wVillager.setOptimization(OptimizationType.NONE); + if (shouldNotifyPlayer) VillagerOptimizer.getLang(player.locale()).nametag_unoptimize_success.forEach(player::sendMessage); if (shouldLog) diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByWorkstation.java b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByWorkstation.java index 4d2c273..d74da06 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByWorkstation.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimizations/OptimizeByWorkstation.java @@ -6,12 +6,13 @@ import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.Permissions; +import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; +import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.utils.CommonUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -106,17 +107,12 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener if (closestOptimizableVillager == null) return; if (closestOptimizableVillager.canOptimize(cooldown) || player.hasPermission(Permissions.Bypass.WORKSTATION_COOLDOWN.get())) { - closestOptimizableVillager.setOptimization(OptimizationType.WORKSTATION); - closestOptimizableVillager.saveOptimizeTime(); + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(closestOptimizableVillager, OptimizationType.WORKSTATION, event.isAsynchronous()); + VillagerOptimizer.callEvent(optimizeEvent); + if (optimizeEvent.isCancelled()) return; - if (shouldRename) { - if (overwrite_name) { - closestOptimizableVillager.villager().customName(optimizeName); - } else { - Villager villager = closestOptimizableVillager.villager(); - if (villager.customName() == null) villager.customName(optimizeName); - } - } + closestOptimizableVillager.setOptimization(optimizeEvent.getOptimizationType()); + closestOptimizableVillager.saveOptimizeTime(); if (shouldNotifyPlayer) { final TextReplacementConfig vilProfession = TextReplacementConfig.builder() @@ -177,21 +173,16 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener if (closestOptimizedVillager == null) return; + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, event.isAsynchronous()); + VillagerOptimizer.callEvent(unOptimizeEvent); + if (unOptimizeEvent.isCancelled()) return; + closestOptimizedVillager.setOptimization(OptimizationType.NONE); - Villager villager = closestOptimizedVillager.villager(); - - if (shouldRename) { - Component vilName = villager.customName(); - if (vilName != null && PlainTextComponentSerializer.plainText().serialize(vilName).equalsIgnoreCase(PlainTextComponentSerializer.plainText().serialize(optimizeName))) { - villager.customName(null); - } - } - if (shouldNotifyPlayer) { final TextReplacementConfig vilProfession = TextReplacementConfig.builder() .matchLiteral("%vil_profession%") - .replacement(villager.getProfession().toString().toLowerCase()) + .replacement(closestOptimizedVillager.villager().getProfession().toString().toLowerCase()) .build(); final TextReplacementConfig brokenWorkstation = TextReplacementConfig.builder() .matchLiteral("%workstation%")