diff --git a/pom.xml b/pom.xml index ac6fedf..5f7b096 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.xginko.VillagerOptimizer VillagerOptimizer - 1.4.1 + 1.5.0 jar VillagerOptimizer @@ -14,7 +14,7 @@ https://github.com/xGinko/VillagerOptimizer - 16 + 1.8 UTF-8 @@ -107,51 +107,53 @@ 1.20.4-R0.1-SNAPSHOT provided + + + net.kyori + adventure-platform-bukkit + 4.3.2 + + net.kyori adventure-text-minimessage - 4.15.0 - compile + 4.16.0 + net.kyori adventure-text-logger-slf4j - 4.15.0 - compile + 4.16.0 + net.kyori adventure-text-serializer-plain - 4.15.0 - compile + 4.16.0 org.bstats bstats-bukkit 3.0.2 - compile com.github.thatsmusic99 ConfigurationMaster-API v2.0.0-rc.1 - compile - + com.github.ben-manes.caffeine caffeine - 3.1.8 - compile + 2.9.3 com.tcoded FoliaLib 0.3.1 - compile diff --git a/src/main/java/me/xginko/villageroptimizer/VillagerCache.java b/src/main/java/me/xginko/villageroptimizer/VillagerCache.java index 7d994b8..1a11e20 100644 --- a/src/main/java/me/xginko/villageroptimizer/VillagerCache.java +++ b/src/main/java/me/xginko/villageroptimizer/VillagerCache.java @@ -2,10 +2,8 @@ package me.xginko.villageroptimizer; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import org.bukkit.Bukkit; import org.bukkit.entity.Villager; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.time.Duration; import java.util.UUID; @@ -23,11 +21,6 @@ public final class VillagerCache { return this.villagerCache.asMap(); } - public @Nullable WrappedVillager get(@NotNull UUID uuid) { - WrappedVillager wrappedVillager = this.villagerCache.getIfPresent(uuid); - return wrappedVillager == null && Bukkit.getEntity(uuid) instanceof Villager villager ? this.add(villager) : wrappedVillager; - } - public @NotNull WrappedVillager getOrAdd(@NotNull Villager villager) { WrappedVillager wrappedVillager = this.villagerCache.getIfPresent(villager.getUniqueId()); return wrappedVillager == null ? this.add(new WrappedVillager(villager)) : this.add(wrappedVillager); diff --git a/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java b/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java index 577440f..bbf7c15 100644 --- a/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java +++ b/src/main/java/me/xginko/villageroptimizer/VillagerOptimizer.java @@ -5,6 +5,7 @@ import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.LanguageCache; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.Style; @@ -15,14 +16,12 @@ import org.bstats.bukkit.Metrics; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Set; +import java.util.*; import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,80 +29,99 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; public final class VillagerOptimizer extends JavaPlugin { - public static final Style plugin_style = Style.style(TextColor.color(102,255,230), TextDecoration.BOLD); + public static final Style STYLE = Style.style(TextColor.color(102,255,230), TextDecoration.BOLD); private static VillagerOptimizer instance; private static VillagerCache villagerCache; private static FoliaLib foliaLib; - private static HashMap languageCacheMap; + private static Map languageCacheMap; private static Config config; + private static BukkitAudiences audiences; private static ComponentLogger logger; @Override public void onEnable() { instance = this; - logger = ComponentLogger.logger(this.getName()); foliaLib = new FoliaLib(this); + audiences = BukkitAudiences.create(this); + logger = ComponentLogger.logger(this.getName()); - logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("│ _ __ _ __ __ │").style(plugin_style)); - logger.info(Component.text("│ | | / /(_)/ // /___ _ ___ _ ___ ____ │").style(plugin_style)); - logger.info(Component.text("│ | |/ // // // // _ `// _ `// -_)/ __/ │").style(plugin_style)); - logger.info(Component.text("│ |___//_//_//_/ \\_,_/ \\_, / \\__//_/ │").style(plugin_style)); - logger.info(Component.text("│ ____ __ _ /___/_ │").style(plugin_style)); - logger.info(Component.text("│ / __ \\ ___ / /_ (_)__ _ (_)___ ___ ____ │").style(plugin_style)); - logger.info(Component.text("│ / /_/ // _ \\/ __// // ' \\ / //_ // -_)/ __/ │").style(plugin_style)); - logger.info(Component.text("│ \\____// .__/\\__//_//_/_/_//_/ /__/\\__//_/ │").style(plugin_style)); - logger.info(Component.text("│ /_/ by xGinko │").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); + logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("│ _ __ _ __ __ │").style(STYLE)); + logger.info(Component.text("│ | | / /(_)/ // /___ _ ___ _ ___ ____ │").style(STYLE)); + logger.info(Component.text("│ | |/ // // // // _ `// _ `// -_)/ __/ │").style(STYLE)); + logger.info(Component.text("│ |___//_//_//_/ \\_,_/ \\_, / \\__//_/ │").style(STYLE)); + logger.info(Component.text("│ ____ __ _ /___/_ │").style(STYLE)); + logger.info(Component.text("│ / __ \\ ___ / /_ (_)__ _ (_)___ ___ ____ │").style(STYLE)); + logger.info(Component.text("│ / /_/ // _ \\/ __// // ' \\ / //_ // -_)/ __/ │").style(STYLE)); + logger.info(Component.text("│ \\____// .__/\\__//_//_/_/_//_/ /__/\\__//_/ │").style(STYLE)); + logger.info(Component.text("│ /_/ by xGinko │").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); logger.info(Component.text("│ ") - .style(plugin_style).append(Component.text("https://github.com/xGinko/VillagerOptimizer") - .color(NamedTextColor.GRAY)).append(Component.text(" │").style(plugin_style))); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); + .style(STYLE).append(Component.text("https://github.com/xGinko/VillagerOptimizer") + .color(NamedTextColor.GRAY)).append(Component.text(" │").style(STYLE))); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); logger.info(Component.text("│ ") - .style(plugin_style).append(Component.text(" ➤ Loading Translations...").style(plugin_style)) - .append(Component.text(" │").style(plugin_style))); + .style(STYLE).append(Component.text(" ➤ Loading Translations...").style(STYLE)) + .append(Component.text(" │").style(STYLE))); reloadLang(true); logger.info(Component.text("│ ") - .style(plugin_style).append(Component.text(" ➤ Loading Config...").style(plugin_style)) - .append(Component.text(" │").style(plugin_style))); + .style(STYLE).append(Component.text(" ➤ Loading Config...").style(STYLE)) + .append(Component.text(" │").style(STYLE))); reloadConfiguration(); logger.info(Component.text("│ ") - .style(plugin_style).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD)) - .append(Component.text(" │").style(plugin_style))); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("│ │").style(plugin_style)); - logger.info(Component.text("╰────────────────────────────────────────────────────────────╯").style(plugin_style)); + .style(STYLE).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD)) + .append(Component.text(" │").style(STYLE))); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("│ │").style(STYLE)); + logger.info(Component.text("╰────────────────────────────────────────────────────────────╯").style(STYLE)); new Metrics(this, 19954); } - public static VillagerOptimizer getInstance() { + @Override + public void onDisable() { + VillagerOptimizerModule.modules.forEach(VillagerOptimizerModule::disable); + VillagerOptimizerModule.modules.clear(); + if (villagerCache != null) { + villagerCache.cacheMap().clear(); + villagerCache = null; + } + if (audiences != null) { + audiences.close(); + audiences = null; + } + } + + public static @NotNull VillagerOptimizer getInstance() { return instance; } - public static Config getConfiguration() { + public static @NotNull Config getConfiguration() { return config; } - public static VillagerCache getCache() { + public static @NotNull VillagerCache getCache() { return villagerCache; } - public static FoliaLib getFoliaLib() { + public static @NotNull FoliaLib getFoliaLib() { return foliaLib; } - public static ComponentLogger getLog() { + public static @NotNull ComponentLogger getLog() { return logger; } - public static LanguageCache getLang(Locale locale) { + public static @NotNull BukkitAudiences getAudiences() { + return audiences; + } + public static @NotNull LanguageCache getLang(Locale locale) { return getLang(locale.toString().toLowerCase()); } - public static LanguageCache getLang(CommandSender commandSender) { - return commandSender instanceof Player player ? getLang(player.locale()) : getLang(config.default_lang); + public static @NotNull LanguageCache getLang(CommandSender commandSender) { + return commandSender instanceof Player ? getLang(((Player) commandSender).locale()) : getLang(config.default_lang); } - public static LanguageCache getLang(String lang) { + public static @NotNull LanguageCache getLang(String lang) { if (!config.auto_lang) return languageCacheMap.get(config.default_lang.toString().toLowerCase()); return languageCacheMap.getOrDefault(lang.replace("-", "_"), languageCacheMap.get(config.default_lang.toString().toLowerCase())); } @@ -120,9 +138,8 @@ public final class VillagerOptimizer extends JavaPlugin { VillagerOptimizerCommand.reloadCommands(); VillagerOptimizerModule.reloadModules(); config.saveConfig(); - } catch (Exception e) { - logger.error("Error loading config! - " + e.getLocalizedMessage()); - e.printStackTrace(); + } catch (Exception exception) { + logger.error("Error loading config!", exception); } } @@ -134,9 +151,9 @@ public final class VillagerOptimizer extends JavaPlugin { for (String fileName : getDefaultLanguageFiles()) { final String localeString = fileName.substring(fileName.lastIndexOf(File.separator) + 1, fileName.lastIndexOf('.')); if (startup) logger.info( - Component.text("│ ").style(plugin_style) + Component.text("│ ").style(STYLE) .append(Component.text(" "+localeString).color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD)) - .append(Component.text(" │").style(plugin_style))); + .append(Component.text(" │").style(STYLE))); else logger.info(String.format("Found language file for %s", localeString)); languageCacheMap.put(localeString, new LanguageCache(localeString)); } @@ -147,9 +164,9 @@ public final class VillagerOptimizer extends JavaPlugin { String localeString = langMatcher.group(1).toLowerCase(); if (!languageCacheMap.containsKey(localeString)) { // make sure it wasn't a default file that we already loaded if (startup) logger.info( - Component.text("│ ").style(plugin_style) + Component.text("│ ").style(STYLE) .append(Component.text(" "+localeString).color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD)) - .append(Component.text(" │").style(plugin_style))); + .append(Component.text(" │").style(STYLE))); else logger.info(String.format("Found language file for %s", localeString)); languageCacheMap.put(localeString, new LanguageCache(localeString)); } @@ -157,22 +174,21 @@ public final class VillagerOptimizer extends JavaPlugin { } } catch (Exception e) { if (startup) logger.error( - Component.text("│ ").style(plugin_style) + Component.text("│ ").style(STYLE) .append(Component.text("LANG ERROR").color(NamedTextColor.RED).decorate(TextDecoration.BOLD)) - .append(Component.text(" │").style(plugin_style))); - else logger.error("Error loading language files! Language files will not reload to avoid errors, make sure to correct this before restarting the server!"); - e.printStackTrace(); + .append(Component.text(" │").style(STYLE)), e); + else logger.error("Error loading language files! Language files will not reload to avoid errors, make sure to correct this before restarting the server!", e); } } - private Set getDefaultLanguageFiles() { + private @NotNull Set getDefaultLanguageFiles() { try (final JarFile pluginJarFile = new JarFile(this.getFile())) { return pluginJarFile.stream() .map(ZipEntry::getName) .filter(name -> name.startsWith("lang" + File.separator) && name.endsWith(".yml")) .collect(Collectors.toSet()); - } catch (IOException e) { - logger.error("Failed getting default lang files! - "+e.getLocalizedMessage()); + } catch (IOException ioException) { + logger.error("Failed getting default lang files!", ioException); return Collections.emptySet(); } } diff --git a/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java b/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java index 5545fca..720bc8e 100644 --- a/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java +++ b/src/main/java/me/xginko/villageroptimizer/WrappedVillager.java @@ -59,13 +59,14 @@ public final class WrappedVillager { /** * @return True if the villager is optimized by the supported plugin, otherwise false. */ - public boolean isOptimized(Keyring.Spaces namespaces) { - return switch (namespaces) { - case VillagerOptimizer -> dataContainer.has(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING); - case AntiVillagerLag -> dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING) - || dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING) - || dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING); - }; + public boolean isOptimized(Keyring.Spaces namespace) { + if (namespace == Keyring.Spaces.VillagerOptimizer) { + return dataContainer.has(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING); + } else { + return dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING) + || dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING) + || dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING); + } } /** @@ -92,26 +93,23 @@ public final class WrappedVillager { // Keep repeating task until villager is no longer trading with a player if (villager.isTrading()) return; - switch (type) { - case NAMETAG, COMMAND, BLOCK, WORKSTATION -> { - dataContainer.set(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING, type.name()); - villager.setAware(false); + if (type == OptimizationType.NONE) { + if (isOptimized(Keyring.Spaces.VillagerOptimizer)) { + dataContainer.remove(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey()); } - case NONE -> { - if (isOptimized(Keyring.Spaces.VillagerOptimizer)) { - dataContainer.remove(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey()); - } - if (parseOther) { - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) - dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey()); - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) - dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey()); - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) - dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey()); - } - villager.setAware(true); - villager.setAI(true); + if (parseOther) { + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) + dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey()); + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) + dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey()); + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) + dataContainer.remove(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey()); } + villager.setAware(true); + villager.setAI(true); + } else { + dataContainer.set(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING, type.name()); + villager.setAware(false); } // End repeating task once logic is finished @@ -134,26 +132,26 @@ public final class WrappedVillager { } public @NotNull OptimizationType getOptimizationType(Keyring.Spaces namespaces) { - return switch (namespaces) { - case VillagerOptimizer -> { - if (isOptimized(Keyring.Spaces.VillagerOptimizer)) { - yield OptimizationType.valueOf(dataContainer.get(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING)); - } - yield OptimizationType.NONE; + if (namespaces == Keyring.Spaces.VillagerOptimizer) { + if (!isOptimized(Keyring.Spaces.VillagerOptimizer)) { + return OptimizationType.valueOf(dataContainer.get(Keyring.VillagerOptimizer.OPTIMIZATION_TYPE.getKey(), PersistentDataType.STRING)); + } else { + return OptimizationType.NONE; } - case AntiVillagerLag -> { - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) { - yield OptimizationType.BLOCK; - } - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) { - yield OptimizationType.WORKSTATION; - } - if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) { - yield OptimizationType.COMMAND; // Best we can do - } - yield OptimizationType.NONE; + } + if (namespaces == Keyring.Spaces.AntiVillagerLag) { + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_BLOCK.getKey(), PersistentDataType.STRING)) { + return OptimizationType.BLOCK; } - }; + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_WORKSTATION.getKey(), PersistentDataType.STRING)) { + return OptimizationType.WORKSTATION; + } + if (dataContainer.has(Keyring.AntiVillagerLag.OPTIMIZED_ANY.getKey(), PersistentDataType.STRING)) { + return OptimizationType.COMMAND; // Best we can do + } + return OptimizationType.NONE; + } + return OptimizationType.NONE; } /** diff --git a/src/main/java/me/xginko/villageroptimizer/commands/VillagerOptimizerCommand.java b/src/main/java/me/xginko/villageroptimizer/commands/VillagerOptimizerCommand.java index 94dbe43..f344075 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/VillagerOptimizerCommand.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/VillagerOptimizerCommand.java @@ -8,6 +8,7 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandMap; import org.bukkit.command.TabCompleter; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -17,7 +18,7 @@ public interface VillagerOptimizerCommand extends CommandExecutor, TabCompleter String label(); List NO_TABCOMPLETES = Collections.emptyList(); - List RADIUS_TABCOMPLETES = List.of("5", "10", "25", "50"); + List RADIUS_TABCOMPLETES = Arrays.asList("5", "10", "25", "50"); HashSet commands = new HashSet<>(); 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 058cb76..3075ab1 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/optimizevillagers/OptVillagersRadius.java @@ -9,6 +9,7 @@ import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.permissions.Bypass; import me.xginko.villageroptimizer.enums.permissions.Commands; import me.xginko.villageroptimizer.events.VillagerOptimizeEvent; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; @@ -32,9 +33,9 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { public OptVillagersRadius() { Config config = VillagerOptimizer.getConfiguration(); this.max_radius = config.getInt("optimization-methods.commands.optimizevillagers.max-block-radius", 100); - 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.cooldown = config.getInt("optimization-methods.commands.optimizevillagers.cooldown-seconds", 600, + "Cooldown in seconds until a villager can be optimized again using the command.\n" + + "Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.") * 1000L; } @Override @@ -50,18 +51,21 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (!sender.hasPermission(Commands.OPTIMIZE_RADIUS.get())) { - sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission); + KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission); return true; } - if (!(sender instanceof Player player)) { - sender.sendMessage(Component.text("This command can only be executed by a player.") + if (!(sender instanceof Player)) { + KyoriUtil.sendMessage(sender, Component.text("This command can only be executed by a player.") .color(NamedTextColor.RED).decorate(TextDecoration.BOLD)); return true; } + Player player = (Player) sender; + if (args.length != 1) { - VillagerOptimizer.getLang(player.locale()).command_specify_radius.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_specify_radius + .forEach(line -> KyoriUtil.sendMessage(sender, line)); return true; } @@ -71,7 +75,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { final int safeRadius = (int) Math.sqrt(specifiedRadius * specifiedRadius); if (safeRadius == 0) { - VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_radius_invalid + .forEach(line -> KyoriUtil.sendMessage(sender, line)); return true; } @@ -80,7 +85,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%distance%") .replacement(Integer.toString(max_radius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed.forEach(line -> player.sendMessage(line.replaceText(limit))); + VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(limit))); return true; } @@ -114,7 +120,8 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%radius%") .replacement(Integer.toString(safeRadius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby.forEach(line -> player.sendMessage(line.replaceText(radius))); + VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(radius))); return true; } @@ -127,20 +134,20 @@ public class OptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%radius%") .replacement(Integer.toString(safeRadius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_optimize_success.forEach(line -> player.sendMessage(line - .replaceText(success_amount) - .replaceText(radius) - )); + VillagerOptimizer.getLang(player.locale()).command_optimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(success_amount).replaceText(radius))); } if (failCount > 0) { final TextReplacementConfig alreadyOptimized = TextReplacementConfig.builder() .matchLiteral("%amount%") .replacement(Integer.toString(failCount)) .build(); - VillagerOptimizer.getLang(player.locale()).command_optimize_fail.forEach(line -> player.sendMessage(line.replaceText(alreadyOptimized))); + VillagerOptimizer.getLang(player.locale()).command_optimize_fail + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(alreadyOptimized))); } } catch (NumberFormatException e) { - VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_radius_invalid + .forEach(line -> KyoriUtil.sendMessage(player, line)); } return true; 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 e6fb875..7257548 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/unoptimizevillagers/UnOptVillagersRadius.java @@ -7,6 +7,7 @@ import me.xginko.villageroptimizer.commands.VillagerOptimizerCommand; import me.xginko.villageroptimizer.enums.OptimizationType; import me.xginko.villageroptimizer.enums.permissions.Commands; import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.format.NamedTextColor; @@ -27,7 +28,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { private final int max_radius; public UnOptVillagersRadius() { - this.max_radius = VillagerOptimizer.getConfiguration().getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100); + this.max_radius = VillagerOptimizer.getConfiguration() + .getInt("optimization-methods.commands.unoptimizevillagers.max-block-radius", 100); } @Override @@ -43,18 +45,21 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if (!sender.hasPermission(Commands.UNOPTIMIZE_RADIUS.get())) { - sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission); + KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission); return true; } - if (!(sender instanceof Player player)) { - sender.sendMessage(Component.text("This command can only be executed by a player.") + if (!(sender instanceof Player)) { + KyoriUtil.sendMessage(sender, Component.text("This command can only be executed by a player.") .color(NamedTextColor.RED).decorate(TextDecoration.BOLD)); return true; } + Player player = (Player) sender; + if (args.length != 1) { - VillagerOptimizer.getLang(player.locale()).command_specify_radius.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_specify_radius + .forEach(line -> KyoriUtil.sendMessage(sender, line)); return true; } @@ -64,7 +69,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { final int safeRadius = (int) Math.sqrt(specifiedRadius * specifiedRadius); if (safeRadius == 0) { - VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_radius_invalid + .forEach(line -> KyoriUtil.sendMessage(sender, line)); return true; } @@ -73,7 +79,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%distance%") .replacement(Integer.toString(max_radius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed.forEach(line -> player.sendMessage(line.replaceText(limit))); + VillagerOptimizer.getLang(player.locale()).command_radius_limit_exceed + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(limit))); return true; } @@ -102,7 +109,8 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%radius%") .replacement(Integer.toString(safeRadius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby.forEach(line -> player.sendMessage(line.replaceText(radius))); + VillagerOptimizer.getLang(player.locale()).command_no_villagers_nearby + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(radius))); } else { final TextReplacementConfig success_amount = TextReplacementConfig.builder() .matchLiteral("%amount%") @@ -112,13 +120,12 @@ public class UnOptVillagersRadius implements VillagerOptimizerCommand { .matchLiteral("%radius%") .replacement(Integer.toString(safeRadius)) .build(); - VillagerOptimizer.getLang(player.locale()).command_unoptimize_success.forEach(line -> player.sendMessage(line - .replaceText(success_amount) - .replaceText(radius) - )); + VillagerOptimizer.getLang(player.locale()).command_unoptimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(success_amount).replaceText(radius))); } } catch (NumberFormatException e) { - VillagerOptimizer.getLang(player.locale()).command_radius_invalid.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).command_radius_invalid + .forEach(line -> KyoriUtil.sendMessage(player, line)); } return true; diff --git a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/VillagerOptimizerCmd.java b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/VillagerOptimizerCmd.java index 986951d..afb16fa 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/VillagerOptimizerCmd.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/VillagerOptimizerCmd.java @@ -7,13 +7,16 @@ import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.Disabl import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.ReloadSubCmd; import me.xginko.villageroptimizer.commands.villageroptimizer.subcommands.VersionSubCmd; import me.xginko.villageroptimizer.enums.permissions.Commands; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class VillagerOptimizerCmd implements VillagerOptimizerCommand { @@ -21,8 +24,8 @@ public class VillagerOptimizerCmd implements VillagerOptimizerCommand { private final List tabCompleter; public VillagerOptimizerCmd() { - subCommands = List.of(new ReloadSubCmd(), new VersionSubCmd(), new DisableSubCmd()); - tabCompleter = subCommands.stream().map(SubCommand::getLabel).toList(); + subCommands = Arrays.asList(new ReloadSubCmd(), new VersionSubCmd(), new DisableSubCmd()); + tabCompleter = subCommands.stream().map(SubCommand::getLabel).collect(Collectors.toList()); } @Override @@ -55,21 +58,21 @@ public class VillagerOptimizerCmd implements VillagerOptimizerCommand { private void sendCommandOverview(CommandSender sender) { if (!sender.hasPermission(Commands.RELOAD.get()) && !sender.hasPermission(Commands.VERSION.get())) return; - sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); - sender.sendMessage(Component.text("VillagerOptimizer Commands").color(VillagerOptimizer.plugin_style.color())); - sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); - subCommands.forEach(subCommand -> sender.sendMessage( + KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); + KyoriUtil.sendMessage(sender, Component.text("VillagerOptimizer Commands").color(VillagerOptimizer.STYLE.color())); + KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); + subCommands.forEach(subCommand -> KyoriUtil.sendMessage(sender, subCommand.getSyntax().append(Component.text(" - ").color(NamedTextColor.DARK_GRAY)).append(subCommand.getDescription()))); - sender.sendMessage( - Component.text("/optimizevillagers ").color(VillagerOptimizer.plugin_style.color()) + KyoriUtil.sendMessage(sender, + Component.text("/optimizevillagers ").color(VillagerOptimizer.STYLE.color()) .append(Component.text(" - ").color(NamedTextColor.DARK_GRAY)) .append(Component.text("Optimize villagers in a radius").color(NamedTextColor.GRAY)) ); - sender.sendMessage( - Component.text("/unoptmizevillagers ").color(VillagerOptimizer.plugin_style.color()) + KyoriUtil.sendMessage(sender, + Component.text("/unoptmizevillagers ").color(VillagerOptimizer.STYLE.color()) .append(Component.text(" - ").color(NamedTextColor.DARK_GRAY)) .append(Component.text("Unoptimize villagers in a radius").color(NamedTextColor.GRAY)) ); - sender.sendMessage(Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); + KyoriUtil.sendMessage(sender, Component.text("-----------------------------------------------------").color(NamedTextColor.GRAY)); } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/DisableSubCmd.java b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/DisableSubCmd.java index 6dfa75a..e329165 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/DisableSubCmd.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/DisableSubCmd.java @@ -4,6 +4,7 @@ import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.enums.permissions.Commands; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; @@ -23,21 +24,21 @@ public class DisableSubCmd extends SubCommand { @Override public TextComponent getSyntax() { - return Component.text("/villageroptimizer disable").color(VillagerOptimizer.plugin_style.color()); + return Component.text("/villageroptimizer disable").color(VillagerOptimizer.STYLE.color()); } @Override public void perform(CommandSender sender, String[] args) { if (!sender.hasPermission(Commands.DISABLE.get())) { - sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission); + KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission); return; } - sender.sendMessage(Component.text("Disabling VillagerOptimizer...").color(NamedTextColor.RED)); + KyoriUtil.sendMessage(sender, Component.text("Disabling VillagerOptimizer...").color(NamedTextColor.RED)); VillagerOptimizerModule.modules.forEach(VillagerOptimizerModule::disable); VillagerOptimizerModule.modules.clear(); VillagerOptimizer.getCache().cacheMap().clear(); - sender.sendMessage(Component.text("Disabled all plugin listeners and tasks.").color(NamedTextColor.GREEN)); - sender.sendMessage(Component.text("You can enable the plugin again using the reload command.").color(NamedTextColor.YELLOW)); + KyoriUtil.sendMessage(sender, Component.text("Disabled all plugin listeners and tasks.").color(NamedTextColor.GREEN)); + KyoriUtil.sendMessage(sender, Component.text("You can enable the plugin again using the reload command.").color(NamedTextColor.YELLOW)); } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/ReloadSubCmd.java b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/ReloadSubCmd.java index b442866..fc265c7 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/ReloadSubCmd.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/ReloadSubCmd.java @@ -3,6 +3,7 @@ package me.xginko.villageroptimizer.commands.villageroptimizer.subcommands; import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.enums.permissions.Commands; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; @@ -22,20 +23,20 @@ public class ReloadSubCmd extends SubCommand { @Override public TextComponent getSyntax() { - return Component.text("/villageroptimizer reload").color(VillagerOptimizer.plugin_style.color()); + return Component.text("/villageroptimizer reload").color(VillagerOptimizer.STYLE.color()); } @Override public void perform(CommandSender sender, String[] args) { if (!sender.hasPermission(Commands.RELOAD.get())) { - sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission); + KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission); return; } - sender.sendMessage(Component.text("Reloading VillagerOptimizer...").color(NamedTextColor.WHITE)); + KyoriUtil.sendMessage(sender, Component.text("Reloading VillagerOptimizer...").color(NamedTextColor.WHITE)); VillagerOptimizer.getFoliaLib().getImpl().runNextTick(reload -> { // Reload in sync with the server VillagerOptimizer.getInstance().reloadPlugin(); - sender.sendMessage(Component.text("Reload complete.").color(NamedTextColor.GREEN)); + KyoriUtil.sendMessage(sender, Component.text("Reload complete.").color(NamedTextColor.GREEN)); }); } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/VersionSubCmd.java b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/VersionSubCmd.java index e7c4238..7eaed60 100644 --- a/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/VersionSubCmd.java +++ b/src/main/java/me/xginko/villageroptimizer/commands/villageroptimizer/subcommands/VersionSubCmd.java @@ -4,6 +4,7 @@ import io.papermc.paper.plugin.configuration.PluginMeta; import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.commands.SubCommand; import me.xginko.villageroptimizer.enums.permissions.Commands; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; @@ -25,14 +26,14 @@ public class VersionSubCmd extends SubCommand { @Override public TextComponent getSyntax() { - return Component.text("/villageroptimizer version").color(VillagerOptimizer.plugin_style.color()); + return Component.text("/villageroptimizer version").color(VillagerOptimizer.STYLE.color()); } @Override @SuppressWarnings({"deprecation", "UnstableApiUsage"}) public void perform(CommandSender sender, String[] args) { if (!sender.hasPermission(Commands.VERSION.get())) { - sender.sendMessage(VillagerOptimizer.getLang(sender).no_permission); + KyoriUtil.sendMessage(sender, VillagerOptimizer.getLang(sender).no_permission); return; } @@ -52,10 +53,10 @@ public class VersionSubCmd extends SubCommand { author = pluginYML.getAuthors().get(0); } - sender.sendMessage(Component.newline() + KyoriUtil.sendMessage(sender, Component.newline() .append( Component.text(name + " " + version) - .style(VillagerOptimizer.plugin_style) + .style(VillagerOptimizer.STYLE) .clickEvent(ClickEvent.openUrl(website)) ) .append(Component.text(" by ").color(NamedTextColor.GRAY)) diff --git a/src/main/java/me/xginko/villageroptimizer/config/Config.java b/src/main/java/me/xginko/villageroptimizer/config/Config.java index 65452d2..86b6bd8 100644 --- a/src/main/java/me/xginko/villageroptimizer/config/Config.java +++ b/src/main/java/me/xginko/villageroptimizer/config/Config.java @@ -33,16 +33,16 @@ public class Config { "If set to true, will display messages based on client language"); this.cache_keep_time_seconds = getInt("general.cache-keep-time-seconds", 30, "The amount of time in seconds a villager will be kept in the plugin's cache."); - this.support_other_plugins = getBoolean("general.support-avl-villagers", false, """ - Enable if you have previously used AntiVillagerLag (https://www.spigotmc.org/resources/antivillagerlag.102949/).\s - Tries to read pre-existing info like optimization state so players don't need to reoptimize their villagers."""); + this.support_other_plugins = getBoolean("general.support-avl-villagers", false, + "Enable if you have previously used AntiVillagerLag (https://www.spigotmc.org/resources/antivillagerlag.102949/).\n" + + "Tries to read pre-existing info like optimization state so players don't need to reoptimize their villagers."); } public void saveConfig() { try { this.config.save(); - } catch (Exception e) { - VillagerOptimizer.getLog().error("Failed to save config file! - " + e.getLocalizedMessage()); + } catch (Throwable throwable) { + VillagerOptimizer.getLog().error("Failed to save config file!", throwable); } } @@ -51,11 +51,10 @@ public class Config { this.createTitledSection("General", "general"); this.createTitledSection("Optimization", "optimization-methods"); this.config.addDefault("optimization-methods.commands.unoptimizevillagers", null); - this.config.addComment("optimization-methods.commands", """ - If you want to disable commands, negate the following permissions:\s - villageroptimizer.cmd.optimize\s - villageroptimizer.cmd.unoptimize - """); + this.config.addComment("optimization-methods.commands", + "If you want to disable commands, negate the following permissions:\n" + + "villageroptimizer.cmd.optimize\n" + + "villageroptimizer.cmd.unoptimize"); this.config.addDefault("optimization-methods.nametag-optimization.enable", true); this.createTitledSection("Villager Chunk Limit", "villager-chunk-limit"); this.createTitledSection("Gameplay", "gameplay"); diff --git a/src/main/java/me/xginko/villageroptimizer/config/LanguageCache.java b/src/main/java/me/xginko/villageroptimizer/config/LanguageCache.java index e759ec6..d46583d 100644 --- a/src/main/java/me/xginko/villageroptimizer/config/LanguageCache.java +++ b/src/main/java/me/xginko/villageroptimizer/config/LanguageCache.java @@ -7,7 +7,9 @@ import net.kyori.adventure.text.minimessage.MiniMessage; import org.jetbrains.annotations.NotNull; import java.io.File; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class LanguageCache { @@ -28,62 +30,62 @@ public class LanguageCache { File parent = langYML.getParentFile(); if (!parent.exists() && !parent.mkdir()) VillagerOptimizer.getLog().error("Failed to create lang directory."); - // Check if the file already exists and save the one from the plugins resources folder if it does not + // Check if the file already exists and save the one from the plugin's resources folder if it does not if (!langYML.exists()) plugin.saveResource("lang" + File.separator + locale + ".yml", false); - // Finally load the lang file with configmaster + // Finally, load the lang file with configmaster this.lang = ConfigFile.loadConfig(langYML); // General this.no_permission = getTranslation("messages.no-permission", "You don't have permission to use this command."); this.trades_restocked = getListTranslation("messages.trades-restocked", - List.of("All trades have been restocked! Next restock in %time%")); + "All trades have been restocked! Next restock in %time%"); this.optimize_for_trading = getListTranslation("messages.optimize-to-trade", - List.of("You need to optimize this villager before you can trade with it.")); + "You need to optimize this villager before you can trade with it."); this.villager_leveling_up = getListTranslation("messages.villager-leveling-up", - List.of("Villager is currently leveling up! You can use the villager again in %time%.")); + "Villager is currently leveling up! You can use the villager again in %time%."); // Nametag this.nametag_optimize_success = getListTranslation("messages.nametag.optimize-success", - List.of("Successfully optimized villager by using a nametag.")); + "Successfully optimized villager by using a nametag."); this.nametag_on_optimize_cooldown = getListTranslation("messages.nametag.optimize-on-cooldown", - List.of("You need to wait %time% until you can optimize this villager again.")); + "You need to wait %time% until you can optimize this villager again."); this.nametag_unoptimize_success = getListTranslation("messages.nametag.unoptimize-success", - List.of("Successfully unoptimized villager by using a nametag.")); + "Successfully unoptimized villager by using a nametag."); // Block this.block_optimize_success = getListTranslation("messages.block.optimize-success", - List.of("%villagertype% villager successfully optimized using block %blocktype%.")); + "%villagertype% villager successfully optimized using block %blocktype%."); this.block_on_optimize_cooldown = getListTranslation("messages.block.optimize-on-cooldown", - List.of("You need to wait %time% until you can optimize this villager again.")); + "You need to wait %time% until you can optimize this villager again."); this.block_unoptimize_success = getListTranslation("messages.block.unoptimize-success", - List.of("Successfully unoptimized %villagertype% villager by removing %blocktype%.")); + "Successfully unoptimized %villagertype% villager by removing %blocktype%."); // Workstation this.workstation_optimize_success = getListTranslation("messages.workstation.optimize-success", - List.of("%villagertype% villager successfully optimized using workstation %workstation%.")); + "%villagertype% villager successfully optimized using workstation %workstation%."); this.workstation_on_optimize_cooldown = getListTranslation("messages.workstation.optimize-on-cooldown", - List.of("You need to wait %time% until you can optimize this villager again.")); + "You need to wait %time% until you can optimize this villager again."); this.workstation_unoptimize_success = getListTranslation("messages.workstation.unoptimize-success", - List.of("Successfully unoptimized %villagertype% villager by removing workstation block %workstation%.")); + "Successfully unoptimized %villagertype% villager by removing workstation block %workstation%."); // Command this.command_optimize_success = getListTranslation("messages.command.optimize-success", - List.of("Successfully optimized %amount% villager(s) in a radius of %radius% blocks.")); + "Successfully optimized %amount% villager(s) in a radius of %radius% blocks."); this.command_radius_limit_exceed = getListTranslation("messages.command.radius-limit-exceed", - List.of("The radius you entered exceeds the limit of %distance% blocks.")); + "The radius you entered exceeds the limit of %distance% blocks."); this.command_optimize_fail = getListTranslation("messages.command.optimize-fail", - List.of("%amount% villagers couldn't be optimized because they have recently been optimized.")); + "%amount% villagers couldn't be optimized because they have recently been optimized."); this.command_unoptimize_success = getListTranslation("messages.command.unoptimize-success", - List.of("Successfully unoptimized %amount% villager(s) in a radius of %radius% blocks.")); + "Successfully unoptimized %amount% villager(s) in a radius of %radius% blocks."); this.command_specify_radius = getListTranslation("messages.command.specify-radius", - List.of("Please specify a radius.")); + "Please specify a radius."); this.command_radius_invalid = getListTranslation("messages.command.radius-invalid", - List.of("The radius you entered is not a valid number. Try again.")); + "The radius you entered is not a valid number. Try again."); this.command_no_villagers_nearby = getListTranslation("messages.command.no-villagers-nearby", - List.of("Couldn't find any employed villagers within a radius of %radius%.")); + "Couldn't find any employed villagers within a radius of %radius%."); try { this.lang.save(); - } catch (Exception e) { - VillagerOptimizer.getLog().error("Failed to save language file: "+ langYML.getName() +" - " + e.getLocalizedMessage()); + } catch (Throwable throwable) { + VillagerOptimizer.getLog().error("Failed to save language file: "+ langYML.getName(), throwable); } } @@ -92,18 +94,8 @@ public class LanguageCache { return MiniMessage.miniMessage().deserialize(this.lang.getString(path, defaultTranslation)); } - public @NotNull Component getTranslation(@NotNull String path, @NotNull String defaultTranslation, @NotNull String comment) { - this.lang.addDefault(path, defaultTranslation, comment); - return MiniMessage.miniMessage().deserialize(this.lang.getString(path, defaultTranslation)); - } - - public @NotNull List getListTranslation(@NotNull String path, @NotNull List defaultTranslation) { - this.lang.addDefault(path, defaultTranslation); - return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).toList(); - } - - public @NotNull List getListTranslation(@NotNull String path, @NotNull List defaultTranslation, @NotNull String comment) { - this.lang.addDefault(path, defaultTranslation, comment); - return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).toList(); + public @NotNull List getListTranslation(@NotNull String path, @NotNull String... defaultTranslation) { + this.lang.addDefault(path, Arrays.asList(defaultTranslation)); + return this.lang.getStringList(path).stream().map(MiniMessage.miniMessage()::deserialize).collect(Collectors.toList()); } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/enums/Keyring.java b/src/main/java/me/xginko/villageroptimizer/enums/Keyring.java index 7278108..7f5fd5a 100644 --- a/src/main/java/me/xginko/villageroptimizer/enums/Keyring.java +++ b/src/main/java/me/xginko/villageroptimizer/enums/Keyring.java @@ -43,7 +43,6 @@ public class Keyring { * @return a {@link NamespacedKey} that can be used to test for and read data stored by plugins * from a {@link PersistentDataContainer} */ - @SuppressWarnings("deprecation") public static NamespacedKey getKey(@NotNull String pluginName, @NotNull String key) { return new NamespacedKey(pluginName.toLowerCase(Locale.ROOT), key); } @@ -58,7 +57,6 @@ public class Keyring { private final @NotNull NamespacedKey key; - @SuppressWarnings("deprecation") VillagerOptimizer(@NotNull String key) { this.key = new NamespacedKey(Spaces.VillagerOptimizer.namespace(), key); } @@ -80,7 +78,6 @@ public class Keyring { private final @NotNull NamespacedKey key; - @SuppressWarnings("deprecation") AntiVillagerLag(@NotNull String avlKey) { this.key = new NamespacedKey(Spaces.AntiVillagerLag.namespace(), avlKey); } diff --git a/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java b/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java index de6ce7b..3b3e6a3 100644 --- a/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java +++ b/src/main/java/me/xginko/villageroptimizer/events/VillagerOptimizeEvent.java @@ -17,7 +17,12 @@ public class VillagerOptimizeEvent extends Event implements Cancellable { private final @Nullable Player whoOptimised; private boolean isCancelled = false; - public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType optimizationType, @Nullable Player whoOptimised, boolean isAsync) throws IllegalArgumentException { + public VillagerOptimizeEvent( + @NotNull WrappedVillager wrappedVillager, + @NotNull OptimizationType optimizationType, + @Nullable Player whoOptimised, + boolean isAsync + ) throws IllegalArgumentException { super(isAsync); this.wrappedVillager = wrappedVillager; this.whoOptimised = whoOptimised; @@ -28,7 +33,11 @@ public class VillagerOptimizeEvent extends Event implements Cancellable { } } - public VillagerOptimizeEvent(@NotNull WrappedVillager wrappedVillager, @NotNull OptimizationType optimizationType, @Nullable Player whoOptimised) throws IllegalArgumentException { + public VillagerOptimizeEvent( + @NotNull WrappedVillager wrappedVillager, + @NotNull OptimizationType optimizationType, + @Nullable Player whoOptimised + ) throws IllegalArgumentException { this.wrappedVillager = wrappedVillager; this.whoOptimised = whoOptimised; if (optimizationType.equals(OptimizationType.NONE)) { diff --git a/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java b/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java index 4d53c52..4506953 100644 --- a/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java +++ b/src/main/java/me/xginko/villageroptimizer/events/VillagerUnoptimizeEvent.java @@ -17,14 +17,23 @@ public class VillagerUnoptimizeEvent extends Event implements Cancellable { private final @Nullable Player whoUnoptimized; private boolean isCancelled = false; - public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager, @Nullable Player whoUnoptimized, @NotNull OptimizationType unOptimizeType, boolean isAsync) { + public VillagerUnoptimizeEvent( + @NotNull WrappedVillager wrappedVillager, + @Nullable Player whoUnoptimized, + @NotNull OptimizationType unOptimizeType, + boolean isAsync + ) { super(isAsync); this.wrappedVillager = wrappedVillager; this.whoUnoptimized = whoUnoptimized; this.unOptimizeType = unOptimizeType; } - public VillagerUnoptimizeEvent(@NotNull WrappedVillager wrappedVillager, @Nullable Player whoUnoptimized, @NotNull OptimizationType unOptimizeType) { + public VillagerUnoptimizeEvent( + @NotNull WrappedVillager wrappedVillager, + @Nullable Player whoUnoptimized, + @NotNull OptimizationType unOptimizeType + ) { this.wrappedVillager = wrappedVillager; this.whoUnoptimized = whoUnoptimized; this.unOptimizeType = unOptimizeType; diff --git a/src/main/java/me/xginko/villageroptimizer/models/ExpiringSet.java b/src/main/java/me/xginko/villageroptimizer/models/ExpiringSet.java deleted file mode 100644 index a5e44ee..0000000 --- a/src/main/java/me/xginko/villageroptimizer/models/ExpiringSet.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.xginko.villageroptimizer.models; - -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; - -import java.time.Duration; -import java.util.concurrent.TimeUnit; - -public final class ExpiringSet { - - private final Cache cache; - private static final Object PRESENT = new Object(); // Dummy value to associate with an Object in the backing Cache - - public ExpiringSet(long duration, TimeUnit unit) { - this.cache = Caffeine.newBuilder().expireAfterWrite(duration, unit).build(); - } - - public ExpiringSet(Duration duration) { - this.cache = Caffeine.newBuilder().expireAfterWrite(duration).build(); - } - - public void add(E item) { - this.cache.put(item, PRESENT); - } - - public boolean contains(E item) { - return this.cache.getIfPresent(item) != null; - } -} \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/modules/VillagerChunkLimit.java b/src/main/java/me/xginko/villageroptimizer/modules/VillagerChunkLimit.java index c7bb72f..c45047a 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/VillagerChunkLimit.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/VillagerChunkLimit.java @@ -21,10 +21,8 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.stream.Collectors; public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { @@ -41,23 +39,23 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("villager-chunk-limit.enable", """ - Checks chunks for too many villagers and removes excess villagers based on priority."""); - this.check_period = config.getInt("villager-chunk-limit.check-period-in-ticks", 600, """ - Check all loaded chunks every X ticks. 1 second = 20 ticks\s - A shorter delay in between checks is more efficient but is also more resource intense.\s - A larger delay is less resource intense but could become inefficient."""); + config.master().addComment("villager-chunk-limit.enable", + "Checks chunks for too many villagers and removes excess villagers based on priority."); + this.check_period = config.getInt("villager-chunk-limit.check-period-in-ticks", 600, + "Check all loaded chunks every X ticks. 1 second = 20 ticks\n" + + "A shorter delay in between checks is more efficient but is also more resource intense.\n" + + "A larger delay is less resource intense but could become inefficient."); this.skip_unloaded_entity_chunks = config.getBoolean("villager-chunk-limit.skip-if-chunk-has-not-loaded-entities", true, "Does not check chunks that don't have their entities loaded."); this.log_enabled = config.getBoolean("villager-chunk-limit.log-removals", true); this.non_optimized_max_per_chunk = config.getInt("villager-chunk-limit.unoptimized.max-per-chunk", 20, "The maximum amount of unoptimized villagers per chunk."); - this.non_optimized_removal_priority = config.getList("villager-chunk-limit.unoptimized.removal-priority", List.of( + this.non_optimized_removal_priority = config.getList("villager-chunk-limit.unoptimized.removal-priority", Arrays.asList( "NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER", "FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN" - ), """ - Professions that are in the top of the list are going to be scheduled for removal first.\s - Use enums from https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html""" + ), + "Professions that are in the top of the list are going to be scheduled for removal first.\n" + + "Use enums from https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html" ).stream().map(configuredProfession -> { try { return Villager.Profession.valueOf(configuredProfession); @@ -67,10 +65,10 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { "https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html."); return null; } - }).filter(Objects::nonNull).toList(); + }).filter(Objects::nonNull).collect(Collectors.toList()); this.optimized_max_per_chunk = config.getInt("villager-chunk-limit.optimized.max-per-chunk", 60, "The maximum amount of optimized villagers per chunk."); - this.optimized_removal_priority = config.getList("villager-chunk-limit.optimized.removal-priority", List.of( + this.optimized_removal_priority = config.getList("villager-chunk-limit.optimized.removal-priority", Arrays.asList( "NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER", "FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN" )).stream().map(configuredProfession -> { @@ -82,7 +80,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { "https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html."); return null; } - }).filter(Objects::nonNull).toList(); + }).filter(Objects::nonNull).collect(Collectors.toList()); } @Override @@ -159,7 +157,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { if (log_enabled) { VillagerOptimizer.getLog().info(Component.text( "Removed unoptimized villager with profession '" + villager.getProfession().name() + "' at " + - CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color())); } }); } @@ -182,7 +180,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { if (log_enabled) { VillagerOptimizer.getLog().info(Component.text("Removed optimized villager with profession '" + villager.getProfession().name() + "' at " + - CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color())); } }); } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/EnableLeashingVillagers.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/EnableLeashingVillagers.java index 0e95b07..365b015 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/EnableLeashingVillagers.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/EnableLeashingVillagers.java @@ -31,8 +31,8 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("gameplay.villagers-can-be-leashed.enable", """ - Enable leashing of villagers, enabling players to easily move villagers to where they want them to be."""); + config.master().addComment("gameplay.villagers-can-be-leashed.enable", + "Enable leashing of villagers, enabling players to easily move villagers to where they want them to be."); this.only_optimized = config.getBoolean("gameplay.villagers-can-be-leashed.only-optimized", false, "If set to true, only optimized villagers can be leashed."); this.log_enabled = config.getBoolean("gameplay.villagers-can-be-leashed.log", false); @@ -86,7 +86,7 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " leashed a villager at " + - CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(villager.getLocation())).color(VillagerOptimizer.STYLE.color())); } }); } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/LevelOptimizedProfession.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/LevelOptimizedProfession.java index d3c43a5..679c544 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/LevelOptimizedProfession.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/LevelOptimizedProfession.java @@ -7,6 +7,7 @@ import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.WrappedVillager; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.utils.CommonUtil; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.TextReplacementConfig; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; @@ -34,13 +35,13 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("gameplay.level-optimized-profession", """ - This is needed to allow optimized villagers to level up.\s - Temporarily enables the villagers AI to allow it to level up and then disables it again."""); + config.master().addComment("gameplay.level-optimized-profession", + "This is needed to allow optimized villagers to level up.\n" + + "Temporarily enables the villagers AI to allow it to level up and then disables it again."); this.cooldown_millis = TimeUnit.SECONDS.toMillis( - config.getInt("gameplay.level-optimized-profession.level-check-cooldown-seconds", 5, """ - Cooldown in seconds until the level of a villager will be checked and updated again.\s - Recommended to leave as is.""")); + config.getInt("gameplay.level-optimized-profession.level-check-cooldown-seconds", 5, + "Cooldown in seconds until the level of a villager will be checked and updated again.\n" + + "Recommended to leave as is.")); this.notify_player = config.getBoolean("gameplay.level-optimized-profession.notify-player", true, "Tell players to wait when a villager is leveling up."); } @@ -61,12 +62,13 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen return true; } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onTradeScreenClose(InventoryCloseEvent event) { if ( event.getInventory().getType().equals(InventoryType.MERCHANT) - && event.getInventory().getHolder() instanceof Villager villager + && event.getInventory().getHolder() instanceof Villager ) { + Villager villager = (Villager) event.getInventory().getHolder(); WrappedVillager wVillager = villagerCache.getOrAdd(villager); if (!wVillager.isOptimized()) return; @@ -89,7 +91,8 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen .matchLiteral("%time%") .replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getLevelCooldownMillis(cooldown_millis)))) .build(); - VillagerOptimizer.getLang(player.locale()).villager_leveling_up.forEach(line -> player.sendMessage(line.replaceText(timeLeft))); + VillagerOptimizer.getLang(player.locale()).villager_leveling_up + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); } } } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/MakeVillagersSpawnAdult.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/MakeVillagersSpawnAdult.java index f3918a4..57d599e 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/MakeVillagersSpawnAdult.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/MakeVillagersSpawnAdult.java @@ -27,16 +27,16 @@ public class MakeVillagersSpawnAdult implements VillagerOptimizerModule, Listene @Override public boolean shouldEnable() { - return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false, """ - Spawned villagers will immediately be adults.\s - This is to save some more resources as players don't have to keep unoptimized\s - villagers loaded because they have to wait for them to turn into adults before they can\s - optimize them."""); + return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false, + "Spawned villagers will immediately be adults.\n" + + "This is to save some more resources as players don't have to keep unoptimized\n" + + "villagers loaded because they have to wait for them to turn into adults before they can\n" + + "optimize them."); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onVillagerSpawn(CreatureSpawnEvent event) { - if (event.getEntityType() == EntityType.VILLAGER) { + if (event.getEntityType().equals(EntityType.VILLAGER)) { Villager villager = (Villager) event.getEntity(); if (!villager.isAdult()) villager.setAdult(); } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedDamage.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedDamage.java index 49aac94..41c65b2 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedDamage.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedDamage.java @@ -23,7 +23,7 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener private final VillagerCache villagerCache; private final Set damage_causes_to_cancel; - private final boolean cancelKnockback; + private final boolean cancel_knockback; public PreventOptimizedDamage() { shouldEnable(); @@ -31,13 +31,13 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener Config config = VillagerOptimizer.getConfiguration(); config.master().addComment("gameplay.prevent-damage-to-optimized.enable", "Configure what kind of damage you want to cancel for optimized villagers here."); - this.cancelKnockback = config.getBoolean("gameplay.prevent-damage-to-optimized.prevent-knockback-from-entity", true, + this.cancel_knockback = config.getBoolean("gameplay.prevent-damage-to-optimized.prevent-knockback-from-entity", true, "Prevents optimized villagers from getting knocked back by an attacking entity"); this.damage_causes_to_cancel = config.getList("gameplay.prevent-damage-to-optimized.damage-causes-to-cancel", - Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Enum::name).sorted().toList(), """ - These are all current entries in the game. Remove what you do not need blocked.\s - If you want a description or need to add a previously removed type, refer to:\s - https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html""" + Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Enum::name).sorted().collect(Collectors.toList()), + "These are all current entries in the game. Remove what you do not need blocked.\n" + + "If you want a description or need to add a previously removed type, refer to:\n" + + "https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html" ).stream().map(configuredDamageCause -> { try { return EntityDamageEvent.DamageCause.valueOf(configuredDamageCause); @@ -80,7 +80,7 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onKnockbackByEntity(EntityKnockbackByEntityEvent event) { if ( - cancelKnockback + cancel_knockback && event.getEntityType().equals(EntityType.VILLAGER) && villagerCache.getOrAdd((Villager) event.getEntity()).isOptimized() ) { diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedTargeting.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedTargeting.java index 6c10e2e..65d375c 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedTargeting.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventOptimizedTargeting.java @@ -42,11 +42,10 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onTarget(EntityTargetEvent event) { - // Yes, instanceof checks would look way more beautiful here but checking type is much faster Entity target = event.getTarget(); if ( target != null - && target.getType() == EntityType.VILLAGER + && target.getType().equals(EntityType.VILLAGER) && villagerCache.getOrAdd((Villager) target).isOptimized() ) { event.setTarget(null); @@ -59,7 +58,7 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste Entity target = event.getTargetEntity(); if ( target != null - && target.getType() == EntityType.VILLAGER + && target.getType().equals(EntityType.VILLAGER) && villagerCache.getOrAdd((Villager) target).isOptimized() ) { event.setCancelled(true); @@ -69,11 +68,11 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onEntityAttackVillager(EntityDamageByEntityEvent event) { if ( - event.getEntityType() == EntityType.VILLAGER - && event.getDamager() instanceof Mob attacker + event.getEntityType().equals(EntityType.VILLAGER) + && event.getDamager() instanceof Mob && villagerCache.getOrAdd((Villager) event.getEntity()).isOptimized() ) { - attacker.setTarget(null); + ((Mob) event.getDamager()).setTarget(null); } } } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventUnoptimizedTrading.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventUnoptimizedTrading.java index df03822..9672d76 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventUnoptimizedTrading.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/PreventUnoptimizedTrading.java @@ -5,6 +5,7 @@ import me.xginko.villageroptimizer.VillagerCache; import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.permissions.Bypass; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; +import me.xginko.villageroptimizer.utils.KyoriUtil; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; import org.bukkit.event.EventHandler; @@ -24,10 +25,10 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste shouldEnable(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("gameplay.prevent-trading-with-unoptimized.enable", """ - Will prevent players from selecting and using trades of unoptimized villagers.\s - Use this if you have a lot of villagers and therefore want to force your players to optimize them.\s - Inventories can still be opened so players can move villagers around."""); + config.master().addComment("gameplay.prevent-trading-with-unoptimized.enable", + "Will prevent players from selecting and using trades of unoptimized villagers.\n" + + "Use this if you have a lot of villagers and therefore want to force your players to optimize them.\n" + + "Inventories can still be opened so players can move villagers around."); this.notify_player = config.getBoolean("gameplay.prevent-trading-with-unoptimized.notify-player", true, "Sends players a message when they try to trade with an unoptimized villager."); } @@ -48,36 +49,38 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste return VillagerOptimizer.getConfiguration().getBoolean("gameplay.prevent-trading-with-unoptimized.enable", false); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onTradeOpen(TradeSelectEvent event) { + if (!event.getInventory().getType().equals(InventoryType.MERCHANT)) return; if (event.getWhoClicked().hasPermission(Bypass.TRADE_PREVENTION.get())) return; + if (!(event.getInventory().getHolder() instanceof Villager)) return; - if ( - event.getInventory().getType().equals(InventoryType.MERCHANT) - && event.getInventory().getHolder() instanceof Villager villager - && !villagerCache.getOrAdd(villager).isOptimized() - ) { + Villager villager = (Villager) event.getInventory().getHolder(); + + if (!villagerCache.getOrAdd(villager).isOptimized()) { event.setCancelled(true); if (notify_player) { Player player = (Player) event.getWhoClicked(); - VillagerOptimizer.getLang(player.locale()).optimize_for_trading.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).optimize_for_trading + .forEach(line -> KyoriUtil.sendMessage(player, line)); } } } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onInventoryClick(InventoryClickEvent event) { + if (!event.getInventory().getType().equals(InventoryType.MERCHANT)) return; if (event.getWhoClicked().hasPermission(Bypass.TRADE_PREVENTION.get())) return; + if (!(event.getInventory().getHolder() instanceof Villager)) return; - if ( - event.getInventory().getType().equals(InventoryType.MERCHANT) - && event.getInventory().getHolder() instanceof Villager villager - && !villagerCache.getOrAdd(villager).isOptimized() - ) { + Villager villager = (Villager) event.getInventory().getHolder(); + + if (!villagerCache.getOrAdd(villager).isOptimized()) { event.setCancelled(true); if (notify_player) { Player player = (Player) event.getWhoClicked(); - VillagerOptimizer.getLang(player.locale()).optimize_for_trading.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).optimize_for_trading + .forEach(line -> KyoriUtil.sendMessage(player, line)); } } } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RenameOptimizedVillagers.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RenameOptimizedVillagers.java index 181b2a1..d764cab 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RenameOptimizedVillagers.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RenameOptimizedVillagers.java @@ -25,10 +25,11 @@ public class RenameOptimizedVillagers implements VillagerOptimizerModule, Listen shouldEnable(); this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("gameplay.rename-optimized-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("gameplay.rename-optimized-villagers.optimized-name", "Optimized", + config.master().addComment("gameplay.rename-optimized-villagers.enable", + "Will change a villager's name to the name configured below when they are optimized.\n" + + "These names will be removed when unoptimized again if they were not changed in the meantime."); + this.optimized_name = MiniMessage.miniMessage().deserialize( + config.getString("gameplay.rename-optimized-villagers.optimized-name", "Optimized", "The name that will be used to mark optimized villagers. Uses MiniMessage format.")); this.overwrite_previous_name = config.getBoolean("gameplay.rename-optimized-villagers.overwrite-existing-name", false, "If set to true, will rename even if the villager has already been named."); diff --git a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RestockOptimizedTrades.java b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RestockOptimizedTrades.java index 616b953..64af127 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RestockOptimizedTrades.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/gameplay/RestockOptimizedTrades.java @@ -7,9 +7,9 @@ import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.enums.permissions.Bypass; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.utils.CommonUtil; +import me.xginko.villageroptimizer.utils.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; -import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.entity.Villager; @@ -31,9 +31,9 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener shouldEnable(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("gameplay.restock-optimized-trades", """ - This is for automatic restocking of trades for optimized villagers. Optimized Villagers\s - don't have enough AI to restock their trades naturally, so this is here as a workaround."""); + config.master().addComment("gameplay.restock-optimized-trades", + "This is for automatic restocking of trades for optimized villagers. Optimized Villagers\n" + + "don't have enough AI to restock their trades naturally, so this is here as a workaround."); this.restock_delay_millis = config.getInt("gameplay.restock-optimized-trades.delay-in-ticks", 1000, "1 second = 20 ticks. There are 24.000 ticks in a single minecraft day.") * 50L; this.notify_player = config.getBoolean("gameplay.restock-optimized-trades.notify-player", true, @@ -70,18 +70,19 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener if (wVillager.canRestock(restock_delay_millis) || player_bypassing) { wVillager.restock(); wVillager.saveRestockTime(); + if (notify_player && !player_bypassing) { final TextReplacementConfig timeLeft = TextReplacementConfig.builder() .matchLiteral("%time%") .replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getRestockCooldownMillis(restock_delay_millis)))) .build(); - VillagerOptimizer.getLang(player.locale()).trades_restocked.forEach(line -> player.sendMessage(line.replaceText(timeLeft))); + VillagerOptimizer.getLang(player.locale()).trades_restocked + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); } + if (log_enabled) { - final Location location = wVillager.villager().getLocation(); VillagerOptimizer.getLog().info(Component.text("Restocked optimized villager at " + - "x=" + location.getBlockX() + ", y=" + location.getBlockY() + ", z=" + location.getBlockZ() + - ", world=" + location.getWorld().getName()).style(VillagerOptimizer.plugin_style)); + CommonUtil.formatLocation(wVillager.villager().getLocation())).style(VillagerOptimizer.STYLE)); } } } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByBlock.java b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByBlock.java index c8536e3..b665601 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByBlock.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByBlock.java @@ -11,6 +11,7 @@ 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.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import org.bukkit.Location; @@ -28,8 +29,8 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import java.time.Duration; +import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -47,10 +48,10 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { shouldEnable(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("optimization-methods.block-optimization.enable", """ - When enabled, the closest villager standing near a configured block being placed will be optimized.\s - If a configured block is broken nearby, the closest villager will become unoptimized again."""); - this.blocks_that_disable = config.getList("optimization-methods.block-optimization.materials", List.of( + config.master().addComment("optimization-methods.block-optimization.enable", + "When enabled, the closest villager standing near a configured block being placed will be optimized.\n" + + "If a configured block is broken nearby, the closest villager will become unoptimized again."); + this.blocks_that_disable = config.getList("optimization-methods.block-optimization.materials", Arrays.asList( "LAPIS_BLOCK", "GLOWSTONE", "IRON_BLOCK" ), "Values here need to be valid bukkit Material enums for your server version." ).stream().map(configuredMaterial -> { @@ -64,12 +65,12 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { } }).filter(Objects::nonNull).collect(Collectors.toCollection(HashSet::new)); this.cooldown_millis = TimeUnit.SECONDS.toMillis( - config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600, """ - Cooldown in seconds until a villager can be optimized again by using specific blocks.\s - Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""")); - this.search_radius = config.getDouble("optimization-methods.block-optimization.search-radius-in-blocks", 2.0, """ - The radius in blocks a villager can be away from the player when he places an optimize block.\s - The closest unoptimized villager to the player will be optimized.""") / 2; + config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600, + "Cooldown in seconds until a villager can be optimized again by using specific blocks.\n" + + "Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.")); + this.search_radius = config.getDouble("optimization-methods.block-optimization.search-radius-in-blocks", 2.0, + "The radius in blocks a villager can be away from the player when he places an optimize block.\n" + + "The closest unoptimized villager to the player will be optimized.") / 2; this.only_while_sneaking = config.getBoolean("optimization-methods.block-optimization.only-when-sneaking", true, "Only optimize/unoptimize by workstation when player is sneaking during place or break."); this.notify_player = config.getBoolean("optimization-methods.block-optimization.notify-player", true, @@ -123,7 +124,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { if (closestOptimizableVillager == null) return; if (closestOptimizableVillager.canOptimize(cooldown_millis) || player.hasPermission(Bypass.BLOCK_COOLDOWN.get())) { - VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(closestOptimizableVillager, OptimizationType.BLOCK, player, event.isAsynchronous()); + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent( + closestOptimizableVillager, + OptimizationType.BLOCK, + player, + event.isAsynchronous() + ); + if (!optimizeEvent.callEvent()) return; closestOptimizableVillager.setOptimizationType(optimizeEvent.getOptimizationType()); @@ -138,15 +145,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { .matchLiteral("%blocktype%") .replacement(placed.getType().toString().toLowerCase()) .build(); - VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(line -> player.sendMessage(line - .replaceText(vilProfession) - .replaceText(placedMaterial) - )); + VillagerOptimizer.getLang(player.locale()).block_optimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(placedMaterial))); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " optimized villager by block at " + - CommonUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } } else { CommonUtil.shakeHead(closestOptimizableVillager.villager()); @@ -155,7 +160,8 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { .matchLiteral("%time%") .replacement(CommonUtil.formatDuration(Duration.ofMillis(closestOptimizableVillager.getOptimizeCooldownMillis(cooldown_millis)))) .build(); - VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown.forEach(line -> player.sendMessage(line.replaceText(timeLeft))); + VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); } } } @@ -187,7 +193,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { if (closestOptimizedVillager == null) return; - VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, player, OptimizationType.BLOCK, event.isAsynchronous()); + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent( + closestOptimizedVillager, + player, + OptimizationType.BLOCK, + event.isAsynchronous() + ); + if (!unOptimizeEvent.callEvent()) return; closestOptimizedVillager.setOptimizationType(OptimizationType.NONE); @@ -201,15 +213,13 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener { .matchLiteral("%blocktype%") .replacement(broken.getType().toString().toLowerCase()) .build(); - VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(line -> player.sendMessage(line - .replaceText(vilProfession) - .replaceText(brokenMaterial) - )); + VillagerOptimizer.getLang(player.locale()).block_unoptimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(brokenMaterial))); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " unoptimized villager by block at " + - CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByNametag.java b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByNametag.java index c25531b..cebfd97 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByNametag.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByNametag.java @@ -11,6 +11,7 @@ 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.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; @@ -27,13 +28,15 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.time.Duration; +import java.util.Arrays; import java.util.HashSet; -import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class OptimizeByNametag implements VillagerOptimizerModule, Listener { + private final PlainTextComponentSerializer plainTextSerializer; private final VillagerCache villagerCache; private final Set nametags; private final long cooldown; @@ -41,19 +44,21 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { public OptimizeByNametag() { shouldEnable(); + this.plainTextSerializer = PlainTextComponentSerializer.plainText(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("optimization-methods.nametag-optimization.enable", """ - Enable optimization by naming villagers to one of the names configured below.\s - Nametag optimized villagers will be unoptimized again when they are renamed to something else."""); - this.nametags = config.getList("optimization-methods.nametag-optimization.names", List.of("Optimize", "DisableAI"), + config.master().addComment("optimization-methods.nametag-optimization.enable", + "Enable optimization by naming villagers to one of the names configured below.\n" + + "Nametag optimized villagers will be unoptimized again when they are renamed to something else."); + this.nametags = config.getList("optimization-methods.nametag-optimization.names", Arrays.asList("Optimize", "DisableAI"), "Names are case insensitive, capital letters won't matter.") .stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new)); this.consume_nametag = config.getBoolean("optimization-methods.nametag-optimization.nametags-get-consumed", true, "Enable or disable consumption of the used nametag item."); - this.cooldown = config.getInt("optimization-methods.nametag-optimization.optimize-cooldown-seconds", 600, """ - Cooldown in seconds until a villager can be optimized again using a nametag.\s - Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""") * 1000L; + this.cooldown = TimeUnit.SECONDS.toMillis( + config.getInt("optimization-methods.nametag-optimization.optimize-cooldown-seconds", 600, + "Cooldown in seconds until a villager can be optimized again using a nametag.\n" + + "Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.")); this.notify_player = config.getBoolean("optimization-methods.nametag-optimization.notify-player", true, "Sends players a message when they successfully optimized a villager."); this.log_enabled = config.getBoolean("optimization-methods.nametag-optimization.log", false); @@ -82,20 +87,27 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { if (!player.hasPermission(Optimize.NAMETAG.get())) return; ItemStack usedItem = player.getInventory().getItem(event.getHand()); - if (!usedItem.getType().equals(Material.NAME_TAG)) return; + if (usedItem != null && !usedItem.getType().equals(Material.NAME_TAG)) return; + if (!usedItem.hasItemMeta()) return; ItemMeta meta = usedItem.getItemMeta(); if (!meta.hasDisplayName()) return; // 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() - final String name = PlainTextComponentSerializer.plainText().serialize(newVillagerName); + final String name = plainTextSerializer.serialize(newVillagerName); Villager villager = (Villager) event.getRightClicked(); WrappedVillager wVillager = villagerCache.getOrAdd(villager); if (nametags.contains(name.toLowerCase())) { if (wVillager.canOptimize(cooldown) || player.hasPermission(Bypass.NAMETAG_COOLDOWN.get())) { - VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(wVillager, OptimizationType.NAMETAG, player, event.isAsynchronous()); + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent( + wVillager, + OptimizationType.NAMETAG, + player, + event.isAsynchronous() + ); + if (!optimizeEvent.callEvent()) return; if (!consume_nametag) { @@ -107,13 +119,14 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { wVillager.saveOptimizeTime(); if (notify_player) { - VillagerOptimizer.getLang(player.locale()).nametag_optimize_success.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).nametag_optimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line)); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " optimized villager by nametag '" + name + "' at " + - CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } } else { event.setCancelled(true); @@ -123,7 +136,8 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { .matchLiteral("%time%") .replacement(CommonUtil.formatDuration(Duration.ofMillis(wVillager.getOptimizeCooldownMillis(cooldown)))) .build(); - VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line -> player.sendMessage(line.replaceText(timeLeft))); + VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); } } } else { @@ -134,13 +148,14 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener { wVillager.setOptimizationType(OptimizationType.NONE); if (notify_player) { - VillagerOptimizer.getLang(player.locale()).nametag_unoptimize_success.forEach(player::sendMessage); + VillagerOptimizer.getLang(player.locale()).nametag_unoptimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line)); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " unoptimized villager by nametag '" + name + "' at " + - CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(wVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } } } diff --git a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByWorkstation.java b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByWorkstation.java index 2541e40..d86a2ce 100644 --- a/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByWorkstation.java +++ b/src/main/java/me/xginko/villageroptimizer/modules/optimization/OptimizeByWorkstation.java @@ -15,6 +15,7 @@ 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.KyoriUtil; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextReplacementConfig; import org.bukkit.Location; @@ -48,27 +49,27 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.villagerCache = VillagerOptimizer.getCache(); Config config = VillagerOptimizer.getConfiguration(); - config.master().addComment("optimization-methods.workstation-optimization.enable", """ - When enabled, villagers that have a job and have been traded with at least once will become optimized,\s - if near their workstation. If the workstation is broken, the villager will become unoptimized again."""); - this.delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.default-delay-in-ticks", 10, """ - The delay in ticks the plugin should wait before trying to optimize the closest villager on workstation place.\s - Gives the villager time to claim the placed workstation. Minimum delay is 1 Tick (Not recommended)"""), 1) * 50L; - this.resettable_delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.resettable-delay-in-ticks", 60, """ - The delay in ticks the plugin should wait before trying to optimize a villager that can loose its profession\s - by having their workstation destroyed.\s - Intended to fix issues while trade rolling."""), 1) * 50L; + config.master().addComment("optimization-methods.workstation-optimization.enable", + "When enabled, villagers that have a job and have been traded with at least once will become optimized,\n" + + "if near their workstation. If the workstation is broken, the villager will become unoptimized again."); + this.delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.default-delay-in-ticks", 10, + "The delay in ticks the plugin should wait before trying to optimize the closest villager on workstation place.\n" + + "Gives the villager time to claim the placed workstation. Minimum delay is 1 Tick (Not recommended)"), 1) * 50L; + this.resettable_delay_millis = Math.max(config.getInt("optimization-methods.workstation-optimization.delay.resettable-delay-in-ticks", 60, + "The delay in ticks the plugin should wait before trying to optimize a villager that can loose its profession\n" + + "by having their workstation destroyed.\n" + + "Intended to fix issues while trade rolling."), 1) * 50L; this.pending_optimizations = Caffeine.newBuilder() .expireAfterWrite(Duration.ofMillis(Math.max(resettable_delay_millis, delay_millis) + 500L)) .build(); - this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, """ - The radius in blocks a villager can be away from the player when he places a workstation.\s - The closest unoptimized villager to the player will be optimized."""); + this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, + "The radius in blocks a villager can be away from the player when he places a workstation.\n" + + "The closest unoptimized villager to the player will be optimized."); this.search_radius_squared = NumberConversions.square(search_radius); this.cooldown_millis = TimeUnit.SECONDS.toMillis( - config.getInt("optimization-methods.workstation-optimization.optimize-cooldown-seconds", 600, """ - Cooldown in seconds until a villager can be optimized again using a workstation.\s - Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""")); + config.getInt("optimization-methods.workstation-optimization.optimize-cooldown-seconds", 600, + "Cooldown in seconds until a villager can be optimized again using a workstation.\n" + + "Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.")); this.only_while_sneaking = config.getBoolean("optimization-methods.workstation-optimization.only-when-sneaking", true, "Only optimize/unoptimize by workstation when player is sneaking during place or break"); this.notify_player = config.getBoolean("optimization-methods.workstation-optimization.notify-player", true, @@ -132,14 +133,19 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener .matchLiteral("%time%") .replacement(CommonUtil.formatDuration(Duration.ofMillis(finalToOptimize.getOptimizeCooldownMillis(cooldown_millis)))) .build(); - VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line -> player.sendMessage(line - .replaceText(timeLeft) - )); + VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(timeLeft))); } return; } - VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent(finalToOptimize, OptimizationType.WORKSTATION, player, event.isAsynchronous()); + VillagerOptimizeEvent optimizeEvent = new VillagerOptimizeEvent( + finalToOptimize, + OptimizationType.WORKSTATION, + player, + event.isAsynchronous() + ); + if (!optimizeEvent.callEvent()) return; finalToOptimize.setOptimizationType(optimizeEvent.getOptimizationType()); @@ -154,16 +160,14 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener .matchLiteral("%workstation%") .replacement(placed.getType().toString().toLowerCase()) .build(); - VillagerOptimizer.getLang(player.locale()).workstation_optimize_success.forEach(line -> player.sendMessage(line - .replaceText(vilProfession) - .replaceText(placedWorkstation) - )); + VillagerOptimizer.getLang(player.locale()).workstation_optimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(placedWorkstation))); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " optimized villager by workstation (" + placed.getType().toString().toLowerCase() + ") at " + - CommonUtil.formatLocation(finalToOptimize.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(finalToOptimize.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } }, toOptimize.canLooseProfession() ? resettable_delay_millis : delay_millis, TimeUnit.MILLISECONDS)); } @@ -201,7 +205,13 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener if (closestOptimizedVillager == null) return; - VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent(closestOptimizedVillager, player, OptimizationType.WORKSTATION, event.isAsynchronous()); + VillagerUnoptimizeEvent unOptimizeEvent = new VillagerUnoptimizeEvent( + closestOptimizedVillager, + player, + OptimizationType.WORKSTATION, + event.isAsynchronous() + ); + if (!unOptimizeEvent.callEvent()) return; closestOptimizedVillager.setOptimizationType(OptimizationType.NONE); @@ -215,16 +225,14 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener .matchLiteral("%workstation%") .replacement(broken.getType().toString().toLowerCase()) .build(); - VillagerOptimizer.getLang(player.locale()).workstation_unoptimize_success.forEach(line -> player.sendMessage(line - .replaceText(vilProfession) - .replaceText(brokenWorkstation) - )); + VillagerOptimizer.getLang(player.locale()).workstation_unoptimize_success + .forEach(line -> KyoriUtil.sendMessage(player, line.replaceText(vilProfession).replaceText(brokenWorkstation))); } if (log_enabled) { VillagerOptimizer.getLog().info(Component.text(player.getName() + " unoptimized villager by workstation (" + broken.getType().toString().toLowerCase() + ") at " + - CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.plugin_style.color())); + CommonUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(VillagerOptimizer.STYLE.color())); } } } \ No newline at end of file diff --git a/src/main/java/me/xginko/villageroptimizer/utils/CommonUtil.java b/src/main/java/me/xginko/villageroptimizer/utils/CommonUtil.java index 4fa51a3..d6c25c2 100644 --- a/src/main/java/me/xginko/villageroptimizer/utils/CommonUtil.java +++ b/src/main/java/me/xginko/villageroptimizer/utils/CommonUtil.java @@ -12,9 +12,9 @@ public class CommonUtil { public static @NotNull String formatDuration(Duration duration) { if (duration.isNegative()) duration = duration.negated(); - final int seconds = duration.toSecondsPart(); - final int minutes = duration.toMinutesPart(); - final int hours = duration.toHoursPart(); + final int seconds = (int) (duration.getSeconds() % 60); + final int minutes = (int) (duration.toMinutes() % 60); + final int hours = (int) (duration.toHours() % 24); if (hours > 0) { return String.format("%02dh %02dm %02ds", hours, minutes, seconds); @@ -49,21 +49,35 @@ public class CommonUtil { } public static Villager.Profession getWorkstationProfession(@NotNull Material workstation) { - return switch (workstation) { - case BARREL -> Villager.Profession.FISHERMAN; - case CARTOGRAPHY_TABLE -> Villager.Profession.CARTOGRAPHER; - case SMOKER -> Villager.Profession.BUTCHER; - case SMITHING_TABLE -> Villager.Profession.TOOLSMITH; - case GRINDSTONE -> Villager.Profession.WEAPONSMITH; - case BLAST_FURNACE -> Villager.Profession.ARMORER; - case CAULDRON -> Villager.Profession.LEATHERWORKER; - case BREWING_STAND -> Villager.Profession.CLERIC; - case COMPOSTER -> Villager.Profession.FARMER; - case FLETCHING_TABLE -> Villager.Profession.FLETCHER; - case LOOM -> Villager.Profession.SHEPHERD; - case LECTERN -> Villager.Profession.LIBRARIAN; - case STONECUTTER -> Villager.Profession.MASON; - default -> Villager.Profession.NONE; - }; + switch (workstation) { + case BARREL: + return Villager.Profession.FISHERMAN; + case CARTOGRAPHY_TABLE: + return Villager.Profession.CARTOGRAPHER; + case SMOKER: + return Villager.Profession.BUTCHER; + case SMITHING_TABLE: + return Villager.Profession.TOOLSMITH; + case GRINDSTONE: + return Villager.Profession.WEAPONSMITH; + case BLAST_FURNACE: + return Villager.Profession.ARMORER; + case CAULDRON: + return Villager.Profession.LEATHERWORKER; + case BREWING_STAND: + return Villager.Profession.CLERIC; + case COMPOSTER: + return Villager.Profession.FARMER; + case FLETCHING_TABLE: + return Villager.Profession.FLETCHER; + case LOOM: + return Villager.Profession.SHEPHERD; + case LECTERN: + return Villager.Profession.LIBRARIAN; + case STONECUTTER: + return Villager.Profession.MASON; + default: + return Villager.Profession.NONE; + } } } diff --git a/src/main/java/me/xginko/villageroptimizer/utils/KyoriUtil.java b/src/main/java/me/xginko/villageroptimizer/utils/KyoriUtil.java new file mode 100644 index 0000000..6822800 --- /dev/null +++ b/src/main/java/me/xginko/villageroptimizer/utils/KyoriUtil.java @@ -0,0 +1,24 @@ +package me.xginko.villageroptimizer.utils; + +import me.xginko.villageroptimizer.VillagerOptimizer; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.text.Component; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Locale; + +public class KyoriUtil { + + public static void sendMessage(CommandSender sender, Component message) { + VillagerOptimizer.getAudiences().sender(sender).sendMessage(message); + } + + public static void sendActionBar(CommandSender sender, Component message) { + VillagerOptimizer.getAudiences().sender(sender).sendActionBar(message); + } + + public static Locale getLocale(Player player) { + return VillagerOptimizer.getAudiences().player(player).pointers().getOrDefault(Identity.LOCALE, Locale.US); + } +}