add ability to leash villagers

This commit is contained in:
xGinko 2024-01-31 14:47:38 +01:00
parent 63744345e2
commit a718e9daeb
4 changed files with 127 additions and 2 deletions

View File

@ -6,7 +6,7 @@
<groupId>me.xginko.VillagerOptimizer</groupId>
<artifactId>VillagerOptimizer</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
<packaging>jar</packaging>
<name>VillagerOptimizer</name>

View File

@ -1,6 +1,5 @@
package me.xginko.villageroptimizer.modules;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.modules.gameplay.*;
import me.xginko.villageroptimizer.modules.optimization.OptimizeByBlock;
import me.xginko.villageroptimizer.modules.optimization.OptimizeByNametag;
@ -31,6 +30,7 @@ public interface VillagerOptimizerModule {
modules.add(new PreventUnoptimizedTrading());
modules.add(new PreventOptimizedTargeting());
modules.add(new PreventOptimizedDamage());
modules.add(new EnableLeashingVillagers());
modules.add(new VillagerChunkLimit());

View File

@ -0,0 +1,96 @@
package me.xginko.villageroptimizer.modules.gameplay;
import me.xginko.villageroptimizer.VillagerCache;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.config.Config;
import me.xginko.villageroptimizer.modules.VillagerOptimizerModule;
import me.xginko.villageroptimizer.utils.ExpiringSet;
import org.bukkit.Material;
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.entity.PlayerLeashEntityEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import java.time.Duration;
import java.util.UUID;
public class EnableLeashingVillagers implements VillagerOptimizerModule, Listener {
private final VillagerCache villagerCache;
private final ExpiringSet<UUID> villagersGettingLeashed;
private final boolean only_optimized;
public EnableLeashingVillagers() {
shouldEnable();
this.villagerCache = VillagerOptimizer.getCache();
this.villagersGettingLeashed = new ExpiringSet<>(Duration.ofSeconds(1));
Config config = VillagerOptimizer.getConfiguration();
config.master().addComment("gameplay.villagers-can-be-leashed.enable", """
Enable leashing of villagers, enabling players to easily move villagers to where they want them to be.""");
this.only_optimized = config.getBoolean("gameplay.villagers-can-be-leashed.only-optimized", false,
"If set to true, only optimized villagers can be leashed.");
}
@Override
public void enable() {
VillagerOptimizer plugin = VillagerOptimizer.getInstance();
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@Override
public void disable() {
HandlerList.unregisterAll(this);
}
@Override
public boolean shouldEnable() {
return VillagerOptimizer.getConfiguration().getBoolean("gameplay.villagers-can-be-leashed.enable", false);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onLeash(PlayerInteractEntityEvent event) {
if (!event.getRightClicked().getType().equals(EntityType.VILLAGER)) return;
Player player = event.getPlayer();
if (!player.getInventory().getItem(event.getHand()).getType().equals(Material.LEAD)) return;
Villager villager = (Villager) event.getRightClicked();
if (villager.isLeashed()) return;
if (only_optimized && !villagerCache.getOrAdd(villager).isOptimized()) return;
// Call event for compatibility with plugins listening to leashing, constructing non deprecated if available.
PlayerLeashEntityEvent leashEvent;
try {
leashEvent = new PlayerLeashEntityEvent(villager, player, player, event.getHand());
} catch (Exception e) {
leashEvent = new PlayerLeashEntityEvent(villager, player, player);
}
if (!leashEvent.callEvent()) return;
VillagerOptimizer.getFoliaLib().getImpl().runAtEntity(villager, leash -> {
// Legitimate like this since values in PlayerLeashEntityEvent are final and can therefore never be changed by a plugin
if (villager.setLeashHolder(player)) {
villagersGettingLeashed.add(villager.getUniqueId());
}
});
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
private void onInventoryOpen(InventoryOpenEvent event) {
if (
event.getInventory().getType().equals(InventoryType.MERCHANT)
&& event.getInventory().getHolder() instanceof Villager villager
&& villagersGettingLeashed.contains(villager.getUniqueId())
) {
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,29 @@
package me.xginko.villageroptimizer.utils;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
public final class ExpiringSet<E> {
private final Cache<E, Object> cache;
private static final Object PRESENT = new Object(); // Dummy value to associate with an Object in the backing Cache
public ExpiringSet(long duration, TimeUnit unit) {
this.cache = Caffeine.newBuilder().expireAfterWrite(duration, unit).build();
}
public ExpiringSet(Duration duration) {
this.cache = Caffeine.newBuilder().expireAfterWrite(duration).build();
}
public void add(E item) {
this.cache.put(item, PRESENT);
}
public boolean contains(E item) {
return this.cache.getIfPresent(item) != null;
}
}