Fixed talisman fetching performance

This commit is contained in:
Auxilor
2022-03-06 15:28:18 +00:00
parent ebec9062f6
commit cf45253c71
2 changed files with 74 additions and 100 deletions

View File

@@ -3,6 +3,7 @@ version rootProject.version
dependencies {
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.5'
}
build.dependsOn publishToMavenLocal

View File

@@ -1,5 +1,7 @@
package com.willfp.talismans.talismans.util
import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.config.updating.ConfigUpdater
import com.willfp.talismans.TalismansPlugin.Companion.instance
@@ -15,11 +17,18 @@ import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.BlockStateMeta
import org.bukkit.persistence.PersistentDataType
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.function.Function
object TalismanChecks {
private val CACHED_TALISMANS = Collections.synchronizedMap(HashMap<UUID, Set<Talisman>>())
private val CACHED_TALISMAN_ITEMS = Collections.synchronizedMap(WeakHashMap<UUID, Set<ItemStack>>())
private val CACHED_TALISMANS: Cache<Player, Set<Talisman>> = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build()
private val CACHED_TALISMAN_ITEMS: Cache<Player, Set<ItemStack>> = Caffeine.newBuilder()
.expireAfterWrite(2, TimeUnit.SECONDS)
.build()
private val PROVIDERS: MutableSet<Function<Player, List<ItemStack>>> = HashSet()
private var readEnderChest = true
@@ -76,17 +85,6 @@ object TalismanChecks {
return getByID(id)
}
/**
* Get all talismans that a player has active.
*
* @param player The player to query.
* @return A set of all found talismans.
*/
@JvmStatic
fun getTalismansOnPlayer(player: Player): Set<Talisman> {
return getTalismansOnPlayer(player, true)
}
/**
* Get all talismans ItemStacks that a player has active.
*
@@ -98,117 +96,92 @@ object TalismanChecks {
@JvmStatic
fun getTalismanItemsOnPlayer(
player: Player,
useCache: Boolean,
vararg extra: ItemStack?
): Set<ItemStack> {
if (useCache) {
val cached = CACHED_TALISMAN_ITEMS[player.uniqueId]
if (cached != null) {
return cached
return CACHED_TALISMAN_ITEMS.get(player) {
val contents = mutableListOf<ItemStack>()
val rawContents = it.inventory.contents.toMutableList()
if (readEnderChest) {
val enderChest = it.enderChest as Inventory?
// Not always true, bug reported where it was null.
if (enderChest != null) {
rawContents.addAll(enderChest.contents)
}
}
}
val contents = mutableListOf<ItemStack>()
val rawContents = player.inventory.contents.toMutableList()
if (readEnderChest) {
val enderChest = player.enderChest as Inventory?
// Not always true, bug reported where it was null.
if (enderChest != null) {
rawContents.addAll(enderChest.contents)
if (offhandOnly) {
rawContents.clear()
rawContents.add(it.inventory.itemInOffHand)
}
}
if (offhandOnly) {
rawContents.clear()
rawContents.add(player.inventory.itemInOffHand)
}
rawContents.addAll(extra)
for (provider in PROVIDERS) {
rawContents.addAll(provider.apply(player))
}
for (rawContent in rawContents) {
if (rawContent == null) {
continue
rawContents.addAll(extra)
for (provider in PROVIDERS) {
rawContents.addAll(provider.apply(it))
}
if (readShulkerBoxes) {
val meta = rawContent.itemMeta
if (meta is BlockStateMeta) {
val shulkerMeta = meta
if (!shulkerMeta.hasBlockState()) {
continue
for (rawContent in rawContents) {
if (rawContent == null) {
continue
}
if (readShulkerBoxes) {
val meta = rawContent.itemMeta
if (meta is BlockStateMeta) {
val shulkerMeta = meta
if (!shulkerMeta.hasBlockState()) {
continue
}
val state = shulkerMeta.blockState
if (state is ShulkerBox) {
contents.addAll(state.inventory.contents)
continue
}
}
val state = shulkerMeta.blockState
if (state is ShulkerBox) {
contents.addAll(state.inventory.contents)
continue
}
contents.add(rawContent)
}
val items = mutableMapOf<Talisman, ItemStack>()
for (itemStack in contents) {
convert(itemStack)
val talis = getTalismanOnItem(itemStack) ?: continue
if (items.size >= getLimit(it)) {
break
}
items[talis] = itemStack
}
if (PLUGIN.configYml.getBool("top-level-only")) {
for ((talisman, _) in items.toMap()) {
var lowerLevel = talisman.lowerLevel
while (lowerLevel != null) {
items.remove(lowerLevel)
lowerLevel = lowerLevel.lowerLevel
}
}
}
contents.add(rawContent)
items.values.toSet()
}
val items = mutableMapOf<Talisman, ItemStack>()
for (itemStack in contents) {
convert(itemStack)
val talis = getTalismanOnItem(itemStack) ?: continue
if (items.size >= getLimit(player)) {
break
}
items[talis] = itemStack
}
if (PLUGIN.configYml.getBool("top-level-only")) {
for ((talisman, _) in items.toMap()) {
var lowerLevel = talisman.lowerLevel
while (lowerLevel != null) {
items.remove(lowerLevel)
lowerLevel = lowerLevel.lowerLevel
}
}
}
if (useCache) {
CACHED_TALISMAN_ITEMS[player.uniqueId] = items.values.toSet()
PLUGIN.scheduler.runLater({ CACHED_TALISMAN_ITEMS.remove(player.uniqueId) }, 40)
}
return items.values.toSet()
}
/**
* Get all talismans that a player has active.
*
* @param player The player to query.
* @param useCache If the cache should be checked.
* @param extra Bonus items.
* @return A set of all found talismans.
*/
@JvmStatic
fun getTalismansOnPlayer(
player: Player,
useCache: Boolean,
vararg extra: ItemStack?
): Set<Talisman> {
if (useCache) {
val cached = CACHED_TALISMANS[player.uniqueId]
if (cached != null) {
return cached
}
return CACHED_TALISMANS.get(player) {
getTalismanItemsOnPlayer(it, *extra).mapNotNull { itemStack -> getTalismanOnItem(itemStack) }.toSet()
}
val found = getTalismanItemsOnPlayer(player, useCache, *extra).mapNotNull { getTalismanOnItem(it) }.toSet()
if (useCache) {
CACHED_TALISMANS[player.uniqueId] = found
PLUGIN.scheduler.runLater({ CACHED_TALISMANS.remove(player.uniqueId) }, 40)
}
return found
}
/**
@@ -218,12 +191,12 @@ object TalismanChecks {
*/
@JvmStatic
fun clearCache(player: Player) {
CACHED_TALISMAN_ITEMS.remove(player.uniqueId)
CACHED_TALISMANS.remove(player.uniqueId)
CACHED_TALISMAN_ITEMS.invalidate(player)
CACHED_TALISMANS.invalidate(player)
}
/**
* Register ItemStack provider (inventory extension, eg talisman bag).
* Register ItemStack provider (inventory extension, e.g. talisman bag).
*
* @param provider The provider.
*/