improve module logging

This commit is contained in:
xGinko 2024-03-23 00:40:29 +01:00
parent 005f26b2d3
commit 5068e59175
18 changed files with 235 additions and 139 deletions

View File

@ -45,6 +45,12 @@ public final class VillagerOptimizer extends JavaPlugin {
audiences = BukkitAudiences.create(this); audiences = BukkitAudiences.create(this);
logger = ComponentLogger.logger(getLogger().getName()); logger = ComponentLogger.logger(getLogger().getName());
bStats = new Metrics(this, 19954); bStats = new Metrics(this, 19954);
try {
getDataFolder().mkdirs();
} catch (Exception e) {
logger.error("Failed to create plugin directory! Cannot enable!", e);
getServer().getPluginManager().disablePlugin(this);
}
logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(GenericUtil.STYLE)); logger.info(Component.text("╭────────────────────────────────────────────────────────────╮").style(GenericUtil.STYLE));
logger.info(Component.text("│ │").style(GenericUtil.STYLE)); logger.info(Component.text("│ │").style(GenericUtil.STYLE));
@ -65,14 +71,17 @@ public final class VillagerOptimizer extends JavaPlugin {
.color(NamedTextColor.GRAY)).append(Component.text("").style(GenericUtil.STYLE))); .color(NamedTextColor.GRAY)).append(Component.text("").style(GenericUtil.STYLE)));
logger.info(Component.text("│ │").style(GenericUtil.STYLE)); logger.info(Component.text("│ │").style(GenericUtil.STYLE));
logger.info(Component.text("│ │").style(GenericUtil.STYLE)); logger.info(Component.text("│ │").style(GenericUtil.STYLE));
logger.info(Component.text("") logger.info(Component.text("")
.style(GenericUtil.STYLE).append(Component.text(" ➤ Loading Translations...").style(GenericUtil.STYLE)) .style(GenericUtil.STYLE).append(Component.text(" ➤ Loading Translations...").style(GenericUtil.STYLE))
.append(Component.text("").style(GenericUtil.STYLE))); .append(Component.text("").style(GenericUtil.STYLE)));
reloadLang(true); reloadLang(true);
logger.info(Component.text("") logger.info(Component.text("")
.style(GenericUtil.STYLE).append(Component.text(" ➤ Loading Config...").style(GenericUtil.STYLE)) .style(GenericUtil.STYLE).append(Component.text(" ➤ Loading Config...").style(GenericUtil.STYLE))
.append(Component.text("").style(GenericUtil.STYLE))); .append(Component.text("").style(GenericUtil.STYLE)));
reloadConfiguration(); reloadConfiguration();
logger.info(Component.text("") logger.info(Component.text("")
.style(GenericUtil.STYLE).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD)) .style(GenericUtil.STYLE).append(Component.text(" ✓ Done.").color(NamedTextColor.WHITE).decorate(TextDecoration.BOLD))
.append(Component.text("").style(GenericUtil.STYLE))); .append(Component.text("").style(GenericUtil.STYLE)));
@ -119,7 +128,7 @@ public final class VillagerOptimizer extends JavaPlugin {
public static @NotNull FoliaLib getFoliaLib() { public static @NotNull FoliaLib getFoliaLib() {
return foliaLib; return foliaLib;
} }
public static @NotNull ComponentLogger getLog() { public static @NotNull ComponentLogger getPrefixedLogger() {
return logger; return logger;
} }
public static @NotNull BukkitAudiences getAudiences() { public static @NotNull BukkitAudiences getAudiences() {

View File

@ -16,12 +16,8 @@ public class Config {
public final long cache_keep_time_seconds; public final long cache_keep_time_seconds;
public Config() throws Exception { public Config() throws Exception {
// Create plugin folder first if it does not exist yet
File pluginFolder = VillagerOptimizer.getInstance().getDataFolder();
if (!pluginFolder.exists() && !pluginFolder.mkdir())
VillagerOptimizer.getLog().error("Failed to create plugin directory.");
// Load config.yml with ConfigMaster // Load config.yml with ConfigMaster
this.config = ConfigFile.loadConfig(new File(pluginFolder, "config.yml")); this.config = ConfigFile.loadConfig(new File(VillagerOptimizer.getInstance().getDataFolder(), "config.yml"));
structureConfig(); structureConfig();
@ -42,7 +38,7 @@ public class Config {
try { try {
this.config.save(); this.config.save();
} catch (Throwable throwable) { } catch (Throwable throwable) {
VillagerOptimizer.getLog().error("Failed to save config file!", throwable); VillagerOptimizer.getPrefixedLogger().error("Failed to save config file!", throwable);
} }
} }

View File

@ -30,7 +30,7 @@ public class LanguageCache {
// Check if the lang folder has already been created // Check if the lang folder has already been created
File parent = langYML.getParentFile(); File parent = langYML.getParentFile();
if (!parent.exists() && !parent.mkdir()) if (!parent.exists() && !parent.mkdir())
VillagerOptimizer.getLog().error("Failed to create lang directory."); VillagerOptimizer.getPrefixedLogger().error("Failed to create lang directory.");
// Check if the file already exists and save the one from the plugin's 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()) if (!langYML.exists())
plugin.saveResource("lang/" + locale + ".yml", false); plugin.saveResource("lang/" + locale + ".yml", false);
@ -86,7 +86,7 @@ public class LanguageCache {
try { try {
this.lang.save(); this.lang.save();
} catch (Throwable throwable) { } catch (Throwable throwable) {
VillagerOptimizer.getLog().error("Failed to save language file: "+ langYML.getName(), throwable); VillagerOptimizer.getPrefixedLogger().error("Failed to save language file: " + langYML.getName(), throwable);
} }
} }

View File

@ -6,7 +6,6 @@ import me.xginko.villageroptimizer.VillagerCache;
import me.xginko.villageroptimizer.VillagerOptimizer; import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.utils.GenericUtil; import me.xginko.villageroptimizer.utils.GenericUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Server; import org.bukkit.Server;
import org.bukkit.World; import org.bukkit.World;
@ -39,48 +38,58 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("villager-chunk-limit.enable", config.master().addComment(configPath() + ".enable",
"Checks chunks for too many villagers and removes excess villagers based on priority."); "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, this.check_period = config.getInt(configPath() + ".check-period-in-ticks", 600,
"Check all loaded chunks every X ticks. 1 second = 20 ticks\n" + "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 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."); "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, this.skip_unloaded_entity_chunks = config.getBoolean(configPath() + ".skip-if-chunk-has-not-loaded-entities", true,
"Does not check chunks that don't have their entities loaded."); "Does not check chunks that don't have their entities loaded.");
this.log_enabled = config.getBoolean("villager-chunk-limit.log-removals", true); this.log_enabled = config.getBoolean(configPath() + ".log-removals", true);
this.non_optimized_max_per_chunk = config.getInt("villager-chunk-limit.unoptimized.max-per-chunk", 20, this.non_optimized_max_per_chunk = config.getInt(configPath() + ".unoptimized.max-per-chunk", 20,
"The maximum amount of unoptimized villagers per chunk."); "The maximum amount of unoptimized villagers per chunk.");
this.non_optimized_removal_priority = config.getList("villager-chunk-limit.unoptimized.removal-priority", Arrays.asList( this.non_optimized_removal_priority = config.getList(configPath() + ".unoptimized.removal-priority", Arrays.asList(
"NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER", "NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER",
"FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN" "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.\n" + "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" "Use enums from https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html")
).stream().map(configuredProfession -> { .stream()
.map(configuredProfession -> {
try { try {
return Villager.Profession.valueOf(configuredProfession); return Villager.Profession.valueOf(configuredProfession);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
VillagerOptimizer.getLog().warn("(villager-chunk-limit.unoptimized) Villager profession '"+configuredProfession + warn("(unoptimized) Villager profession '" + configuredProfession +
"' not recognized. Make sure you're using the correct profession enums from " + "' not recognized. Make sure you're using the correct profession enums from " +
"https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html."); "https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html.");
return null; return null;
} }
}).filter(Objects::nonNull).collect(Collectors.toList()); })
this.optimized_max_per_chunk = config.getInt("villager-chunk-limit.optimized.max-per-chunk", 60, .filter(Objects::nonNull)
.collect(Collectors.toList());
this.optimized_max_per_chunk = config.getInt(configPath() + ".optimized.max-per-chunk", 60,
"The maximum amount of optimized villagers per chunk."); "The maximum amount of optimized villagers per chunk.");
this.optimized_removal_priority = config.getList("villager-chunk-limit.optimized.removal-priority", Arrays.asList( this.optimized_removal_priority = config.getList(configPath() + ".optimized.removal-priority", Arrays.asList(
"NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER", "NONE", "NITWIT", "SHEPHERD", "FISHERMAN", "BUTCHER", "CARTOGRAPHER", "LEATHERWORKER",
"FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN" "FLETCHER", "MASON", "FARMER", "ARMORER", "TOOLSMITH", "WEAPONSMITH", "CLERIC", "LIBRARIAN"))
)).stream().map(configuredProfession -> { .stream()
.map(configuredProfession -> {
try { try {
return Villager.Profession.valueOf(configuredProfession); return Villager.Profession.valueOf(configuredProfession);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
VillagerOptimizer.getLog().warn("(villager-chunk-limit.optimized) Villager profession '"+configuredProfession + warn("(optimized) Villager profession '" + configuredProfession + "' not recognized. " +
"' not recognized. Make sure you're using the correct profession enums from " + "Make sure you're using the correct profession enums from " +
"https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html."); "https://jd.papermc.io/paper/1.20/org/bukkit/entity/Villager.Profession.html.");
return null; return null;
} }
}).filter(Objects::nonNull).collect(Collectors.toList()); })
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
@Override
public String configPath() {
return "villager-chunk-limit";
} }
@Override @Override
@ -102,7 +111,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("villager-chunk-limit.enable", false); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false);
} }
@Override @Override
@ -155,9 +164,8 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
scheduler.runAtEntity(villager, kill -> { scheduler.runAtEntity(villager, kill -> {
villager.remove(); villager.remove();
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text( info("Removed unoptimized villager with profession '" + villager.getProfession() + "' at " +
"Removed unoptimized villager with profession '" + villager.getProfession().name() + "' at " + GenericUtil.formatLocation(villager.getLocation()));
GenericUtil.formatLocation(villager.getLocation())).color(GenericUtil.COLOR));
} }
}); });
} }
@ -178,9 +186,8 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
villager.remove(); villager.remove();
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text("Removed optimized villager with profession '" + info("Removed optimized villager with profession '" + villager.getProfession() + "' at " +
villager.getProfession().name() + "' at " + GenericUtil.formatLocation(villager.getLocation()));
GenericUtil.formatLocation(villager.getLocation())).color(GenericUtil.COLOR));
} }
}); });
} }

View File

@ -1,5 +1,6 @@
package me.xginko.villageroptimizer.modules; package me.xginko.villageroptimizer.modules;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.modules.gameplay.*; import me.xginko.villageroptimizer.modules.gameplay.*;
import me.xginko.villageroptimizer.modules.optimization.OptimizeByBlock; import me.xginko.villageroptimizer.modules.optimization.OptimizeByBlock;
import me.xginko.villageroptimizer.modules.optimization.OptimizeByNametag; import me.xginko.villageroptimizer.modules.optimization.OptimizeByNametag;
@ -9,6 +10,7 @@ import java.util.HashSet;
public interface VillagerOptimizerModule { public interface VillagerOptimizerModule {
String configPath();
void enable(); void enable();
void disable(); void disable();
boolean shouldEnable(); boolean shouldEnable();
@ -40,4 +42,26 @@ public interface VillagerOptimizerModule {
if (module.shouldEnable()) module.enable(); if (module.shouldEnable()) module.enable();
}); });
} }
default void trace(String message, Throwable throwable) {
VillagerOptimizer.getPrefixedLogger().trace(logPrefix() + message, throwable);
}
default void error(String message) {
VillagerOptimizer.getPrefixedLogger().error(logPrefix() + message);
}
default void warn(String message) {
VillagerOptimizer.getPrefixedLogger().warn(logPrefix() + message);
}
default void info(String message) {
VillagerOptimizer.getPrefixedLogger().info(logPrefix() + message);
}
default String logPrefix() {
String[] split = configPath().split("\\.");
if (split.length <= 2) return "<" + configPath() + "> ";
return "<" + String.join(".", split[split.length - 2], split[split.length - 1]) + "> ";
}
} }

View File

@ -6,7 +6,6 @@ import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config; import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.GenericUtil; import me.xginko.villageroptimizer.utils.GenericUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -31,11 +30,16 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.villagers-can-be-leashed.enable", config.master().addComment(configPath() + ".enable",
"Enable leashing of villagers, enabling players to easily move villagers to where they want them to be."); "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, this.only_optimized = config.getBoolean(configPath() + ".only-optimized", false,
"If set to true, only optimized villagers can be leashed."); "If set to true, only optimized villagers can be leashed.");
this.log_enabled = config.getBoolean("gameplay.villagers-can-be-leashed.log", false); this.log_enabled = config.getBoolean(configPath() + ".log", false);
}
@Override
public String configPath() {
return "gameplay.villagers-can-be-leashed";
} }
@Override @Override
@ -51,7 +55,7 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-can-be-leashed.enable", false); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false);
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@ -86,8 +90,7 @@ public class EnableLeashingVillagers implements VillagerOptimizerModule, Listene
handItem.subtract(1); // Manually consume for survival players handItem.subtract(1); // Manually consume for survival players
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + " leashed a villager at " + info(player.getName() + " leashed a villager at " + GenericUtil.formatLocation(villager.getLocation()));
GenericUtil.formatLocation(villager.getLocation())).color(GenericUtil.COLOR));
} }
}); });
} }

View File

@ -17,6 +17,11 @@ public class FixOptimisationAfterCure implements VillagerOptimizerModule, Listen
public FixOptimisationAfterCure() {} public FixOptimisationAfterCure() {}
@Override
public String configPath() {
return "post-cure-optimization-fix";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();

View File

@ -35,17 +35,22 @@ public class LevelOptimizedProfession implements VillagerOptimizerModule, Listen
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.level-optimized-profession", config.master().addComment(configPath(),
"This is needed to allow optimized villagers to level up.\n" + "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."); "Temporarily enables the villagers AI to allow it to level up and then disables it again.");
this.cooldown_millis = TimeUnit.SECONDS.toMillis( this.cooldown_millis = TimeUnit.SECONDS.toMillis(
config.getInt("gameplay.level-optimized-profession.level-check-cooldown-seconds", 5, config.getInt(configPath() + ".level-check-cooldown-seconds", 5,
"Cooldown in seconds until the level of a villager will be checked and updated again.\n" + "Cooldown in seconds until the level of a villager will be checked and updated again.\n" +
"Recommended to leave as is.")); "Recommended to leave as is."));
this.notify_player = config.getBoolean("gameplay.level-optimized-profession.notify-player", true, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Tell players to wait when a villager is leveling up."); "Tell players to wait when a villager is leveling up.");
} }
@Override
public String configPath() {
return "gameplay.level-optimized-profession";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();

View File

@ -14,6 +14,11 @@ public class MakeVillagersSpawnAdult implements VillagerOptimizerModule, Listene
public MakeVillagersSpawnAdult() {} public MakeVillagersSpawnAdult() {}
@Override
public String configPath() {
return "gameplay.villagers-spawn-as-adults";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();
@ -27,7 +32,7 @@ public class MakeVillagersSpawnAdult implements VillagerOptimizerModule, Listene
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false, return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false,
"Spawned villagers will immediately be adults.\n" + "Spawned villagers will immediately be adults.\n" +
"This is to save some more resources as players don't have to keep unoptimized\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" + "villagers loaded because they have to wait for them to turn into adults before they can\n" +

View File

@ -29,25 +29,32 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener
shouldEnable(); shouldEnable();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.prevent-damage-to-optimized.enable", config.master().addComment(configPath() + ".enable",
"Configure what kind of damage you want to cancel for optimized villagers here."); "Configure what kind of damage you want to cancel for optimized villagers here.");
this.cancel_knockback = config.getBoolean("gameplay.prevent-damage-to-optimized.prevent-knockback-from-entity", true, this.cancel_knockback = config.getBoolean(configPath() + ".prevent-knockback-from-entity", true,
"Prevents optimized villagers from getting knocked back by an attacking entity"); "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", this.damage_causes_to_cancel = config.getList(configPath() + ".damage-causes-to-cancel",
Arrays.stream(EntityDamageEvent.DamageCause.values()).map(Enum::name).sorted().collect(Collectors.toList()), 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" + "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" + "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" "https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html")
).stream().map(configuredDamageCause -> { .stream()
.map(configuredDamageCause -> {
try { try {
return EntityDamageEvent.DamageCause.valueOf(configuredDamageCause); return EntityDamageEvent.DamageCause.valueOf(configuredDamageCause);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
VillagerOptimizer.getLog().warn("(prevent-damage-to-optimized) DamageCause '"+configuredDamageCause + warn("DamageCause '" + configuredDamageCause + "' not recognized. Please use correct DamageCause enums from: " +
"' not recognized. Please use correct DamageCause enums from: " +
"https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html"); "https://jd.papermc.io/paper/1.20/org/bukkit/event/entity/EntityDamageEvent.DamageCause.html");
return null; return null;
} }
}).filter(Objects::nonNull).collect(Collectors.toCollection(HashSet::new)); })
.filter(Objects::nonNull)
.collect(Collectors.toCollection(HashSet::new));
}
@Override
public String configPath() {
return "gameplay.prevent-damage-to-optimized";
} }
@Override @Override
@ -63,7 +70,7 @@ public class PreventOptimizedDamage implements VillagerOptimizerModule, Listener
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.prevent-damage-to-optimized.enable", true); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", true);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

View File

@ -23,6 +23,11 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
} }
@Override
public String configPath() {
return "gameplay.prevent-entities-from-targeting-optimized";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();
@ -36,7 +41,7 @@ public class PreventOptimizedTargeting implements VillagerOptimizerModule, Liste
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.prevent-entities-from-targeting-optimized.enable", true, return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", true,
"Prevents hostile entities from targeting optimized villagers."); "Prevents hostile entities from targeting optimized villagers.");
} }

View File

@ -25,14 +25,19 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste
shouldEnable(); shouldEnable();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.prevent-trading-with-unoptimized.enable", config.master().addComment(configPath() + ".enable",
"Will prevent players from selecting and using trades of unoptimized villagers.\n" + "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" + "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."); "Inventories can still be opened so players can move villagers around.");
this.notify_player = config.getBoolean("gameplay.prevent-trading-with-unoptimized.notify-player", true, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Sends players a message when they try to trade with an unoptimized villager."); "Sends players a message when they try to trade with an unoptimized villager.");
} }
@Override
public String configPath() {
return "gameplay.prevent-trading-with-unoptimized";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();
@ -46,7 +51,7 @@ public class PreventUnoptimizedTrading implements VillagerOptimizerModule, Liste
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.prevent-trading-with-unoptimized.enable", false); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

View File

@ -8,7 +8,6 @@ import me.xginko.villageroptimizer.enums.Permissions;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.GenericUtil; import me.xginko.villageroptimizer.utils.GenericUtil;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.TextReplacementConfig;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -31,14 +30,19 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener
shouldEnable(); shouldEnable();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.restock-optimized-trades", config.master().addComment(configPath(),
"This is for automatic restocking of trades for optimized villagers. Optimized Villagers\n" + "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."); "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, this.restock_delay_millis = config.getInt(configPath() + ".delay-in-ticks", 1000,
"1 second = 20 ticks. There are 24.000 ticks in a single minecraft day.") * 50L; "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, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Sends the player a message when the trades were restocked on a clicked villager."); "Sends the player a message when the trades were restocked on a clicked villager.");
this.log_enabled = config.getBoolean("gameplay.restock-optimized-trades.log", false); this.log_enabled = config.getBoolean(configPath() + ".log", false);
}
@Override
public String configPath() {
return "gameplay.restock-optimized-trades";
} }
@Override @Override
@ -81,8 +85,7 @@ public class RestockOptimizedTrades implements VillagerOptimizerModule, Listener
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text("Restocked optimized villager at " + info("Restocked optimized villager at " + GenericUtil.formatLocation(wVillager.villager().getLocation()));
GenericUtil.formatLocation(wVillager.villager().getLocation())).color(GenericUtil.COLOR));
} }
} }
} }

View File

@ -19,6 +19,11 @@ public class UnoptimizeOnJobLoose implements VillagerOptimizerModule, Listener {
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
} }
@Override
public String configPath() {
return "gameplay.unoptimize-on-job-loose";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();
@ -32,7 +37,7 @@ public class UnoptimizeOnJobLoose implements VillagerOptimizerModule, Listener {
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.unoptimize-on-job-loose.enable", true, return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", true,
"Villagers that get their jobs reset will become unoptimized again."); "Villagers that get their jobs reset will become unoptimized again.");
} }

View File

@ -24,6 +24,11 @@ public class VisuallyHighlightOptimized implements VillagerOptimizerModule, List
"Will make optimized villagers glow."); "Will make optimized villagers glow.");
} }
@Override
public String configPath() {
return "gameplay.outline-optimized-villagers";
}
@Override @Override
public void enable() { public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance(); VillagerOptimizer plugin = VillagerOptimizer.getInstance();

View File

@ -45,34 +45,41 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
shouldEnable(); shouldEnable();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("optimization-methods.block-optimization.enable", config.master().addComment(configPath() + ".enable",
"When enabled, the closest villager standing near a configured block being placed will be optimized.\n" + "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."); "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( this.blocks_that_disable = config.getList(configPath() + ".materials", Arrays.asList(
"LAPIS_BLOCK", "GLOWSTONE", "IRON_BLOCK" "LAPIS_BLOCK", "GLOWSTONE", "IRON_BLOCK"
), "Values here need to be valid bukkit Material enums for your server version." ), "Values here need to be valid bukkit Material enums for your server version.")
).stream().map(configuredMaterial -> { .stream()
.map(configuredMaterial -> {
try { try {
return Material.valueOf(configuredMaterial); return Material.valueOf(configuredMaterial);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
VillagerOptimizer.getLog().warn("(block-optimization) Material '" + configuredMaterial + warn("Material '" + configuredMaterial + "' not recognized. Please use correct Material enums from: " +
"' not recognized. Please use correct Material enums from: " +
"https://jd.papermc.io/paper/1.20/org/bukkit/Material.html"); "https://jd.papermc.io/paper/1.20/org/bukkit/Material.html");
return null; return null;
} }
}).filter(Objects::nonNull).collect(Collectors.toCollection(HashSet::new)); })
.filter(Objects::nonNull)
.collect(Collectors.toCollection(HashSet::new));
this.cooldown_millis = TimeUnit.SECONDS.toMillis( this.cooldown_millis = TimeUnit.SECONDS.toMillis(
config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600, config.getInt(configPath() + ".optimize-cooldown-seconds", 600,
"Cooldown in seconds until a villager can be optimized again by using specific blocks.\n" + "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.")); "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, this.search_radius = config.getDouble(configPath() + ".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 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; "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, this.only_while_sneaking = config.getBoolean(configPath() + ".only-when-sneaking", true,
"Only optimize/unoptimize by block when player is sneaking during place or break."); "Only optimize/unoptimize by block when player is sneaking during place or break.");
this.notify_player = config.getBoolean("optimization-methods.block-optimization.notify-player", true, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Sends players a message when they successfully optimized or unoptimized a villager."); "Sends players a message when they successfully optimized or unoptimized a villager.");
this.log_enabled = config.getBoolean("optimization-methods.block-optimization.log", false); this.log_enabled = config.getBoolean(configPath() + ".log", false);
}
@Override
public String configPath() {
return "optimization-methods.block-optimization";
} }
@Override @Override
@ -88,7 +95,7 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("optimization-methods.block-optimization.enable", false); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@ -144,7 +151,7 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + " optimized villager by block at " + VillagerOptimizer.getPrefixedLogger().info(Component.text(player.getName() + " optimized villager by block at " +
GenericUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(GenericUtil.COLOR)); GenericUtil.formatLocation(closestOptimizableVillager.villager().getLocation())).color(GenericUtil.COLOR));
} }
} else { } else {
@ -209,7 +216,7 @@ public class OptimizeByBlock implements VillagerOptimizerModule, Listener {
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + " unoptimized villager by block at " + VillagerOptimizer.getPrefixedLogger().info(Component.text(player.getName() + " unoptimized villager by block at " +
GenericUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(GenericUtil.COLOR)); GenericUtil.formatLocation(closestOptimizedVillager.villager().getLocation())).color(GenericUtil.COLOR));
} }
} }

View File

@ -43,21 +43,26 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
shouldEnable(); shouldEnable();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("optimization-methods.nametag-optimization.enable", config.master().addComment(configPath() + ".enable",
"Enable optimization by naming villagers to one of the names configured below.\n" + "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."); "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"), this.nametags = config.getList(configPath() + ".names", Arrays.asList("Optimize", "DisableAI"),
"Names are case insensitive, capital letters won't matter.") "Names are case insensitive, capital letters won't matter.")
.stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new)); .stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
this.consume_nametag = config.getBoolean("optimization-methods.nametag-optimization.nametags-get-consumed", true, this.consume_nametag = config.getBoolean(configPath() + ".nametags-get-consumed", true,
"Enable or disable consumption of the used nametag item."); "Enable or disable consumption of the used nametag item.");
this.cooldown = TimeUnit.SECONDS.toMillis( this.cooldown = TimeUnit.SECONDS.toMillis(
config.getInt("optimization-methods.nametag-optimization.optimize-cooldown-seconds", 600, config.getInt(configPath() + ".optimize-cooldown-seconds", 600,
"Cooldown in seconds until a villager can be optimized again using a nametag.\n" + "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.")); "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, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Sends players a message when they successfully optimized a villager."); "Sends players a message when they successfully optimized a villager.");
this.log_enabled = config.getBoolean("optimization-methods.nametag-optimization.log", false); this.log_enabled = config.getBoolean(configPath() + ".log", false);
}
@Override
public String configPath() {
return "optimization-methods.nametag-optimization";
} }
@Override @Override
@ -73,7 +78,7 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("optimization-methods.nametag-optimization.enable", true); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", true);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@ -120,9 +125,8 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + info(player.getName() + " optimized villager using nametag '" + nameTagPlainText + "' at " +
" optimized villager by nametag '" + nameTagPlainText + "' at " + GenericUtil.formatLocation(wVillager.villager().getLocation()));
GenericUtil.formatLocation(wVillager.villager().getLocation())).color(GenericUtil.COLOR));
} }
} else { } else {
event.setCancelled(true); event.setCancelled(true);
@ -154,9 +158,8 @@ public class OptimizeByNametag implements VillagerOptimizerModule, Listener {
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + info(player.getName() + " unoptimized villager using nametag '" + nameTagPlainText + "' at " +
" unoptimized villager by nametag '" + nameTagPlainText + "' at " + GenericUtil.formatLocation(wVillager.villager().getLocation()));
GenericUtil.formatLocation(wVillager.villager().getLocation())).color(GenericUtil.COLOR));
} }
} }
} }

View File

@ -12,7 +12,6 @@ import me.xginko.villageroptimizer.events.VillagerUnoptimizeEvent;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule; import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.GenericUtil; import me.xginko.villageroptimizer.utils.GenericUtil;
import me.xginko.villageroptimizer.utils.KyoriUtil; import me.xginko.villageroptimizer.utils.KyoriUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig; import net.kyori.adventure.text.TextReplacementConfig;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -44,24 +43,29 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
this.scheduler = VillagerOptimizer.getFoliaLib().getImpl(); this.scheduler = VillagerOptimizer.getFoliaLib().getImpl();
this.villagerCache = VillagerOptimizer.getCache(); this.villagerCache = VillagerOptimizer.getCache();
Config config = VillagerOptimizer.getConfiguration(); Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("optimization-methods.workstation-optimization.enable", config.master().addComment(configPath() + ".enable",
"When enabled, villagers that have a job and have been traded with at least once will become optimized,\n" + "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."); "if near their workstation. If the workstation is broken, the villager will become unoptimized again.");
this.check_duration_ticks = Math.max(config.getInt("optimization-methods.workstation-optimization.check-linger-duration-ticks", 100, this.check_duration_ticks = Math.max(config.getInt(configPath() + ".check-linger-duration-ticks", 100,
"After a workstation has been placed, the plugin will wait for the configured amount of time in ticks\n" + "After a workstation has been placed, the plugin will wait for the configured amount of time in ticks\n" +
"for a villager to claim that workstation. Not recommended to go below 100 ticks."), 1); "for a villager to claim that workstation. Not recommended to go below 100 ticks."), 1);
this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, this.search_radius = config.getDouble(configPath() + ".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 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."); "The closest unoptimized villager to the player will be optimized.");
this.cooldown_millis = TimeUnit.SECONDS.toMillis( this.cooldown_millis = TimeUnit.SECONDS.toMillis(
Math.max(1, config.getInt("optimization-methods.workstation-optimization.optimize-cooldown-seconds", 600, Math.max(1, config.getInt(configPath() + ".optimize-cooldown-seconds", 600,
"Cooldown in seconds until a villager can be optimized again using a workstation.\n" + "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."))); "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, this.only_while_sneaking = config.getBoolean(configPath() + ".only-when-sneaking", true,
"Only optimize/unoptimize by workstation when player is sneaking during place or break. Useful for villager rolling."); "Only optimize/unoptimize by workstation when player is sneaking during place or break. Useful for villager rolling.");
this.notify_player = config.getBoolean("optimization-methods.workstation-optimization.notify-player", true, this.notify_player = config.getBoolean(configPath() + ".notify-player", true,
"Sends players a message when they successfully optimized a villager."); "Sends players a message when they successfully optimized a villager.");
this.log_enabled = config.getBoolean("optimization-methods.workstation-optimization.log", false); this.log_enabled = config.getBoolean(configPath() + ".log", false);
}
@Override
public String configPath() {
return "optimization-methods.workstation-optimization";
} }
@Override @Override
@ -77,7 +81,7 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("optimization-methods.workstation-optimization.enable", false); return VillagerOptimizer.getConfiguration().getBoolean(configPath() + ".enable", false);
} }
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@ -146,9 +150,8 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + info(player.getName() + " optimized villager using workstation " + placed.getType() + " at " +
" optimized villager by workstation (" + placed.getType().toString().toLowerCase() + ") at " + GenericUtil.formatLocation(wrapped.villager().getLocation()));
GenericUtil.formatLocation(wrapped.villager().getLocation())).color(GenericUtil.COLOR));
} }
taskComplete.set(true); taskComplete.set(true);
@ -211,9 +214,8 @@ public class OptimizeByWorkstation implements VillagerOptimizerModule, Listener
} }
if (log_enabled) { if (log_enabled) {
VillagerOptimizer.getLog().info(Component.text(player.getName() + info(player.getName() + " unoptimized villager using workstation " + broken.getType() + " at " +
" unoptimized villager by workstation (" + broken.getType().toString().toLowerCase() + ") at " + GenericUtil.formatLocation(closestOptimized.villager().getLocation()));
GenericUtil.formatLocation(closestOptimized.villager().getLocation())).color(GenericUtil.COLOR));
} }
} }
} }