Skip to content

Commit 8919f2a

Browse files
committed
refactor(heads): 优化材质获取逻辑并升级依赖版本
- 将 Heads.kt 中的材质获取改为异步非阻塞方式 - 添加 ConcurrentHashMap 缓存机制提升性能 - 实现黑名单功能防止重复失败请求 - 升级 taboolib 依赖从 2.0.27 到 2.0.30 版本 - 修改 gradle.properties 项目版本为 3.9.25
1 parent edce89a commit 8919f2a

3 files changed

Lines changed: 65 additions & 6 deletions

File tree

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
java
66
idea
77
kotlin("jvm") version "2.1.0"
8-
id("io.izzel.taboolib") version "2.0.27"
8+
id("io.izzel.taboolib") version "2.0.30"
99
}
1010

1111
// 这段。一言难尽,但我不想动 (依托)
@@ -72,7 +72,7 @@ subprojects {
7272
disableOnSkippedVersion = false
7373
}
7474
version {
75-
taboolib = "6.2.4-e6c8347"
75+
taboolib = "6.2.4-86dd2bf"
7676
coroutines = null
7777
}
7878
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
group=me.arasple.mc.trmenu
2-
version=3.9.24
2+
version=3.9.25

plugin/src/main/kotlin/trplugins/menu/util/bukkit/Heads.kt

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ import taboolib.library.reflex.Reflex.Companion.invokeMethod
1414
import taboolib.library.xseries.XMaterial
1515
import taboolib.module.nms.MinecraftVersion
1616
import taboolib.platform.util.BukkitSkull
17+
import taboolib.common.platform.function.submit
1718
import trplugins.menu.module.internal.hook.HookPlugin
1819
import java.io.BufferedReader
1920
import java.io.InputStreamReader
2021
import java.net.URL
2122
import java.util.*
23+
import java.util.concurrent.ConcurrentHashMap
2224

2325
/**
2426
* @author Arasple
@@ -43,6 +45,16 @@ object Heads {
4345
private val NAME = if (MinecraftVersion.major >= 1.20) "name" else "getName"
4446
private val USE_PROFILE = runCatching { OfflinePlayer::class.java.getDeclaredMethod("getPlayerProfile") }.isSuccess
4547

48+
// 异步材质缓存: 玩家名 -> 材质URL
49+
private val textureCache = ConcurrentHashMap<String, String>()
50+
// 正在异步加载中的玩家名集合,防止重复请求
51+
private val loading = ConcurrentHashMap.newKeySet<String>()
52+
// 获取失败计数: 玩家名 -> 失败次数
53+
private val failedCount = ConcurrentHashMap<String, Int>()
54+
// 失败超过3次后加入黑名单,不再请求
55+
private val blacklisted = ConcurrentHashMap.newKeySet<String>()
56+
private const val MAX_RETRIES = 3
57+
4658
fun cacheSize(): Int {
4759
return CACHED_SKULLS.size
4860
}
@@ -87,7 +99,7 @@ object Heads {
8799
if (player != null) {
88100
return getPlayerHead(player)
89101
}
90-
val texture = seekTexture(name)
102+
val texture = seekTextureAsync(name)
91103
return if (texture == null) DEFAULT_HEAD else getCustomHead(texture)
92104
}
93105

@@ -101,7 +113,7 @@ object Heads {
101113
return getCustomHead(texture.getProperty<String>(VALUE)!!)
102114
}
103115
}
104-
val texture = seekTexture(player.name)
116+
val texture = seekTextureAsync(player.name)
105117
return if (texture == null) DEFAULT_HEAD else getCustomHead(texture)
106118
}
107119
}
@@ -119,7 +131,50 @@ object Heads {
119131
return null
120132
}
121133

122-
fun seekTexture(name: String): String? {
134+
/**
135+
* 非阻塞获取材质:返回缓存值或 null,并在后台异步请求 Mojang API
136+
* 首次调用返回 null(显示默认头颅),下次菜单刷新时从缓存获取
137+
* 失败超过 3 次后将该名称加入黑名单,不再请求
138+
*/
139+
private fun seekTextureAsync(name: String): String? {
140+
val key = name.lowercase()
141+
// 已缓存直接返回
142+
textureCache[key]?.let { return it }
143+
// 已被黑名单标记,不再请求
144+
if (key in blacklisted) return null
145+
// 未在加载中则发起异步请求
146+
if (loading.add(key)) {
147+
submit(async = true) {
148+
try {
149+
val texture = fetchTexture(name)
150+
if (texture != null) {
151+
textureCache[key] = texture
152+
failedCount.remove(key)
153+
} else {
154+
recordFailure(key)
155+
}
156+
} catch (_: Exception) {
157+
recordFailure(key)
158+
} finally {
159+
loading.remove(key)
160+
}
161+
}
162+
}
163+
return null
164+
}
165+
166+
private fun recordFailure(key: String) {
167+
val count = failedCount.merge(key, 1) { old, inc -> old + inc } ?: 1
168+
if (count >= MAX_RETRIES) {
169+
blacklisted.add(key)
170+
failedCount.remove(key)
171+
}
172+
}
173+
174+
/**
175+
* 实际执行 HTTP 请求获取材质(仅在异步线程调用)
176+
*/
177+
private fun fetchTexture(name: String): String? {
123178
val user = urlJson(USER_API + name)
124179
if (user != null && user.has("id")) {
125180
val uuid = user["id"].asString
@@ -140,6 +195,10 @@ object Heads {
140195
return null
141196
}
142197

198+
fun seekTexture(name: String): String? {
199+
return textureCache[name.lowercase()]
200+
}
201+
143202
private fun urlJson(url: String): JsonObject? {
144203
val text = urlText(url)
145204
return if (text.trim { it <= ' ' }.isEmpty()) {

0 commit comments

Comments
 (0)