unfinished changes

This commit is contained in:
xGinko 2023-09-12 02:08:39 +02:00
parent 1329fd337e
commit 5ceb1b7484
6 changed files with 70 additions and 42 deletions

View File

@ -30,6 +30,10 @@ import java.util.List;
public class BlockOptimization implements VillagerOptimizerModule, Listener { public class BlockOptimization implements VillagerOptimizerModule, Listener {
/*
* TODO: Think of better logic than just checking under the villagers feet for block
* */
private final VillagerManager villagerManager; private final VillagerManager villagerManager;
private final HashSet<Material> blocks_that_disable = new HashSet<>(4); private final HashSet<Material> blocks_that_disable = new HashSet<>(4);
private final boolean shouldLog, shouldNotifyPlayer; private final boolean shouldLog, shouldNotifyPlayer;
@ -43,8 +47,7 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
config.addComment("optimization-methods.block-optimization.enable", """ config.addComment("optimization-methods.block-optimization.enable", """
When enabled, villagers standing on the configured specific blocks will become optimized once a\s When enabled, villagers standing on the configured specific blocks will become optimized once a\s
player interacts with them. If the block is broken or moved, the villager will become unoptimized\s player interacts with them. If the block is broken or moved, the villager will become unoptimized\s
again once a player interacts with the villager afterwards. again once a player interacts with the villager afterwards.""");
""");
config.getList("optimization-methods.block-optimization.materials", List.of( config.getList("optimization-methods.block-optimization.materials", List.of(
"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."
@ -53,13 +56,12 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
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("optimization-methods.block-optimization", configuredMaterial); LogUtils.materialNotRecognized("block-optimization", configuredMaterial);
} }
}); });
this.cooldown = config.getInt("optimization-methods.block-optimization.optimize-cooldown-seconds", 600, """ this.cooldown = 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 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. Here for configuration freedom. Recommended to leave as is to not enable any exploitable behavior.""") * 1000L;
""") * 1000L;
this.maxVillagers = config.getInt("optimization-methods.block-optimization.max-villagers-per-block", 3, this.maxVillagers = config.getInt("optimization-methods.block-optimization.max-villagers-per-block", 3,
"How many villagers can be optimized at once by placing a block under them."); "How many villagers can be optimized at once by placing a block under them.");
this.shouldNotifyPlayer = config.getBoolean("optimization-methods.block-optimization.notify-player", true, this.shouldNotifyPlayer = config.getBoolean("optimization-methods.block-optimization.notify-player", true,
@ -92,11 +94,12 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
int counter = 0; int counter = 0;
for (Entity entity : placed.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,1,0.5)) { for (Entity entity : placed.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,1,0.5)) {
if (counter >= maxVillagers) return;
if (!entity.getType().equals(EntityType.VILLAGER)) continue; if (!entity.getType().equals(EntityType.VILLAGER)) continue;
WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity); WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity);
if (wVillager.isOptimized()) continue; final OptimizationType type = wVillager.getOptimizationType();
if (counter >= maxVillagers) return; if (!type.equals(OptimizationType.OFF) && !type.equals(OptimizationType.COMMAND)) continue;
if (wVillager.canOptimize(cooldown) || player.hasPermission(Permissions.Bypass.BLOCK_COOLDOWN.get())) { if (wVillager.canOptimize(cooldown) || player.hasPermission(Permissions.Bypass.BLOCK_COOLDOWN.get())) {
wVillager.setOptimization(OptimizationType.BLOCK); wVillager.setOptimization(OptimizationType.BLOCK);

View File

@ -18,6 +18,10 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
public class RestockTrades implements VillagerOptimizerModule, Listener { public class RestockTrades implements VillagerOptimizerModule, Listener {
/*
* TODO: Disable notify message for cooldown bypassers
* */
private final VillagerManager villagerManager; private final VillagerManager villagerManager;
private final long restock_delay_millis; private final long restock_delay_millis;
private final boolean shouldLog, notifyPlayer; private final boolean shouldLog, notifyPlayer;

View File

@ -23,13 +23,17 @@ import java.util.logging.Level;
public class VillagerChunkLimit implements VillagerOptimizerModule, Listener { public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
/*
* TODO: expand villager chunk limit with settings for optimized and optimzed.
* */
private final VillagerOptimizer plugin; private final VillagerOptimizer plugin;
private final VillagerManager villagerManager; private final VillagerManager villagerManager;
private ScheduledTask scheduledTask; private ScheduledTask scheduledTask;
private final List<Villager.Profession> removalPriority = new ArrayList<>(16); private final List<Villager.Profession> removalPriority = new ArrayList<>(16);
private final int maxVillagersPerChunk; private final int global_max_villagers_per_chunk, max_unoptimized_per_chunk, max_optimized_per_chunk;
private final boolean logIsEnabled; private final boolean logIsEnabled;
private final long checkPeriod; private final long check_period;
protected VillagerChunkLimit() { protected VillagerChunkLimit() {
shouldEnable(); shouldEnable();
@ -40,10 +44,17 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
Checks chunks for too many villagers and removes excess villagers based on priority.\s Checks chunks for too many villagers and removes excess villagers based on priority.\s
Naturally, optimized villagers will be picked last since they don't affect performance\s Naturally, optimized villagers will be picked last since they don't affect performance\s
as much as unoptimized villagers."""); as much as unoptimized villagers.""");
this.maxVillagersPerChunk = config.getInt("villager-chunk-limit.max-villagers-per-chunk", 25); this.global_max_villagers_per_chunk = config.getInt("villager-chunk-limit.global-max-villagers-per-chunk", 50, """
this.logIsEnabled = config.getBoolean("villager-chunk-limit.log-removals", false); The total amount of villagers, no matter if optimized or unoptimized per chunk.\s
this.checkPeriod = config.getInt("villager-chunk-limit.check-period-in-ticks", 600, You want this number to be minimum as high as the sum of optimized and unoptimized\s
per chunk if you don't want to risk deleting the wrong villagers.""");
this.max_unoptimized_per_chunk = config.getInt("villager-chunk-limit.max-unoptimized-per-chunk", 30,
"The maximum amount of unoptimized villagers per chunk.");
this.max_optimized_per_chunk = config.getInt("villager-chunk-limit.max-optimized-per-chunk", 20,
"The maximum amount of optimized villagers per chunk.");
this.check_period = config.getInt("villager-chunk-limit.check-period-in-ticks", 600,
"Check all loaded chunks every X ticks. 1 second = 20 ticks"); "Check all loaded chunks every X ticks. 1 second = 20 ticks");
this.logIsEnabled = config.getBoolean("villager-chunk-limit.log-removals", false);
config.getList("villager-chunk-limit.removal-priority", List.of( config.getList("villager-chunk-limit.removal-priority", List.of(
"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"
@ -64,7 +75,13 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
@Override @Override
public void enable() { public void enable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin); plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.scheduledTask = plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, task -> run(), checkPeriod, checkPeriod); this.scheduledTask = plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, periodic_chunk_check -> {
plugin.getServer().getWorlds().forEach(world -> {
for (Chunk chunk : world.getLoadedChunks()) {
plugin.getServer().getRegionScheduler().run(plugin, world, chunk.getX(), chunk.getZ(), check_chunk -> checkVillagersInChunk(chunk));
}
});
}, check_period, check_period);
} }
@Override @Override
@ -94,14 +111,6 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
} }
} }
private void run() {
plugin.getServer().getWorlds().forEach(world -> {
for (Chunk chunk : world.getLoadedChunks()) {
plugin.getServer().getRegionScheduler().run(plugin, world, chunk.getX(), chunk.getZ(), task -> checkVillagersInChunk(chunk));
}
});
}
private void checkVillagersInChunk(Chunk chunk) { private void checkVillagersInChunk(Chunk chunk) {
// Create a list with all villagers in that chunk // Create a list with all villagers in that chunk
List<Villager> villagers_in_chunk = new ArrayList<>(); List<Villager> villagers_in_chunk = new ArrayList<>();
@ -112,7 +121,7 @@ public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
} }
// Check if there are more villagers in that chunk than allowed // Check if there are more villagers in that chunk than allowed
int amount_over_the_limit = villagers_in_chunk.size() - maxVillagersPerChunk; int amount_over_the_limit = villagers_in_chunk.size() - global_max_villagers_per_chunk;
if (amount_over_the_limit <= 0) return; if (amount_over_the_limit <= 0) return;
// Sort villager list by profession priority // Sort villager list by profession priority

View File

@ -17,12 +17,12 @@ public interface VillagerOptimizerModule {
modules.add(new BlockOptimization()); modules.add(new BlockOptimization());
modules.add(new LevelVillagers()); modules.add(new LevelVillagers());
modules.add(new NametagOptimization()); modules.add(new NametagOptimization());
modules.add(new NoBabyVillagers());
modules.add(new PreventUnoptimizedTrading()); modules.add(new PreventUnoptimizedTrading());
modules.add(new PreventVillagerDamage()); modules.add(new PreventVillagerDamage());
modules.add(new PreventVillagerTargetting()); modules.add(new PreventVillagerTargetting());
modules.add(new RestockTrades()); modules.add(new RestockTrades());
modules.add(new VillagerChunkLimit()); modules.add(new VillagerChunkLimit());
modules.add(new VillagersSpawnAdult());
modules.add(new WorkstationOptimization()); modules.add(new WorkstationOptimization());
modules.forEach(module -> { modules.forEach(module -> {

View File

@ -9,9 +9,9 @@ import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
public class NoBabyVillagers implements VillagerOptimizerModule, Listener { public class VillagersSpawnAdult implements VillagerOptimizerModule, Listener {
protected NoBabyVillagers() {} protected VillagersSpawnAdult() {}
@Override @Override
public void enable() { public void enable() {
@ -26,14 +26,18 @@ public class NoBabyVillagers implements VillagerOptimizerModule, Listener {
@Override @Override
public boolean shouldEnable() { public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults", false, return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-spawn-as-adults.enable", false, """
"Automatically turns baby villagers into adults when spawning."); Spawned villagers will immediately be adults.\s
This is to save some more performance 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.""");
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onVillagerSpawn(CreatureSpawnEvent event) { private void onVillagerSpawn(CreatureSpawnEvent event) {
if (!event.getEntityType().equals(EntityType.VILLAGER)) return; if (event.getEntityType().equals(EntityType.VILLAGER)) {
Villager villager = (Villager) event.getEntity(); Villager villager = (Villager) event.getEntity();
if (!villager.isAdult()) villager.setAdult(); if (!villager.isAdult()) villager.setAdult();
}
} }
} }

View File

@ -27,6 +27,9 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
public class WorkstationOptimization implements VillagerOptimizerModule, Listener { public class WorkstationOptimization implements VillagerOptimizerModule, Listener {
/*
* TODO: Make placed workstation villager profession related.
* */
private final VillagerManager villagerManager; private final VillagerManager villagerManager;
private final HashSet<Material> workstations_that_disable = new HashSet<>(14); private final HashSet<Material> workstations_that_disable = new HashSet<>(14);
@ -50,7 +53,7 @@ public class WorkstationOptimization implements VillagerOptimizerModule, Listene
Material disableBlock = Material.valueOf(configuredMaterial); Material disableBlock = Material.valueOf(configuredMaterial);
this.workstations_that_disable.add(disableBlock); this.workstations_that_disable.add(disableBlock);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
LogUtils.materialNotRecognized("optimization-methods.workstation-optimization", configuredMaterial); LogUtils.materialNotRecognized("workstation-optimization", configuredMaterial);
} }
}); });
this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, """ this.search_radius = config.getDouble("optimization-methods.workstation-optimization.search-radius-in-blocks", 2.0, """
@ -100,9 +103,12 @@ public class WorkstationOptimization implements VillagerOptimizerModule, Listene
WrappedVillager wVillager = villagerManager.getOrAdd(villager); WrappedVillager wVillager = villagerManager.getOrAdd(villager);
final double distance = entity.getLocation().distance(workstationLoc); final double distance = entity.getLocation().distance(workstationLoc);
if (!wVillager.isOptimized() && distance < closestDistance) { if (distance < closestDistance) {
closestOptimizableVillager = wVillager; final OptimizationType type = wVillager.getOptimizationType();
closestDistance = distance; if (type.equals(OptimizationType.OFF) || type.equals(OptimizationType.COMMAND)) {
closestOptimizableVillager = wVillager;
closestDistance = distance;
}
} }
} }
@ -150,15 +156,17 @@ public class WorkstationOptimization implements VillagerOptimizerModule, Listene
WrappedVillager wVillager = villagerManager.getOrAdd(villager); WrappedVillager wVillager = villagerManager.getOrAdd(villager);
final double distance = entity.getLocation().distance(workstationLoc); final double distance = entity.getLocation().distance(workstationLoc);
if (wVillager.isOptimized() && distance < closestDistance) { if (distance < closestDistance) {
closestOptimizedVillager = wVillager; final OptimizationType type = wVillager.getOptimizationType();
closestDistance = distance; if (type.equals(OptimizationType.WORKSTATION) || type.equals(OptimizationType.COMMAND)) {
closestOptimizedVillager = wVillager;
closestDistance = distance;
}
} }
} }
if (closestOptimizedVillager == null) return; if (closestOptimizedVillager != null) {
closestOptimizedVillager.setOptimization(OptimizationType.OFF);
if (closestOptimizedVillager.getOptimizationType().equals(OptimizationType.WORKSTATION)) {
if (shouldNotifyPlayer) { if (shouldNotifyPlayer) {
final String villagerType = closestOptimizedVillager.villager().getProfession().toString().toLowerCase(); final String villagerType = closestOptimizedVillager.villager().getProfession().toString().toLowerCase();
final String workstation = placed.getType().toString().toLowerCase(); final String workstation = placed.getType().toString().toLowerCase();