finish optimization interactions
This commit is contained in:
parent
e29bb8fcb1
commit
61ffc8e198
@ -1,22 +1,13 @@
|
|||||||
package me.xginko.villageroptimizer;
|
package me.xginko.villageroptimizer;
|
||||||
|
|
||||||
|
import me.xginko.villageroptimizer.cache.VillagerManager;
|
||||||
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.cache.VillagerManager;
|
|
||||||
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 org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -146,54 +137,4 @@ public final class VillagerOptimizer extends JavaPlugin {
|
|||||||
return getLang(config.default_lang);
|
return getLang(config.default_lang);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OptimizationType computeOptimization(@NotNull WrappedVillager wrapped) {
|
|
||||||
if (config.enable_nametag_optimization) {
|
|
||||||
Component name = wrapped.villager().customName();
|
|
||||||
if (name != null && config.nametags.contains(PlainTextComponentSerializer.plainText().serialize(name).toLowerCase())) {
|
|
||||||
return OptimizationType.NAMETAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 OptimizationType computeOptimization(@NotNull Villager villager) {
|
|
||||||
if (config.enable_nametag_optimization) {
|
|
||||||
Component name = villager.customName();
|
|
||||||
if (name != null && config.nametags.contains(PlainTextComponentSerializer.plainText().serialize(name).toLowerCase())) {
|
|
||||||
return OptimizationType.NAMETAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 villagerManager.getOrAdd(villager).getOptimizationType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public class LanguageCache {
|
|||||||
public final Component no_permission;
|
public final Component no_permission;
|
||||||
public final List<Component> nametag_optimize_success, nametag_on_optimize_cooldown, nametag_unoptimize_success,
|
public final List<Component> nametag_optimize_success, nametag_on_optimize_cooldown, nametag_unoptimize_success,
|
||||||
block_optimize_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;
|
workstation_optimize_success, workstation_on_optimize_cooldown, workstation_unoptimize_success;
|
||||||
|
|
||||||
public LanguageCache(String lang) throws Exception {
|
public LanguageCache(String lang) throws Exception {
|
||||||
this.lang = loadLang(new File(VillagerOptimizer.getInstance().getDataFolder() + File.separator + "lang", lang + ".yml"));
|
this.lang = loadLang(new File(VillagerOptimizer.getInstance().getDataFolder() + File.separator + "lang", lang + ".yml"));
|
||||||
@ -28,10 +28,10 @@ public class LanguageCache {
|
|||||||
this.nametag_unoptimize_success = getListTranslation("messages.nametag.unoptimize-success", List.of("<green>Successfully unoptimized villager by using a nametag."));
|
this.nametag_unoptimize_success = getListTranslation("messages.nametag.unoptimize-success", List.of("<green>Successfully unoptimized villager by using a nametag."));
|
||||||
this.block_optimize_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_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.block_unoptimize_success = getListTranslation("messages.block.unoptimize-success", List.of("<green>Successfully unoptimized %villagertype% villager by removing %blocktype%."));
|
||||||
this.workstation_optimization_success = getListTranslation("messages.workstation.optimize-success", List.of("<green>%villagertype% villager successfully optimized using workstation block %blocktype%."));
|
this.workstation_optimize_success = getListTranslation("messages.workstation.optimize-success", List.of("<green>%villagertype% villager successfully optimized using workstation %workstation%."));
|
||||||
this.workstation_on_optimize_cooldown = getListTranslation("messages.workstation.optimize-on-cooldown", List.of("<gray>You need to wait %time% until you can optimize this villager again."));
|
this.workstation_on_optimize_cooldown = getListTranslation("messages.workstation.optimize-on-cooldown", List.of("<gray>You need to wait %time% until you can optimize this villager again."));
|
||||||
this.workstation_unoptimize_success = getListTranslation("messages.workstation.unoptimize-success", List.of("<green>Successfully unoptimized villager by removing workstation block %blocktype%."));
|
this.workstation_unoptimize_success = getListTranslation("messages.workstation.unoptimize-success", List.of("<green>Successfully unoptimized %villagertype% villager by removing workstation block %workstation%."));
|
||||||
|
|
||||||
saveLang();
|
saveLang();
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public final class WrappedVillager {
|
public final class WrappedVillager {
|
||||||
|
|
||||||
private final @NotNull Villager villager;
|
private final @NotNull Villager villager;
|
||||||
private final @NotNull PersistentDataContainer villagerData;
|
private final @NotNull PersistentDataContainer dataContainer;
|
||||||
|
|
||||||
public WrappedVillager(@NotNull Villager villager) {
|
public WrappedVillager(@NotNull Villager villager) {
|
||||||
this.villager = villager;
|
this.villager = villager;
|
||||||
this.villagerData = this.villager.getPersistentDataContainer();
|
this.dataContainer = this.villager.getPersistentDataContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Villager villager() {
|
public @NotNull Villager villager() {
|
||||||
@ -27,41 +27,37 @@ public final class WrappedVillager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOptimized() {
|
public boolean isOptimized() {
|
||||||
return villagerData.has(Keys.OPTIMIZED.key());
|
return dataContainer.has(Keys.OPTIMIZED.key());
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull OptimizationType computeOptimization() {
|
|
||||||
return VillagerOptimizer.computeOptimization(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setOptimization(OptimizationType type) {
|
public boolean setOptimization(OptimizationType type) {
|
||||||
if (type.equals(OptimizationType.OFF) && isOptimized()) {
|
if (type.equals(OptimizationType.OFF) && isOptimized()) {
|
||||||
villagerData.remove(Keys.OPTIMIZED.key());
|
dataContainer.remove(Keys.OPTIMIZED.key());
|
||||||
villager.setAware(true);
|
villager.setAware(true);
|
||||||
villager.setAI(true);
|
villager.setAI(true);
|
||||||
} else {
|
} else {
|
||||||
if (isOnOptimizeCooldown()) return false;
|
if (isOnOptimizeCooldown()) return false;
|
||||||
setOptimizeCooldown(VillagerOptimizer.getConfiguration().state_change_cooldown);
|
dataContainer.set(Keys.OPTIMIZED.key(), PersistentDataType.STRING, type.name());
|
||||||
villagerData.set(Keys.OPTIMIZED.key(), PersistentDataType.STRING, type.name());
|
|
||||||
villager.setAware(false);
|
villager.setAware(false);
|
||||||
|
setOptimizeCooldown(VillagerOptimizer.getConfiguration().state_change_cooldown);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull OptimizationType getOptimizationType() {
|
public @NotNull OptimizationType getOptimizationType() {
|
||||||
return isOptimized() ? OptimizationType.valueOf(villagerData.get(Keys.OPTIMIZED.key(), PersistentDataType.STRING)) : OptimizationType.OFF;
|
return isOptimized() ? OptimizationType.valueOf(dataContainer.get(Keys.OPTIMIZED.key(), PersistentDataType.STRING)) : OptimizationType.OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOptimizeCooldown(long milliseconds) {
|
public void setOptimizeCooldown(long milliseconds) {
|
||||||
villagerData.set(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
|
dataContainer.set(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getOptimizeCooldown() {
|
public long getOptimizeCooldown() {
|
||||||
return villagerData.has(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) ? System.currentTimeMillis() - villagerData.get(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) : 0L;
|
return dataContainer.has(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) ? System.currentTimeMillis() - dataContainer.get(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) : 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnOptimizeCooldown() {
|
public boolean isOnOptimizeCooldown() {
|
||||||
return villagerData.has(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) && villagerData.get(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) <= System.currentTimeMillis();
|
return dataContainer.has(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) && dataContainer.get(Keys.COOLDOWN_OPTIMIZE.key(), PersistentDataType.LONG) <= System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restock() {
|
public void restock() {
|
||||||
@ -69,20 +65,20 @@ public final class WrappedVillager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setExpCooldown(long milliseconds) {
|
public void setExpCooldown(long milliseconds) {
|
||||||
villagerData.set(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
|
dataContainer.set(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnExpCooldown() {
|
public boolean isOnExpCooldown() {
|
||||||
return villagerData.has(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG) && villagerData.get(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG) <= System.currentTimeMillis();
|
return dataContainer.has(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG) && dataContainer.get(Keys.COOLDOWN_EXPERIENCE.key(), PersistentDataType.LONG) <= System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long saveWorldTime() {
|
public long saveWorldTime() {
|
||||||
final long worldTime = villager.getWorld().getFullTime();
|
final long worldTime = villager.getWorld().getFullTime();
|
||||||
villagerData.set(Keys.WORLDTIME.key(), PersistentDataType.LONG, worldTime);
|
dataContainer.set(Keys.WORLDTIME.key(), PersistentDataType.LONG, worldTime);
|
||||||
return worldTime;
|
return worldTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSavedWorldTime() {
|
public long getSavedWorldTime() {
|
||||||
return villagerData.has(Keys.WORLDTIME.key(), PersistentDataType.LONG) ? villagerData.get(Keys.WORLDTIME.key(), PersistentDataType.LONG) : saveWorldTime();
|
return dataContainer.has(Keys.WORLDTIME.key(), PersistentDataType.LONG) ? dataContainer.get(Keys.WORLDTIME.key(), PersistentDataType.LONG) : saveWorldTime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,17 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
|
|||||||
Block placed = event.getBlock();
|
Block placed = event.getBlock();
|
||||||
if (!config.blocks_that_disable.contains(placed.getType())) return;
|
if (!config.blocks_that_disable.contains(placed.getType())) return;
|
||||||
|
|
||||||
placed.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,0.5,0.5).forEach(entity -> {
|
placed.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,1,0.5).forEach(entity -> {
|
||||||
if (entity.getType().equals(EntityType.VILLAGER)) {
|
if (entity.getType().equals(EntityType.VILLAGER)) {
|
||||||
WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity);
|
WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity);
|
||||||
if (!wVillager.isOptimized()) {
|
if (!wVillager.isOptimized()) {
|
||||||
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
|
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
|
||||||
if (shouldNotifyPlayer) {
|
if (shouldNotifyPlayer) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(player::sendMessage);
|
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(wVillager.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%blocktype%").replacement(placed.getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (shouldLog)
|
if (shouldLog)
|
||||||
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
|
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
|
||||||
@ -89,14 +92,17 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
|
|||||||
Block broken = event.getBlock();
|
Block broken = event.getBlock();
|
||||||
if (!config.blocks_that_disable.contains(broken.getType())) return;
|
if (!config.blocks_that_disable.contains(broken.getType())) return;
|
||||||
|
|
||||||
broken.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,0.5,0.5).forEach(entity -> {
|
broken.getRelative(BlockFace.UP).getLocation().getNearbyEntities(0.5,1,0.5).forEach(entity -> {
|
||||||
if (entity.getType().equals(EntityType.VILLAGER)) {
|
if (entity.getType().equals(EntityType.VILLAGER)) {
|
||||||
WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity);
|
WrappedVillager wVillager = villagerManager.getOrAdd((Villager) entity);
|
||||||
if (wVillager.getOptimizationType().equals(OptimizationType.BLOCK)) {
|
if (wVillager.getOptimizationType().equals(OptimizationType.BLOCK)) {
|
||||||
wVillager.setOptimization(OptimizationType.OFF);
|
wVillager.setOptimization(OptimizationType.OFF);
|
||||||
if (shouldNotifyPlayer) {
|
if (shouldNotifyPlayer) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(player::sendMessage);
|
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(wVillager.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%blocktype%").replacement(broken.getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (shouldLog)
|
if (shouldLog)
|
||||||
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
|
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
|
||||||
@ -121,7 +127,10 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
|
|||||||
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
|
if (wVillager.setOptimization(OptimizationType.BLOCK)) {
|
||||||
if (shouldNotifyPlayer) {
|
if (shouldNotifyPlayer) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(player::sendMessage);
|
VillagerOptimizer.getLang(player.locale()).block_optimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(wVillager.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%blocktype%").replacement(entityLegs.getBlock().getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (shouldLog)
|
if (shouldLog)
|
||||||
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
|
VillagerOptimizer.getLog().info("Villager was optimized by block at "+wVillager.villager().getLocation());
|
||||||
@ -138,7 +147,10 @@ public class BlockOptimization implements VillagerOptimizerModule, Listener {
|
|||||||
wVillager.setOptimization(OptimizationType.OFF);
|
wVillager.setOptimization(OptimizationType.OFF);
|
||||||
if (shouldNotifyPlayer) {
|
if (shouldNotifyPlayer) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(player::sendMessage);
|
VillagerOptimizer.getLang(player.locale()).block_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(wVillager.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%blocktype%").replacement(entityLegs.getBlock().getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if (shouldLog)
|
if (shouldLog)
|
||||||
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
|
VillagerOptimizer.getLog().info("Villager unoptimized because no longer standing on optimization block at "+wVillager.villager().getLocation());
|
||||||
|
@ -37,16 +37,20 @@ public class PreventVillagerDamage implements VillagerOptimizerModule, Listener
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
private void onDamageReceive(EntityDamageEvent event) {
|
private void onDamageReceive(EntityDamageEvent event) {
|
||||||
if (!event.getEntityType().equals(EntityType.VILLAGER)) return;
|
if (
|
||||||
if (villagerManager.getOrAdd((Villager) event.getEntity()).isOptimized()) {
|
!event.getEntityType().equals(EntityType.VILLAGER)
|
||||||
|
&& villagerManager.getOrAdd((Villager) event.getEntity()).isOptimized()
|
||||||
|
) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
private void onPushByEntityAttack(EntityPushedByEntityAttackEvent event) {
|
private void onPushByEntityAttack(EntityPushedByEntityAttackEvent event) {
|
||||||
if (!event.getEntityType().equals(EntityType.VILLAGER)) return;
|
if (
|
||||||
if (villagerManager.getOrAdd((Villager) event.getEntity()).isOptimized()) {
|
!event.getEntityType().equals(EntityType.VILLAGER)
|
||||||
|
&& villagerManager.getOrAdd((Villager) event.getEntity()).isOptimized()
|
||||||
|
) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package me.xginko.villageroptimizer.modules;
|
|||||||
import com.destroystokyo.paper.event.entity.EntityPathfindEvent;
|
import com.destroystokyo.paper.event.entity.EntityPathfindEvent;
|
||||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||||
import me.xginko.villageroptimizer.cache.VillagerManager;
|
import me.xginko.villageroptimizer.cache.VillagerManager;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Mob;
|
import org.bukkit.entity.Mob;
|
||||||
import org.bukkit.entity.Villager;
|
import org.bukkit.entity.Villager;
|
||||||
@ -39,14 +40,25 @@ public class PreventVillagerTargetting implements VillagerOptimizerModule, Liste
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
private void onTarget(EntityTargetLivingEntityEvent event) {
|
private void onTarget(EntityTargetLivingEntityEvent event) {
|
||||||
if (event.getTarget() instanceof Villager villager && villagerManager.getOrAdd(villager).isOptimized()) {
|
// Yes, instanceof checks would look way more beautiful here but checking type is much faster
|
||||||
|
Entity target = event.getTarget();
|
||||||
|
if (
|
||||||
|
target != null
|
||||||
|
&& target.getType().equals(EntityType.VILLAGER)
|
||||||
|
&& villagerManager.getOrAdd((Villager) target).isOptimized()
|
||||||
|
) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
private void onEntityTargetVillager(EntityPathfindEvent event) {
|
private void onEntityTargetVillager(EntityPathfindEvent event) {
|
||||||
if (event.getTargetEntity() instanceof Villager villager && villagerManager.getOrAdd(villager).isOptimized()) {
|
Entity target = event.getTargetEntity();
|
||||||
|
if (
|
||||||
|
target != null
|
||||||
|
&& target.getType().equals(EntityType.VILLAGER)
|
||||||
|
&& villagerManager.getOrAdd((Villager) target).isOptimized()
|
||||||
|
) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,10 @@ package me.xginko.villageroptimizer.modules;
|
|||||||
|
|
||||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||||
|
import me.xginko.villageroptimizer.cache.VillagerManager;
|
||||||
import me.xginko.villageroptimizer.config.Config;
|
import me.xginko.villageroptimizer.config.Config;
|
||||||
import me.xginko.villageroptimizer.models.WrappedVillager;
|
|
||||||
import me.xginko.villageroptimizer.utils.LogUtils;
|
import me.xginko.villageroptimizer.utils.LogUtils;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.Villager;
|
import org.bukkit.entity.Villager;
|
||||||
@ -15,24 +14,27 @@ import org.bukkit.event.EventPriority;
|
|||||||
import org.bukkit.event.HandlerList;
|
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;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class ChunkLimit implements VillagerOptimizerModule, Listener {
|
public class VillagerChunkLimit implements VillagerOptimizerModule, Listener {
|
||||||
|
|
||||||
private final VillagerOptimizer plugin;
|
private final VillagerOptimizer plugin;
|
||||||
|
private final VillagerManager villagerManager;
|
||||||
private ScheduledTask scheduledTask;
|
private ScheduledTask scheduledTask;
|
||||||
private final List<Villager.Profession> removalPriority = new ArrayList<>();
|
private final List<Villager.Profession> removalPriority = new ArrayList<>(16);
|
||||||
private final int maxVillagersPerChunk;
|
private final int maxVillagersPerChunk;
|
||||||
private final boolean logIsEnabled;
|
private final boolean logIsEnabled;
|
||||||
private final long checkPeriod;
|
private final long checkPeriod;
|
||||||
|
|
||||||
protected ChunkLimit() {
|
protected VillagerChunkLimit() {
|
||||||
shouldEnable();
|
shouldEnable();
|
||||||
this.plugin = VillagerOptimizer.getInstance();
|
this.plugin = VillagerOptimizer.getInstance();
|
||||||
|
this.villagerManager = VillagerOptimizer.getVillagerManager();
|
||||||
Config config = VillagerOptimizer.getConfiguration();
|
Config config = VillagerOptimizer.getConfiguration();
|
||||||
this.maxVillagersPerChunk = config.getInt("villager-chunk-limit.max-villagers-per-chunk", 25);
|
this.maxVillagersPerChunk = config.getInt("villager-chunk-limit.max-villagers-per-chunk", 25);
|
||||||
this.logIsEnabled = config.getBoolean("villager-chunk-limit.log-removals", false);
|
this.logIsEnabled = config.getBoolean("villager-chunk-limit.log-removals", false);
|
||||||
@ -70,19 +72,28 @@ public class ChunkLimit implements VillagerOptimizerModule, Listener {
|
|||||||
if (scheduledTask != null) scheduledTask.cancel();
|
if (scheduledTask != null) scheduledTask.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
private void onCreatureSpawn(CreatureSpawnEvent event) {
|
||||||
|
Entity spawned = event.getEntity();
|
||||||
|
if (spawned.getType().equals(EntityType.VILLAGER)) {
|
||||||
|
checkVillagersInChunk(spawned.getChunk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
||||||
private void onCreateSpawn(CreatureSpawnEvent event) {
|
private void onInteract(PlayerInteractEntityEvent event) {
|
||||||
if (event.getEntityType().equals(EntityType.VILLAGER)) {
|
Entity clicked = event.getRightClicked();
|
||||||
checkVillagersInChunk(event.getEntity().getChunk());
|
if (clicked.getType().equals(EntityType.VILLAGER)) {
|
||||||
|
checkVillagersInChunk(clicked.getChunk());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run() {
|
private void run() {
|
||||||
for (World world : plugin.getServer().getWorlds()) {
|
plugin.getServer().getWorlds().forEach(world -> {
|
||||||
for (Chunk chunk : world.getLoadedChunks()) {
|
for (Chunk chunk : world.getLoadedChunks()) {
|
||||||
plugin.getServer().getRegionScheduler().run(plugin, world, chunk.getX(), chunk.getZ(), task -> checkVillagersInChunk(chunk));
|
plugin.getServer().getRegionScheduler().run(plugin, world, chunk.getX(), chunk.getZ(), task -> checkVillagersInChunk(chunk));
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkVillagersInChunk(Chunk chunk) {
|
private void checkVillagersInChunk(Chunk chunk) {
|
||||||
@ -104,17 +115,14 @@ public class ChunkLimit implements VillagerOptimizerModule, Listener {
|
|||||||
// Remove prioritized villagers that are too many
|
// Remove prioritized villagers that are too many
|
||||||
for (int i = 0; i < amount_over_the_limit; i++) {
|
for (int i = 0; i < amount_over_the_limit; i++) {
|
||||||
Villager villager = villagers_in_chunk.get(i);
|
Villager villager = villagers_in_chunk.get(i);
|
||||||
if (logIsEnabled) LogUtils.moduleLog(
|
|
||||||
Level.INFO,
|
|
||||||
"villager-chunk-limit",
|
|
||||||
"Removing villager of profession type '"+villager.getProfession()+"' at "+villager.getLocation()
|
|
||||||
);
|
|
||||||
villager.remove();
|
villager.remove();
|
||||||
|
if (logIsEnabled) LogUtils.moduleLog(Level.INFO, "villager-chunk-limit",
|
||||||
|
"Removed villager of profession type '"+villager.getProfession()+"' at "+villager.getLocation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getProfessionPriority(Villager villager) {
|
private int getProfessionPriority(Villager villager) {
|
||||||
Villager.Profession profession = villager.getProfession();
|
final Villager.Profession profession = villager.getProfession();
|
||||||
return removalPriority.contains(profession) && !WrappedVillager.fromCache(villager).isOptimized() ? removalPriority.indexOf(profession) : Integer.MAX_VALUE;
|
return removalPriority.contains(profession) && !villagerManager.getOrAdd(villager).isOptimized() ? removalPriority.indexOf(profession) : Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ public interface VillagerOptimizerModule {
|
|||||||
modules.forEach(VillagerOptimizerModule::disable);
|
modules.forEach(VillagerOptimizerModule::disable);
|
||||||
modules.clear();
|
modules.clear();
|
||||||
|
|
||||||
modules.add(new ChunkLimit());
|
modules.add(new VillagerChunkLimit());
|
||||||
modules.add(new NametagOptimization());
|
modules.add(new NametagOptimization());
|
||||||
modules.add(new BlockOptimization());
|
modules.add(new BlockOptimization());
|
||||||
modules.add(new WorkstationOptimization());
|
modules.add(new WorkstationOptimization());
|
||||||
|
@ -1,28 +1,46 @@
|
|||||||
package me.xginko.villageroptimizer.modules;
|
package me.xginko.villageroptimizer.modules;
|
||||||
|
|
||||||
import io.papermc.paper.event.entity.EntityMoveEvent;
|
|
||||||
import me.xginko.villageroptimizer.VillagerOptimizer;
|
import me.xginko.villageroptimizer.VillagerOptimizer;
|
||||||
import me.xginko.villageroptimizer.config.Config;
|
|
||||||
import me.xginko.villageroptimizer.cache.VillagerManager;
|
import me.xginko.villageroptimizer.cache.VillagerManager;
|
||||||
|
import me.xginko.villageroptimizer.config.Config;
|
||||||
|
import me.xginko.villageroptimizer.enums.OptimizationType;
|
||||||
|
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.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Villager;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class WorkstationOptimization implements VillagerOptimizerModule, Listener {
|
public class WorkstationOptimization implements VillagerOptimizerModule, Listener {
|
||||||
|
|
||||||
private final VillagerManager villagerManager;
|
private final VillagerManager villagerManager;
|
||||||
private final Config config;
|
private final Config config;
|
||||||
private final boolean shouldLog, shouldNotifyPlayer;
|
private final boolean shouldLog, shouldNotifyPlayer;
|
||||||
|
private final double search_radius;
|
||||||
|
|
||||||
protected WorkstationOptimization() {
|
protected WorkstationOptimization() {
|
||||||
this.villagerManager = VillagerOptimizer.getVillagerManager();
|
this.villagerManager = VillagerOptimizer.getVillagerManager();
|
||||||
this.config = VillagerOptimizer.getConfiguration();
|
this.config = VillagerOptimizer.getConfiguration();
|
||||||
this.config.addComment("optimization.methods.by-workstation.enable", """
|
this.config.addComment("optimization.methods.by-workstation.enable", """
|
||||||
When enabled, villagers near a configured radius to a workstation specific to their profession\s
|
When enabled, villagers near a configured radius to a workstation specific to your config\s
|
||||||
will be optimized.
|
will be optimized.
|
||||||
""");
|
""");
|
||||||
|
this.search_radius = config.getDouble("optimization.methods.by-workstation.search-radius-in-blocks", 4.0, """
|
||||||
|
The radius in blocks a villager can be away from the player when he places a workstation.\s
|
||||||
|
The closest unoptimized villager to the player will be optimized.
|
||||||
|
""");
|
||||||
this.shouldLog = config.getBoolean("optimization.methods.by-workstation.log", false);
|
this.shouldLog = config.getBoolean("optimization.methods.by-workstation.log", false);
|
||||||
this.shouldNotifyPlayer = config.getBoolean("optimization.methods.by-workstation.notify-player", true);
|
this.shouldNotifyPlayer = config.getBoolean("optimization.methods.by-workstation.notify-player", true);
|
||||||
}
|
}
|
||||||
@ -43,10 +61,87 @@ public class WorkstationOptimization implements VillagerOptimizerModule, Listene
|
|||||||
return config.enable_workstation_optimization;
|
return config.enable_workstation_optimization;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
private void onEntityMove(EntityMoveEvent event) {
|
private void onBlockPlace(BlockPlaceEvent event) {
|
||||||
if (!event.getEntity().getType().equals(EntityType.VILLAGER)) return;
|
Block placed = event.getBlock();
|
||||||
|
if (!config.workstations_that_disable.contains(placed.getType())) return;
|
||||||
|
|
||||||
|
final Location workstationLoc = placed.getLocation();
|
||||||
|
|
||||||
|
List<Entity> nearbyUnoptimized = workstationLoc.getNearbyEntities(search_radius, search_radius, search_radius)
|
||||||
|
.stream().sorted(Comparator.comparingInt(entity -> {
|
||||||
|
if (entity.getType().equals(EntityType.VILLAGER)) {
|
||||||
|
Villager villager = (Villager) entity;
|
||||||
|
Villager.Profession profession = villager.getProfession();
|
||||||
|
if (
|
||||||
|
!profession.equals(Villager.Profession.NONE)
|
||||||
|
&& !profession.equals(Villager.Profession.NITWIT)
|
||||||
|
&& !villagerManager.getOrAdd(villager).isOptimized()
|
||||||
|
) {
|
||||||
|
return (int) entity.getLocation().distance(workstationLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
})).toList();
|
||||||
|
if (nearbyUnoptimized.isEmpty()) return;
|
||||||
|
|
||||||
|
WrappedVillager closest = villagerManager.getOrAdd((Villager) nearbyUnoptimized.get(0));
|
||||||
|
|
||||||
|
if (closest.setOptimization(OptimizationType.WORKSTATION)) {
|
||||||
|
if (shouldNotifyPlayer) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
VillagerOptimizer.getLang(player.locale()).workstation_optimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(closest.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%workstation%").replacement(placed.getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (shouldLog)
|
||||||
|
VillagerOptimizer.getLog().info(event.getPlayer().getName() + " optimized a villager using workstation: '" + placed.getType().toString().toLowerCase() + "'");
|
||||||
|
} 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(closest.getOptimizeCooldown())).build())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
private void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
Block placed = event.getBlock();
|
||||||
|
if (!config.workstations_that_disable.contains(placed.getType())) return;
|
||||||
|
|
||||||
|
final Location workstationLoc = placed.getLocation();
|
||||||
|
|
||||||
|
List<Entity> nearbyOptimized = workstationLoc.getNearbyEntities(search_radius, search_radius, search_radius)
|
||||||
|
.stream().sorted(Comparator.comparingInt(entity -> {
|
||||||
|
if (entity.getType().equals(EntityType.VILLAGER)) {
|
||||||
|
Villager villager = (Villager) entity;
|
||||||
|
Villager.Profession profession = villager.getProfession();
|
||||||
|
if (
|
||||||
|
!profession.equals(Villager.Profession.NONE)
|
||||||
|
&& !profession.equals(Villager.Profession.NITWIT)
|
||||||
|
&& villagerManager.getOrAdd(villager).isOptimized()
|
||||||
|
) {
|
||||||
|
return (int) entity.getLocation().distance(workstationLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
})).toList();
|
||||||
|
if (nearbyOptimized.isEmpty()) return;
|
||||||
|
|
||||||
|
WrappedVillager closest = villagerManager.getOrAdd((Villager) nearbyOptimized.get(0));
|
||||||
|
|
||||||
|
if (closest.getOptimizationType().equals(OptimizationType.WORKSTATION)) {
|
||||||
|
if (shouldNotifyPlayer) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
VillagerOptimizer.getLang(player.locale()).workstation_unoptimize_success.forEach(line -> player.sendMessage(line
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%villagertype%").replacement(closest.villager().getProfession().toString().toLowerCase()).build())
|
||||||
|
.replaceText(TextReplacementConfig.builder().matchLiteral("%workstation%").replacement(placed.getType().toString().toLowerCase()).build())
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (shouldLog)
|
||||||
|
VillagerOptimizer.getLog().info(event.getPlayer().getName() + " unoptimized a villager by breaking workstation: '" + placed.getType().toString().toLowerCase() + "'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ messages:
|
|||||||
optimize-on-cooldown:
|
optimize-on-cooldown:
|
||||||
- "<gray>You need to wait %time% until you can optimize this villager again."
|
- "<gray>You need to wait %time% until you can optimize this villager again."
|
||||||
unoptimize-success:
|
unoptimize-success:
|
||||||
- "<green>Successfully unoptimized villager by moving it off a %blocktype% block."
|
- "<green>Successfully unoptimized %villagertype% villager by removing %blocktype%."
|
||||||
workstation:
|
workstation:
|
||||||
optimize-success:
|
optimize-success:
|
||||||
- "<green>%villagertype% villager successfully optimized using workstation block %blocktype%."
|
- "<green>%villagertype% villager successfully optimized using workstation block %blocktype%."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user