large chunk of progress

This commit is contained in:
xGinko 2023-09-07 21:30:23 +02:00
parent 84e9542f19
commit 4d01238f4f
10 changed files with 149 additions and 35 deletions

View File

@ -15,7 +15,7 @@ public class LanguageCache {
public final Component no_permission;
public final List<Component> nametag_optimize_success, nametag_on_optimize_cooldown, nametag_unoptimize_success,
block_optimization_success, block_on_optimize_cooldown, block_unoptimize_success,
block_optimize_success, block_on_optimize_cooldown, block_unoptimize_success,
workstation_optimization_success, workstation_on_optimize_cooldown, workstation_unoptimize_success;
public LanguageCache(String lang) throws Exception {
@ -26,7 +26,7 @@ public class LanguageCache {
this.nametag_optimize_success = getListTranslation("messages.nametag.optimize-success", List.of("<green>Successfully optimized villager by using a nametag."));
this.nametag_on_optimize_cooldown = getListTranslation("messages.nametag.optimize-on-cooldown", List.of("<gray>You need to wait %time% until you can optimize this villager again."));
this.nametag_unoptimize_success = getListTranslation("messages.nametag.unoptimize-success", List.of("<green>Successfully unoptimized villager by using a nametag."));
this.block_optimization_success = getListTranslation("messages.block.optimize-success", List.of("<green>%villagertype% villager successfully optimized using block %blocktype%."));
this.block_optimize_success = getListTranslation("messages.block.optimize-success", List.of("<green>%villagertype% villager successfully optimized using block %blocktype%."));
this.block_on_optimize_cooldown = getListTranslation("messages.block.optimize-on-cooldown", List.of("<gray>You need to wait %time% until you can optimize this villager again."));
this.block_unoptimize_success = getListTranslation("messages.block.unoptimize-success", List.of("<green>Successfully unoptimized villager by moving it off a %blocktype% block."));
this.workstation_optimization_success = getListTranslation("messages.workstation.optimize-success", List.of("<green>%villagertype% villager successfully optimized using workstation block %blocktype%."));

View File

@ -15,14 +15,14 @@ public final class WrappedVillager {
public WrappedVillager(@NotNull Villager villager) {
this.villager = villager;
this.villagerData = villager.getPersistentDataContainer();
this.villagerData = this.villager.getPersistentDataContainer();
}
public @NotNull Villager villager() {
return villager;
}
public static @NotNull WrappedVillager fromVillager(Villager villager) {
public static @NotNull WrappedVillager fromCache(Villager villager) {
return VillagerOptimizer.getVillagerCache().get(villager);
}

View File

@ -36,16 +36,16 @@ public class AntiVillagerDamage implements VillagerOptimizerModule, Listener {
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onDamage(EntityDamageEvent event) {
if (!event.getEntity().getType().equals(EntityType.VILLAGER)) return;
private void onDamageReceive(EntityDamageEvent event) {
if (!event.getEntityType().equals(EntityType.VILLAGER)) return;
if (cache.get((Villager) event.getEntity()).isOptimized()) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onPathfind(EntityPushedByEntityAttackEvent event) {
if (!event.getEntity().getType().equals(EntityType.VILLAGER)) return;
private void onPushByEntityAttack(EntityPushedByEntityAttackEvent event) {
if (!event.getEntityType().equals(EntityType.VILLAGER)) return;
if (cache.get((Villager) event.getEntity()).isOptimized()) {
event.setCancelled(true);
}

View File

@ -3,11 +3,14 @@ package me.xginko.villageroptimizer.modules;
import com.destroystokyo.paper.event.entity.EntityPathfindEvent;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.models.VillagerCache;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityTargetLivingEntityEvent;
public class AntiVillagerTargetting implements VillagerOptimizerModule, Listener {
@ -42,9 +45,20 @@ public class AntiVillagerTargetting implements VillagerOptimizerModule, Listener
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onTarget(EntityPathfindEvent event) {
private void onEntityTargetVillager(EntityPathfindEvent event) {
if (event.getTargetEntity() instanceof Villager villager && cache.get(villager).isOptimized()) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onEntityAttackVillager(EntityDamageByEntityEvent event) {
if (
event.getEntityType().equals(EntityType.VILLAGER)
&& event.getDamager() instanceof Mob attacker
&& cache.get((Villager) event.getEntity()).isOptimized()
) {
attacker.setTarget(null);
}
}
}

View File

@ -1,29 +1,43 @@
package me.xginko.villageroptimizer.modules;
import io.papermc.paper.event.entity.EntityMoveEvent;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.enums.OptimizationType;
import me.xginko.villageroptimizer.models.VillagerCache;
import me.xginko.villageroptimizer.models.WrappedVillager;
import me.xginko.villageroptimizer.utils.CommonUtils;
import net.kyori.adventure.text.TextReplacementConfig;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
public class BlockOptimization implements VillagerOptimizerModule, Listener {
private final VillagerCache cache;
private final Config config;
private final boolean shouldLog;
private final boolean shouldLog, shouldNotifyPlayer;
protected BlockOptimization() {
this.cache = VillagerOptimizer.getVillagerCache();
this.config = VillagerOptimizer.getConfiguration();
this.config.addComment("optimization.methods.by-specific-block.enable", """
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
again once a player interacts with the villager afterwards.
""");
this.shouldLog = config.getBoolean("optimization.methods.by-specific-block.log", false);
this.shouldNotifyPlayer = config.getBoolean("optimization.methods.by-specific-block.notify-player", true);
}
@Override
@ -43,24 +57,91 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onEntityMove(EntityMoveEvent event) {
if (!event.getEntityType().equals(EntityType.VILLAGER)) return;
private void onBlockPlace(BlockPlaceEvent event) {
Block placed = event.getBlock();
if (!config.blocks_that_disable.contains(placed.getType())) return;
placed.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,0.5,0.5).forEach(entity -> {
if (entity.getType().equals(EntityType.VILLAGER)) {
WrappedVillager wVillager = cache.get((Villager) entity);
if (!wVillager.isOptimized()) {
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(player::sendMessage);
}
if (shouldLog)
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
} else {
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown.forEach(line -> player.sendMessage(line
.replaceText(TextReplacementConfig.builder().matchLiteral("%time%").replacement(CommonUtils.formatTime(wVillager.getOptimizeCooldown())).build())));
}
}
}
}
});
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onBlockBreak(BlockBreakEvent event) {
Block broken = event.getBlock();
if (!config.blocks_that_disable.contains(broken.getType())) return;
broken.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,0.5,0.5).forEach(entity -> {
if (entity.getType().equals(EntityType.VILLAGER)) {
WrappedVillager wVillager = cache.get((Villager) entity);
if (wVillager.getOptimizationType().equals(OptimizationType.BLOCK)) {
wVillager.setOptimization(OptimizationType.OFF);
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(player::sendMessage);
}
if (shouldLog)
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
}
}
});
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onPlayerInteract(PlayerInteractEntityEvent event) {
Entity interacted = event.getRightClicked();
if (!interacted.getType().equals(EntityType.VILLAGER)) return;
WrappedVillager wVillager = cache.get((Villager) interacted);
final Location entityLegs = interacted.getLocation();
final Location entityLegs = event.getEntity().getLocation();
if (
config.blocks_that_disable.contains(entityLegs.getBlock().getType())
config.blocks_that_disable.contains(entityLegs.getBlock().getType()) // for slabs and sink in blocks
|| config.blocks_that_disable.contains(entityLegs.clone().subtract(0,1,0).getBlock().getType())
) {
WrappedVillager wVillager = cache.get((Villager) event.getEntity());
if (!wVillager.isOptimized()) {
wVillager.setOptimization(OptimizationType.BLOCK);
if (shouldLog) VillagerOptimizer.getLog().info("Villager moved onto an optimization block at "+wVillager.villager().getLocation());
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(player::sendMessage);
}
if (shouldLog)
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
} else {
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_on_optimize_cooldown.forEach(line -> player.sendMessage(line
.replaceText(TextReplacementConfig.builder().matchLiteral("%time%").replacement(CommonUtils.formatTime(wVillager.getOptimizeCooldown())).build())));
}
}
}
} else {
WrappedVillager wVillager = cache.get((Villager) event.getEntity());
if (wVillager.isOptimized()) {
if (wVillager.getOptimizationType().equals(OptimizationType.BLOCK)) {
wVillager.setOptimization(OptimizationType.OFF);
if (shouldLog) VillagerOptimizer.getLog().info("Villager moved away from an optimization block at "+wVillager.villager().getLocation());
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(player::sendMessage);
}
if (shouldLog)
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
}
}
}

View File

@ -115,6 +115,6 @@ public class ChunkLimit implements VillagerOptimizerModule, Listener {
private int getProfessionPriority(Villager villager) {
Villager.Profession profession = villager.getProfession();
return removalPriority.contains(profession) && !WrappedVillager.fromVillager(villager).isOptimized() ? removalPriority.indexOf(profession) : Integer.MAX_VALUE;
return removalPriority.contains(profession) && !WrappedVillager.fromCache(villager).isOptimized() ? removalPriority.indexOf(profession) : Integer.MAX_VALUE;
}
}

View File

@ -27,6 +27,12 @@ public class NametagOptimization implements VillagerOptimizerModule, Listener {
protected NametagOptimization() {
this.cache = VillagerOptimizer.getVillagerCache();
this.config = VillagerOptimizer.getConfiguration();
this.config.addComment("optimization.methods.by-nametag.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.shouldLog = config.getBoolean("optimization.methods.by-nametag.log", false);
this.shouldNotifyPlayer = config.getBoolean("optimization.methods.by-nametag.notify-player", true);
}
@ -48,7 +54,7 @@ public class NametagOptimization implements VillagerOptimizerModule, Listener {
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onNametag(PlayerNameEntityEvent event) {
private void onPlayerNameEntity(PlayerNameEntityEvent event) {
if (!event.getEntity().getType().equals(EntityType.VILLAGER)) return;
Component name = event.getName();
if (name == null) return;
@ -68,14 +74,13 @@ public class NametagOptimization implements VillagerOptimizerModule, Listener {
} else {
if (shouldNotifyPlayer) {
Player player = event.getPlayer();
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line ->
player.sendMessage(line.replaceText(TextReplacementConfig.builder().matchLiteral("%time").replacement(CommonUtils.formatTime(wVillager.getOptimizeCooldown())).build()))
);
VillagerOptimizer.getLang(player.locale()).nametag_on_optimize_cooldown.forEach(line -> player.sendMessage(line
.replaceText(TextReplacementConfig.builder().matchLiteral("%time%").replacement(CommonUtils.formatTime(wVillager.getOptimizeCooldown())).build())));
}
}
}
} else {
if (wVillager.isOptimized()) {
if (wVillager.getOptimizationType().equals(OptimizationType.NAMETAG)) {
wVillager.setOptimization(OptimizationType.OFF);
if (shouldNotifyPlayer) {
Player player = event.getPlayer();

View File

@ -2,6 +2,7 @@ package me.xginko.villageroptimizer.modules;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.models.VillagerCache;
import me.xginko.villageroptimizer.models.WrappedVillager;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Villager;
@ -13,12 +14,19 @@ import org.bukkit.event.player.PlayerInteractEntityEvent;
public class RestockOptimized implements VillagerOptimizerModule, Listener {
private final VillagerCache cache;
private final long restock_delay;
private final boolean shouldLog;
public RestockOptimized() {
this.cache = VillagerOptimizer.getVillagerCache();
Config config = VillagerOptimizer.getConfiguration();
this.restock_delay = config.getInt("")
config.addComment("optimization.trade-restocking.enable", """
This is for automatic restocking of trades for optimized villagers. Optimized Villagers\s
Don't have enough AI to do trade restocks themselves, so this needs to always be enabled.
""");
this.restock_delay = config.getInt("optimization.trade-restocking.delay-in-ticks", 1200);
this.shouldLog = config.getBoolean("optimization.trade-restocking.log", false);
}
@Override
@ -34,15 +42,15 @@ public class RestockOptimized implements VillagerOptimizerModule, Listener {
@Override
public boolean shouldEnable() {
return true;
return VillagerOptimizer.getConfiguration().getBoolean("optimization.trade-restocking.enable", true);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
private void onInteract(PlayerInteractEntityEvent event) {
if (!event.getRightClicked().getType().equals(EntityType.VILLAGER)) return;
WrappedVillager wrappedVillager = new WrappedVillager((Villager) event.getRightClicked());
if (!wrappedVillager.isOptimized()) return;
WrappedVillager wVillager = cache.get((Villager) event.getRightClicked());
if (!wVillager.isOptimized()) return;
if (wrappedVillager.getSavedWorldTime() >)
}
}

View File

@ -14,12 +14,17 @@ public class WorkstationOptimization implements VillagerOptimizerModule, Listene
private final VillagerCache cache;
private final Config config;
private final boolean shouldLog;
private final boolean shouldLog, shouldNotifyPlayer;
protected WorkstationOptimization() {
this.cache = VillagerOptimizer.getVillagerCache();
this.config = VillagerOptimizer.getConfiguration();
this.config.addComment("optimization.methods.by-workstation.enable", """
When enabled, villagers near a configured radius to a workstation specific to their profession\s
will be optimized.
""");
this.shouldLog = config.getBoolean("optimization.methods.by-workstation.log", false);
this.shouldNotifyPlayer = config.getBoolean("optimization.methods.by-workstation.notify-player", true);
}
@Override

View File

@ -1,4 +1,5 @@
name: VillagerOptimizer
version: '${project.version}'
main: me.xginko.villageroptimizer.VillagerOptimizer
api-version: '1.20'
api-version: '1.19'
folia-supported: true