redsign helper methods into a wrapper and utilize caching

This commit is contained in:
xGinko 2023-09-05 01:56:06 +02:00
parent d542755a49
commit a84fe51953
9 changed files with 147 additions and 152 deletions

View File

@ -82,5 +82,10 @@
<version>v2.0.0-BETA-9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,40 @@
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.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Villager;
import org.bukkit.plugin.java.JavaPlugin;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
public class VillagerCache {
private final Cache<UUID, WrappedVillager> villagerCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofSeconds(30)).build();
public VillagerCache(JavaPlugin plugin) {
plugin.getServer().getGlobalRegionScheduler().run(plugin, populateCache -> {
for (World world : plugin.getServer().getWorlds()) {
for (Entity entity : world.getEntities()) {
if (entity instanceof Villager villager) {
this.villagerCache.put(villager.getUniqueId(), new WrappedVillager(villager));
}
}
}
});
}
public WrappedVillager getVillager(Villager villager) {
WrappedVillager wrappedVillager = villagerCache.getIfPresent(villager.getUniqueId());
if (wrappedVillager == null) wrappedVillager = new WrappedVillager(villager);
this.villagerCache.put(villager.getUniqueId(), wrappedVillager);
return wrappedVillager;
}
public Map<UUID, WrappedVillager> get() {
return this.villagerCache.asMap();
}
}

View File

@ -0,0 +1,22 @@
package me.xginko.villageroptimizer.enums;
import me.xginko.villageroptimizer.VillagerOptimizer;
import org.bukkit.NamespacedKey;
public enum NamespacedKeys {
OPTIMIZED(VillagerOptimizer.getKey("optimized")),
COOLDOWN_RESTOCK(VillagerOptimizer.getKey("restock-cooldown")),
COOLDOWN_EXPERIENCE(VillagerOptimizer.getKey("experience-cooldown")),
GAME_TIME(VillagerOptimizer.getKey("game-time"));
private final NamespacedKey key;
NamespacedKeys(NamespacedKey key) {
this.key = key;
}
public NamespacedKey get() {
return key;
}
}

View File

@ -0,0 +1,11 @@
package me.xginko.villageroptimizer.enums;
public enum OptimizationType {
COMMAND,
NAMETAG,
WORKSTATION,
BLOCK,
OFF
}

View File

@ -1,17 +0,0 @@
package me.xginko.villageroptimizer.models;
import org.bukkit.entity.Villager;
public class OptimizedVillager {
private final Villager villager;
public OptimizedVillager(Villager villager) {
this.villager = villager;
}
public Villager villager() {
return villager;
}
}

View File

@ -0,0 +1,67 @@
package me.xginko.villageroptimizer.models;
import me.xginko.villageroptimizer.enums.NamespacedKeys;
import me.xginko.villageroptimizer.enums.OptimizationType;
import org.bukkit.entity.Villager;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
public record WrappedVillager(Villager villager) {
public long getLevel() {
// Villager Level depending on their XP (source: https://minecraft.fandom.com/wiki/Trading#Mechanics)
final int experience = villager.getVillagerExperience();
if (experience >= 250) return 5;
if (experience >= 150) return 4;
if (experience >= 70) return 3;
if (experience >= 10) return 2;
return 1;
}
public boolean isOptimized() {
return villager.getPersistentDataContainer().has(NamespacedKeys.OPTIMIZED.get());
}
public void setOptimization(OptimizationType type) {
if (type.equals(OptimizationType.OFF) && isOptimized()) {
villager.getPersistentDataContainer().remove(NamespacedKeys.OPTIMIZED.get());
} else {
villager.getPersistentDataContainer().set(NamespacedKeys.OPTIMIZED.get(), PersistentDataType.STRING, type.name());
}
}
public OptimizationType getOptimizationType() {
return isOptimized() ? OptimizationType.valueOf(villager().getPersistentDataContainer().get(NamespacedKeys.OPTIMIZED.get(), PersistentDataType.STRING)) : OptimizationType.OFF;
}
public void setRestockCooldown(long milliseconds) {
villager.getPersistentDataContainer().set(NamespacedKeys.COOLDOWN_RESTOCK.get(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
}
public boolean shouldRestock() {
PersistentDataContainer villagerData = villager.getPersistentDataContainer();
return villagerData.has(NamespacedKeys.COOLDOWN_RESTOCK.get(), PersistentDataType.LONG) && villagerData.get(NamespacedKeys.COOLDOWN_RESTOCK.get(), PersistentDataType.LONG) <= System.currentTimeMillis();
}
public void restock() {
villager.getRecipes().forEach(recipe -> recipe.setUses(0));
}
public void setExpCooldown(long milliseconds) {
villager.getPersistentDataContainer().set(NamespacedKeys.COOLDOWN_EXPERIENCE.get(), PersistentDataType.LONG, System.currentTimeMillis() + milliseconds);
}
public boolean isOnExpCooldown() {
PersistentDataContainer villagerData = villager.getPersistentDataContainer();
return villagerData.has(NamespacedKeys.COOLDOWN_EXPERIENCE.get(), PersistentDataType.LONG) && villagerData.get(NamespacedKeys.COOLDOWN_EXPERIENCE.get(), PersistentDataType.LONG) <= System.currentTimeMillis();
}
public void saveWorldTime() {
villager.getPersistentDataContainer().set(NamespacedKeys.GAME_TIME.get(), PersistentDataType.LONG, villager.getWorld().getFullTime());
}
public long getSavedWorldTime() {
PersistentDataContainer villagerData = villager.getPersistentDataContainer();
return villagerData.has(NamespacedKeys.GAME_TIME.get(), PersistentDataType.LONG) ? villagerData.get(NamespacedKeys.GAME_TIME.get(), PersistentDataType.LONG) : villager.getWorld().getFullTime();
}
}

View File

@ -1,21 +0,0 @@
package me.xginko.villageroptimizer.utils;
import org.bukkit.entity.Villager;
public class CalculateLevel {
public static long villagerEXP (Villager vil) {
int vilEXP = vil.getVillagerExperience();
// Villager Level depending on their XP
// source: https://minecraft.fandom.com/wiki/Trading#Mechanics
if (vilEXP >= 250) return 5;
if (vilEXP >= 150) return 4;
if (vilEXP >= 70) return 3;
if (vilEXP >= 10) return 2;
// default level is 1
return 1;
}
}

View File

@ -1,24 +0,0 @@
package me.xginko.villageroptimizer.utils;
import me.xginko.villageroptimizer.VillagerOptimizer;
import org.bukkit.NamespacedKey;
public enum NamespacedKeys {
COOLDOWN(VillagerOptimizer.getKey("cooldown")),
TIME(VillagerOptimizer.getKey("time")),
LEVEL_COOLDOWN(VillagerOptimizer.getKey("level-cooldown")),
NAMETAG_DISABLED(VillagerOptimizer.getKey("nametag-disabled")),
BLOCK_DISABLED(VillagerOptimizer.getKey("block-disabled")),
WORKSTATION_DISABLED(VillagerOptimizer.getKey("workstation-disabled"));
private final NamespacedKey key;
NamespacedKeys(NamespacedKey key) {
this.key = key;
}
public NamespacedKey get() {
return key;
}
}

View File

@ -1,28 +1,14 @@
package me.xginko.villageroptimizer.utils;
import me.xginko.villageroptimizer.VillagerOptimizer;
import me.xginko.villageroptimizer.models.WrappedVillager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.MerchantRecipe;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Optional;
public class VillagerUtils {
public static boolean isDisabled(Villager villager) {
return hasDisabledByBlock(villager) || hasDisabledByWorkstation(villager) || hasMarker(villager);
}
public static void restockTrades(Villager villager) {
for (MerchantRecipe recipe : villager.getRecipes()) {
recipe.setUses(0);
}
}
public static boolean shouldDisable(Villager villager) {
// Check nametag
Component nameTag = villager.customName();
@ -38,80 +24,6 @@ public class VillagerUtils {
}
// Check Workstation
return getDisabledByWorkstation(villager).orElse(false);
}
/*
*
* Helper Methods for storing and reading data inside villagers using PersistentDataContainer
*
* */
// Disabled by Block
public static void setDisabledByBlock(Villager villager, boolean state) {
villager.getPersistentDataContainer().set(NamespacedKeys.BLOCK_DISABLED.get(), PersistentDataType.BOOLEAN, state);
}
public static boolean isDisabledByBlock(Villager villager) {
if (villager.getPersistentDataContainer().has(NamespacedKeys.BLOCK_DISABLED.get(), PersistentDataType.BOOLEAN)) {
return villager.getPersistentDataContainer().get(NamespacedKeys.BLOCK_DISABLED.get(), PersistentDataType.BOOLEAN);
} else {
setDisabledByBlock(villager, false);
return false;
}
}
// Disabled by Workstation
public static void setDisabledByWorkstation(Villager villager, Boolean state) {
villager.getPersistentDataContainer().set(NamespacedKeys.WORKSTATION_DISABLED.get(), PersistentDataType.BOOLEAN, state);
}
public static boolean hasDisabledByWorkstation(Villager villager) {
return villager.getPersistentDataContainer().has(NamespacedKeys.WORKSTATION_DISABLED.get(), PersistentDataType.BOOLEAN);
}
public static Optional<Boolean> getDisabledByWorkstation(Villager villager) {
return Optional.ofNullable(villager.getPersistentDataContainer().get(NamespacedKeys.WORKSTATION_DISABLED.get(), PersistentDataType.BOOLEAN));
}
// Cooldown
public static void setCooldown(Villager villager, long cooldown_millis) {
villager.getPersistentDataContainer().set(NamespacedKeys.COOLDOWN.get(), PersistentDataType.LONG, System.currentTimeMillis() + cooldown_millis);
}
public static boolean hasCooldown(Villager villager) {
return villager.getPersistentDataContainer().has(NamespacedKeys.COOLDOWN.get(), PersistentDataType.LONG);
}
public static Optional<Long> getCooldown(Villager villager) {
return Optional.ofNullable(villager.getPersistentDataContainer().get(NamespacedKeys.COOLDOWN.get(), PersistentDataType.LONG));
}
// Time
public static void setTime(Villager villager) {
villager.getPersistentDataContainer().set(NamespacedKeys.TIME.get(), PersistentDataType.LONG, villager.getWorld().getFullTime());
}
public static boolean hasTime(Villager villager) {
return villager.getPersistentDataContainer().has(NamespacedKeys.TIME.get(), PersistentDataType.LONG);
}
public static Optional<Long> getTime(Villager villager) {
return Optional.ofNullable(villager.getPersistentDataContainer().get(NamespacedKeys.TIME.get(), PersistentDataType.LONG));
}
// Level Cooldown
public static void setLevelCooldown(Villager villager, long cooldown_millis) {
villager.getPersistentDataContainer().set(NamespacedKeys.LEVEL_COOLDOWN.get(), PersistentDataType.LONG, System.currentTimeMillis() + cooldown_millis);
}
public static boolean hasLevelCooldown(Villager villager, JavaPlugin plugin) {
return villager.getPersistentDataContainer().has(NamespacedKeys.LEVEL_COOLDOWN.get(), PersistentDataType.LONG);
}
public static Optional<Long> getLevelCooldown(Villager villager) {
return Optional.ofNullable(villager.getPersistentDataContainer().get(NamespacedKeys.LEVEL_COOLDOWN.get(), PersistentDataType.LONG));
}
// Marker
public static void setMarker(Villager villager) {
villager.getPersistentDataContainer().set(NamespacedKeys.NAMETAG_DISABLED.get(), PersistentDataType.BYTE, (byte)1);
}
public static boolean hasMarker(Villager villager) {
return villager.getPersistentDataContainer().has(NamespacedKeys.NAMETAG_DISABLED.get(), PersistentDataType.BYTE);
}
public static void removeMarker(Villager villager) {
villager.getPersistentDataContainer().remove(NamespacedKeys.NAMETAG_DISABLED.get());
return new WrappedVillager(villager).isOptimized();
}
}