Fixed CustomEnchantLookup performance issues

This commit is contained in:
Auxilor
2022-03-06 13:00:58 +00:00
parent 7ff86f187a
commit 6deea17b85
2 changed files with 51 additions and 56 deletions

View File

@@ -10,5 +10,6 @@ dependencies {
compileOnly 'io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
compileOnly 'io.lumine.xikage:MythicMobs:4.9.1'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.5'
compileOnly fileTree(dir: '../../lib', include: ['*.jar'])
}

View File

@@ -1,5 +1,7 @@
package com.willfp.ecoenchants.enchantments.custom;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.willfp.eco.core.EcoPlugin;
import com.willfp.ecoenchants.EcoEnchantsPlugin;
import com.willfp.ecoenchants.enchantments.EcoEnchant;
@@ -17,8 +19,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class CustomEnchantLookup {
@@ -30,12 +31,16 @@ public class CustomEnchantLookup {
/**
* Cached items.
*/
private static final Map<UUID, Map<ItemStack, EnchantmentTarget.Slot>> ITEM_CACHE = new WeakHashMap<>();
private static final Cache<Player, Map<ItemStack, EnchantmentTarget.Slot>> ITEM_CACHE = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build();
/**
* Cached enchant levels.
*/
private static final Map<UUID, Collection<CustomEcoEnchantLevel>> ENCHANT_LEVELS_CACHE = new WeakHashMap<>();
private static final Cache<Player, Collection<CustomEcoEnchantLevel>> ENCHANT_LEVELS_CACHE = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build();
/**
* Instance of EcoEnchants.
@@ -54,73 +59,62 @@ public class CustomEnchantLookup {
/**
* Provide ItemStacks.
*
* @param player The player.
* @param p The player.
* @return The ItemStacks.
*/
public static Map<ItemStack, EnchantmentTarget.Slot> provide(@NotNull final Player player) {
if (ITEM_CACHE.containsKey(player.getUniqueId())) {
return new HashMap<>(ITEM_CACHE.get(player.getUniqueId()));
}
Map<ItemStack, EnchantmentTarget.Slot> found = new HashMap<>();
for (Function<Player, Map<ItemStack, EnchantmentTarget.Slot>> provider : PROVIDERS) {
found.putAll(provider.apply(player));
}
found.keySet().removeIf(Objects::isNull);
ITEM_CACHE.put(player.getUniqueId(), found);
PLUGIN.getScheduler().runLater(() -> ITEM_CACHE.remove(player.getUniqueId()), 40);
return found;
public static Map<ItemStack, EnchantmentTarget.Slot> provide(@NotNull final Player p) {
return ITEM_CACHE.get(p, player -> {
Map<ItemStack, EnchantmentTarget.Slot> found = new HashMap<>();
for (Function<Player, Map<ItemStack, EnchantmentTarget.Slot>> provider : PROVIDERS) {
found.putAll(provider.apply(player));
}
found.keySet().removeIf(Objects::isNull);
return found;
});
}
/**
* Provide levels.
*
* @param player The player.
* @param p The player.
* @return The levels.
*/
public static List<CustomEcoEnchantLevel> provideLevels(@NotNull final Player player) {
if (ENCHANT_LEVELS_CACHE.containsKey(player.getUniqueId())) {
return new ArrayList<>(ENCHANT_LEVELS_CACHE.get(player.getUniqueId()));
}
public static List<CustomEcoEnchantLevel> provideLevels(@NotNull final Player p) {
return new ArrayList<>(ENCHANT_LEVELS_CACHE.get(p, player -> {
List<CustomEcoEnchantLevel> found = new ArrayList<>();
List<CustomEcoEnchantLevel> found = new ArrayList<>();
for (Map.Entry<ItemStack, EnchantmentTarget.Slot> entry : provide(player).entrySet()) {
ItemStack itemStack = entry.getKey();
EnchantmentTarget.Slot slot = entry.getValue();
if (itemStack == null) {
continue;
}
Map<EcoEnchant, Integer> enchants = EnchantChecks.getEnchantsOnItem(itemStack);
if (enchants.isEmpty()) {
continue;
}
for (Map.Entry<EcoEnchant, Integer> enchantEntry : enchants.entrySet()) {
if (!(enchantEntry.getKey() instanceof CustomEcoEnchant enchant)) {
for (Map.Entry<ItemStack, EnchantmentTarget.Slot> entry : provide(player).entrySet()) {
ItemStack itemStack = entry.getKey();
EnchantmentTarget.Slot slot = entry.getValue();
if (itemStack == null) {
continue;
}
if (slot != EnchantmentTarget.Slot.ANY) {
if (!enchant.getTargets().stream()
.map(EnchantmentTarget::getSlot).toList()
.contains(slot)) {
continue;
}
Map<EcoEnchant, Integer> enchants = EnchantChecks.getEnchantsOnItem(itemStack);
if (enchants.isEmpty()) {
continue;
}
found.add(enchant.getLevel(enchantEntry.getValue()));
for (Map.Entry<EcoEnchant, Integer> enchantEntry : enchants.entrySet()) {
if (!(enchantEntry.getKey() instanceof CustomEcoEnchant enchant)) {
continue;
}
if (slot != EnchantmentTarget.Slot.ANY) {
if (!enchant.getTargets().stream()
.map(EnchantmentTarget::getSlot).toList()
.contains(slot)) {
continue;
}
}
found.add(enchant.getLevel(enchantEntry.getValue()));
}
}
}
ENCHANT_LEVELS_CACHE.put(player.getUniqueId(), found);
PLUGIN.getScheduler().runLater(() -> ENCHANT_LEVELS_CACHE.remove(player.getUniqueId()), 40);
return found;
return found;
}));
}
/**
@@ -129,8 +123,8 @@ public class CustomEnchantLookup {
* @param player The player.
*/
public static void clearCache(@NotNull final Player player) {
ITEM_CACHE.remove(player.getUniqueId());
ENCHANT_LEVELS_CACHE.remove(player.getUniqueId());
ITEM_CACHE.invalidate(player);
ENCHANT_LEVELS_CACHE.invalidate(player);
}
static {