better villagercache
This commit is contained in:
parent
6501b38dd8
commit
5f0c4e2f00
52
src/main/java/me/xginko/villageroptimizer/VillagerCache.java
Normal file
52
src/main/java/me/xginko/villageroptimizer/VillagerCache.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package me.xginko.villageroptimizer;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import me.xginko.villageroptimizer.models.WrappedVillager;
|
||||||
|
import org.bukkit.entity.Villager;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class VillagerCache {
|
||||||
|
|
||||||
|
private final Cache<UUID, WrappedVillager> villagerCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(30)).build();
|
||||||
|
|
||||||
|
protected VillagerCache() {}
|
||||||
|
|
||||||
|
public Collection<WrappedVillager> getAll() {
|
||||||
|
return this.villagerCache.asMap().values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable WrappedVillager get(UUID uuid) {
|
||||||
|
return villagerCache.getIfPresent(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappedVillager getOrAddIfAbsent(Villager villager) {
|
||||||
|
WrappedVillager wrappedVillager = villagerCache.getIfPresent(villager.getUniqueId());
|
||||||
|
if (wrappedVillager == null) wrappedVillager = new WrappedVillager(villager);
|
||||||
|
this.villagerCache.put(villager.getUniqueId(), wrappedVillager); // refresh cache
|
||||||
|
return wrappedVillager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappedVillager add(WrappedVillager villager) {
|
||||||
|
villagerCache.put(villager.villager().getUniqueId(), villager);
|
||||||
|
return villager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappedVillager add(Villager villager) {
|
||||||
|
WrappedVillager wrapped = new WrappedVillager(villager);
|
||||||
|
villagerCache.put(villager.getUniqueId(), wrapped);
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(WrappedVillager villager) {
|
||||||
|
return villagerCache.getIfPresent(villager.villager().getUniqueId()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Villager villager) {
|
||||||
|
return villagerCache.getIfPresent(villager.getUniqueId()) != null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,65 +0,0 @@
|
|||||||
package me.xginko.villageroptimizer;
|
|
||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
|
||||||
import me.xginko.villageroptimizer.config.Config;
|
|
||||||
import me.xginko.villageroptimizer.enums.OptimizationType;
|
|
||||||
import me.xginko.villageroptimizer.models.WrappedVillager;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.Villager;
|
|
||||||
import org.bukkit.entity.memory.MemoryKey;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class VillagerManager {
|
|
||||||
|
|
||||||
private final Cache<UUID, WrappedVillager> villagerCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(30)).build();
|
|
||||||
private final Config config;
|
|
||||||
|
|
||||||
protected VillagerManager(JavaPlugin plugin) {
|
|
||||||
this.config = VillagerOptimizer.getConfiguration();
|
|
||||||
plugin.getServer().getGlobalRegionScheduler().run(plugin, reCache -> {
|
|
||||||
for (World world : plugin.getServer().getWorlds()) {
|
|
||||||
for (Villager villager : world.getEntitiesByClass(Villager.class)) {
|
|
||||||
this.villagerCache.put(villager.getUniqueId(), new WrappedVillager(villager));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<WrappedVillager> getCachedVillagers() {
|
|
||||||
return this.villagerCache.asMap().values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public WrappedVillager wrap(Villager villager) {
|
|
||||||
WrappedVillager wrappedVillager = villagerCache.getIfPresent(villager.getUniqueId());
|
|
||||||
if (wrappedVillager == null) wrappedVillager = new WrappedVillager(villager);
|
|
||||||
this.villagerCache.put(villager.getUniqueId(), wrappedVillager);
|
|
||||||
return wrappedVillager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OptimizationType computeOptimization(WrappedVillager wrapped) {
|
|
||||||
Component nameTag = wrapped.villager().customName();
|
|
||||||
if (nameTag != null && config.names_that_disable.contains(PlainTextComponentSerializer.plainText().serialize(nameTag).toLowerCase())) {
|
|
||||||
return OptimizationType.NAMETAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.blocks_that_disable.contains(wrapped.villager().getLocation().getBlock().getRelative(BlockFace.DOWN).getType())) {
|
|
||||||
return OptimizationType.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Location jobSite = wrapped.villager().getMemory(MemoryKey.JOB_SITE);
|
|
||||||
if (jobSite != null && config.workstations_that_disable.contains(jobSite.getBlock().getType())) {
|
|
||||||
return OptimizationType.WORKSTATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wrapped.getOptimizationType();
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,10 +2,18 @@ package me.xginko.villageroptimizer;
|
|||||||
|
|
||||||
import me.xginko.villageroptimizer.config.Config;
|
import me.xginko.villageroptimizer.config.Config;
|
||||||
import me.xginko.villageroptimizer.config.LanguageCache;
|
import me.xginko.villageroptimizer.config.LanguageCache;
|
||||||
|
import me.xginko.villageroptimizer.enums.OptimizationType;
|
||||||
|
import me.xginko.villageroptimizer.models.WrappedVillager;
|
||||||
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Villager;
|
||||||
|
import org.bukkit.entity.memory.MemoryKey;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -24,7 +32,7 @@ public final class VillagerOptimizer extends JavaPlugin {
|
|||||||
private static Logger logger;
|
private static Logger logger;
|
||||||
private static Config config;
|
private static Config config;
|
||||||
private static HashMap<String, LanguageCache> languageCacheMap;
|
private static HashMap<String, LanguageCache> languageCacheMap;
|
||||||
private static VillagerManager villagerManager;
|
private static VillagerCache villagerCache;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
@ -45,31 +53,60 @@ public final class VillagerOptimizer extends JavaPlugin {
|
|||||||
// Plugin shutdown logic
|
// Plugin shutdown logic
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LanguageCache getLang(String lang) {
|
public static OptimizationType computeOptimization(WrappedVillager wrapped) {
|
||||||
lang = lang.replace("-", "_");
|
if (config.enable_nametag_optimization) {
|
||||||
if (config.auto_lang) {
|
Component name = wrapped.villager().customName();
|
||||||
return languageCacheMap.getOrDefault(lang, languageCacheMap.get(config.default_lang.toString().toLowerCase()));
|
if (name != null && config.nametags.contains(PlainTextComponentSerializer.plainText().serialize(name).toLowerCase())) {
|
||||||
} else {
|
return OptimizationType.NAMETAG;
|
||||||
return languageCacheMap.get(config.default_lang.toString().toLowerCase());
|
}
|
||||||
}
|
}
|
||||||
|
if (config.enable_block_optimization) {
|
||||||
|
if (config.blocks_that_disable.contains(wrapped.villager().getLocation().getBlock().getRelative(BlockFace.DOWN).getType())) {
|
||||||
|
return OptimizationType.BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.enable_workstation_optimization) {
|
||||||
|
final Location jobSite = wrapped.villager().getMemory(MemoryKey.JOB_SITE);
|
||||||
|
if (
|
||||||
|
jobSite != null
|
||||||
|
&& config.workstations_that_disable.contains(jobSite.getBlock().getType())
|
||||||
|
&& wrapped.villager().getLocation().distance(jobSite) <= config.workstation_max_distance
|
||||||
|
) {
|
||||||
|
return OptimizationType.WORKSTATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wrapped.getOptimizationType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LanguageCache getLang(Locale locale) {
|
public static OptimizationType computeOptimization(Villager villager) {
|
||||||
return getLang(locale.toString().toLowerCase());
|
if (config.enable_nametag_optimization) {
|
||||||
}
|
Component name = villager.customName();
|
||||||
|
if (name != null && config.nametags.contains(PlainTextComponentSerializer.plainText().serialize(name).toLowerCase())) {
|
||||||
public static LanguageCache getLang(CommandSender commandSender) {
|
return OptimizationType.NAMETAG;
|
||||||
if (commandSender instanceof Player player) {
|
}
|
||||||
return getLang(player.locale());
|
|
||||||
} else {
|
|
||||||
return getLang(config.default_lang);
|
|
||||||
}
|
}
|
||||||
|
if (config.enable_block_optimization) {
|
||||||
|
if (config.blocks_that_disable.contains(villager.getLocation().getBlock().getRelative(BlockFace.DOWN).getType())) {
|
||||||
|
return OptimizationType.BLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config.enable_workstation_optimization) {
|
||||||
|
final Location jobSite = villager.getMemory(MemoryKey.JOB_SITE);
|
||||||
|
if (
|
||||||
|
jobSite != null
|
||||||
|
&& config.workstations_that_disable.contains(jobSite.getBlock().getType())
|
||||||
|
&& villager.getLocation().distance(jobSite) <= config.workstation_max_distance
|
||||||
|
) {
|
||||||
|
return OptimizationType.WORKSTATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return villagerCache.getOrAddIfAbsent(villager).getOptimizationType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reloadPlugin() {
|
public void reloadPlugin() {
|
||||||
|
villagerCache = new VillagerCache();
|
||||||
reloadLang();
|
reloadLang();
|
||||||
reloadConfiguration();
|
reloadConfiguration();
|
||||||
villagerManager = new VillagerManager(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reloadConfiguration() {
|
private void reloadConfiguration() {
|
||||||
@ -129,6 +166,27 @@ public final class VillagerOptimizer extends JavaPlugin {
|
|||||||
return languageFiles;
|
return languageFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LanguageCache getLang(String lang) {
|
||||||
|
lang = lang.replace("-", "_");
|
||||||
|
if (config.auto_lang) {
|
||||||
|
return languageCacheMap.getOrDefault(lang, languageCacheMap.get(config.default_lang.toString().toLowerCase()));
|
||||||
|
} else {
|
||||||
|
return languageCacheMap.get(config.default_lang.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LanguageCache getLang(Locale locale) {
|
||||||
|
return getLang(locale.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LanguageCache getLang(CommandSender commandSender) {
|
||||||
|
if (commandSender instanceof Player player) {
|
||||||
|
return getLang(player.locale());
|
||||||
|
} else {
|
||||||
|
return getLang(config.default_lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static VillagerOptimizer getInstance() {
|
public static VillagerOptimizer getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@ -144,7 +202,7 @@ public final class VillagerOptimizer extends JavaPlugin {
|
|||||||
public static Logger getLog() {
|
public static Logger getLog() {
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
public static VillagerManager getVillagerManager() {
|
public static VillagerCache getVillagerCache() {
|
||||||
return villagerManager;
|
return villagerCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,32 +17,41 @@ public class Config {
|
|||||||
private final ConfigFile config;
|
private final ConfigFile config;
|
||||||
|
|
||||||
public final Locale default_lang;
|
public final Locale default_lang;
|
||||||
public final boolean auto_lang;
|
public final boolean auto_lang, enable_nametag_optimization, enable_workstation_optimization, enable_block_optimization;
|
||||||
|
public final double workstation_max_distance;
|
||||||
|
|
||||||
public final HashSet<String> names_that_disable = new HashSet<>(2);
|
public final HashSet<String> nametags = new HashSet<>(2);
|
||||||
public final HashSet<Material> blocks_that_disable = new HashSet<>(2);
|
public final HashSet<Material> blocks_that_disable = new HashSet<>(2);
|
||||||
public final HashSet<Material> workstations_that_disable = new HashSet<>(13);
|
public final HashSet<Material> workstations_that_disable = new HashSet<>(13);
|
||||||
|
|
||||||
public Config() throws Exception {
|
public Config() throws Exception {
|
||||||
this.config = loadConfig(new File(VillagerOptimizer.getInstance().getDataFolder(), "config.yml"));
|
this.config = loadConfig(new File(VillagerOptimizer.getInstance().getDataFolder(), "config.yml"));
|
||||||
structureConfig();
|
structureConfig();
|
||||||
|
/**
|
||||||
// Language Settings
|
* Language
|
||||||
this.default_lang = Locale.forLanguageTag(getString("language.default-language", "en_us", "The default language that will be used if auto-language is false or no matching language file was found.").replace("_", "-"));
|
*/
|
||||||
|
this.default_lang = Locale.forLanguageTag(
|
||||||
|
getString("language.default-language", "en_us",
|
||||||
|
"The default language that will be used if auto-language is false or no matching language file was found.")
|
||||||
|
.replace("_", "-"));
|
||||||
this.auto_lang = getBoolean("language.auto-language", true, "If set to true, will display messages based on client language");
|
this.auto_lang = getBoolean("language.auto-language", true, "If set to true, will display messages based on client language");
|
||||||
|
/**
|
||||||
|
* Optimization
|
||||||
// AI-Disabling
|
*/
|
||||||
this.names_that_disable.addAll(getList("ai-disabling.names-that-disable", List.of("Optimize", "DisableAI")).stream().map(String::toLowerCase).toList());
|
// Nametags
|
||||||
getList("ai-disabling.blocks-that-disable", List.of("EMERALD_BLOCK", "COBBLESTONE")).forEach(configuredMaterial -> {
|
this.enable_nametag_optimization = getBoolean("optimization.by-nametag.enable", true);
|
||||||
try {
|
this.nametags.addAll(getList("optimization.by-nametag.names", List.of("Optimize", "DisableAI"), "Names are case insensitive")
|
||||||
Material disableBlock = Material.valueOf(configuredMaterial);
|
.stream().map(String::toLowerCase).toList());
|
||||||
this.blocks_that_disable.add(disableBlock);
|
// Workstations
|
||||||
} catch (IllegalArgumentException e) {
|
this.enable_workstation_optimization = getBoolean("optimization.by-workstation.enable", true,
|
||||||
LogUtils.materialNotRecognized("blocks-that-disable", configuredMaterial);
|
"""
|
||||||
}
|
Optimize villagers that are standing near their acquired workstations /s
|
||||||
});
|
Values here need to be valid bukkit Material enums for your server version.
|
||||||
getList("ai-disabling.workstations-that-disable", List.of(
|
"""
|
||||||
|
);
|
||||||
|
this.workstation_max_distance = getDouble("optimization.by-workstation.", 4.0,
|
||||||
|
"How close in blocks a villager needs to be to get optimized by its workstation");
|
||||||
|
this.getList("optimization.by-workstation.workstation-materials", List.of(
|
||||||
"COMPOSTER", "SMOKER", "BARREL", "LOOM", "BLAST_FURNACE", "BREWING_STAND", "CAULDRON",
|
"COMPOSTER", "SMOKER", "BARREL", "LOOM", "BLAST_FURNACE", "BREWING_STAND", "CAULDRON",
|
||||||
"FLETCHING_TABLE", "CARTOGRAPHY_TABLE", "LECTERN", "SMITHING_TABLE", "STONECUTTER", "GRINDSTONE"
|
"FLETCHING_TABLE", "CARTOGRAPHY_TABLE", "LECTERN", "SMITHING_TABLE", "STONECUTTER", "GRINDSTONE"
|
||||||
)).forEach(configuredMaterial -> {
|
)).forEach(configuredMaterial -> {
|
||||||
@ -50,7 +59,24 @@ public class Config {
|
|||||||
Material disableBlock = Material.valueOf(configuredMaterial);
|
Material disableBlock = Material.valueOf(configuredMaterial);
|
||||||
this.blocks_that_disable.add(disableBlock);
|
this.blocks_that_disable.add(disableBlock);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
LogUtils.materialNotRecognized("workstations-that-disable", configuredMaterial);
|
LogUtils.materialNotRecognized("optimization.by-workstation", configuredMaterial);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Blocks
|
||||||
|
this.enable_block_optimization = getBoolean("optimization.by-specific-block.enable", true,
|
||||||
|
"""
|
||||||
|
Optimize villagers that are standing on these specific block materials /s
|
||||||
|
Values here need to be valid bukkit Material enums for your server version.
|
||||||
|
"""
|
||||||
|
);
|
||||||
|
this.getList("optimization.by-specific-block.materials", List.of(
|
||||||
|
"LAPIS_BLOCK", "GLOWSTONE", "IRON_BLOCK"
|
||||||
|
)).forEach(configuredMaterial -> {
|
||||||
|
try {
|
||||||
|
Material disableBlock = Material.valueOf(configuredMaterial);
|
||||||
|
this.blocks_that_disable.add(disableBlock);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
LogUtils.materialNotRecognized("optimization.by-specific-block", configuredMaterial);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -76,8 +102,7 @@ public class Config {
|
|||||||
private void structureConfig() {
|
private void structureConfig() {
|
||||||
config.addDefault("config-version", 1.00);
|
config.addDefault("config-version", 1.00);
|
||||||
createTitledSection("Language", "language");
|
createTitledSection("Language", "language");
|
||||||
createTitledSection("AI Disabling", "ai-disabling");
|
createTitledSection("Optimization", "optimization");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createTitledSection(String title, String path) {
|
public void createTitledSection(String title, String path) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package me.xginko.villageroptimizer.models;
|
package me.xginko.villageroptimizer.models;
|
||||||
|
|
||||||
|
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||||
import me.xginko.villageroptimizer.enums.NamespacedKeys;
|
import me.xginko.villageroptimizer.enums.NamespacedKeys;
|
||||||
import me.xginko.villageroptimizer.enums.OptimizationType;
|
import me.xginko.villageroptimizer.enums.OptimizationType;
|
||||||
import org.bukkit.entity.Villager;
|
import org.bukkit.entity.Villager;
|
||||||
@ -8,6 +9,10 @@ import org.bukkit.persistence.PersistentDataType;
|
|||||||
|
|
||||||
public record WrappedVillager(Villager villager) {
|
public record WrappedVillager(Villager villager) {
|
||||||
|
|
||||||
|
public static WrappedVillager fromVillager(Villager villager) {
|
||||||
|
return VillagerOptimizer.getVillagerCache().getOrAddIfAbsent(villager);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOptimized() {
|
public boolean isOptimized() {
|
||||||
return villager.getPersistentDataContainer().has(NamespacedKeys.OPTIMIZED.key());
|
return villager.getPersistentDataContainer().has(NamespacedKeys.OPTIMIZED.key());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user