Skip to content

Commit 1f4460d

Browse files
committed
fix(menu): 修复菜单标题显示和窗口同步问题
- 更新版本号从 3.9.19 到 3.9.21 - 添加统一的标题格式化方法支持组件和颜色解析 - 修复 1.21.11+ 版本下副手槽位更新导致的崩溃问题 - 优化窗口接收器中的玩家视图验证逻辑 - 改进窗口属性更新时的安全检查机制 - 移除关闭窗口后的空悬引用防止内存泄漏
1 parent 30b82c6 commit 1f4460d

5 files changed

Lines changed: 51 additions & 30 deletions

File tree

api/receptacle/src/main/kotlin/trplugins/menu/api/receptacle/vanilla/window/WindowListener.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ object WindowListener {
106106
receptacle.callEventClick(evt)
107107
if (evt.isCancelled) {
108108
if (clickType == ReceptacleClickType.OFFHAND) {
109-
nmsProxy<NMS>().sendWindowsSetSlot(player, windowId = 0, slot = 45)
109+
if (MinecraftVersion.majorLegacy < 12111) {
110+
nmsProxy<NMS>().sendWindowsSetSlot(player, windowId = 0, slot = 45)
111+
} else {
112+
nmsProxy<NMS>().sendWindowsSetSlot(player, slot = -1, windowId = -1)
113+
}
110114
} else {
111115
nmsProxy<NMS>().sendWindowsSetSlot(player, slot = -1, windowId = -1)
112116
}
@@ -129,4 +133,4 @@ object WindowListener {
129133
}
130134
}
131135
}
132-
}
136+
}

api/receptacle/src/main/kotlin/trplugins/menu/api/receptacle/vanilla/window/WindowReceptacle.kt

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import org.bukkit.entity.Player
44
import org.bukkit.inventory.ItemStack
55
import taboolib.common.platform.function.submit
66
import taboolib.module.chat.component
7+
import taboolib.module.nms.MinecraftVersion
78
import taboolib.module.nms.nmsProxy
89
import trplugins.menu.api.receptacle.Receptacle
910
import trplugins.menu.api.receptacle.ReceptacleInteractEvent
11+
import trplugins.menu.api.receptacle.getViewingReceptacle
1012
import trplugins.menu.api.receptacle.setViewingReceptacle
1113

1214
/**
@@ -47,8 +49,9 @@ open class WindowReceptacle(var type: WindowLayout, override var title: String =
4749

4850
override fun setElement(element: ItemStack?, slot: Int, display: Boolean) {
4951
contents[slot] = element
50-
if (!display || viewer == null) return
51-
nmsProxy<NMS>().sendWindowsSetSlot(viewer!!, slot = slot, itemStack = element, stateId = stateId)
52+
val player = viewer ?: return
53+
if (!display || player.getViewingReceptacle() != this) return
54+
nmsProxy<NMS>().sendWindowsSetSlot(player, slot = slot, itemStack = element, stateId = stateId)
5255
}
5356

5457
override fun clear(display: Boolean) {
@@ -59,22 +62,22 @@ open class WindowReceptacle(var type: WindowLayout, override var title: String =
5962
}
6063

6164
override fun refresh(slot: Int) {
62-
if (viewer != null) {
63-
setupPlayerInventorySlots()
64-
runCatching {
65-
if (slot >= 0) {
66-
nmsProxy<NMS>().sendWindowsSetSlot(viewer!!, slot = slot, itemStack = contents[slot], stateId = stateId)
67-
} else {
68-
nmsProxy<NMS>().sendWindowsItems(viewer!!, items = contents)
69-
}
65+
val player = viewer ?: return
66+
if (player.getViewingReceptacle() != this) return
67+
setupPlayerInventorySlots()
68+
runCatching {
69+
if (slot >= 0) {
70+
nmsProxy<NMS>().sendWindowsSetSlot(player, slot = slot, itemStack = contents[slot], stateId = stateId)
71+
} else {
72+
nmsProxy<NMS>().sendWindowsItems(player, items = contents)
7073
}
7174
}
7275
}
7376

7477
override fun open(player: Player) {
7578
viewer = player
76-
initializationPackets()
7779
player.setViewingReceptacle(this)
80+
initializationPackets()
7881
onOpen(player, this)
7982
}
8083

@@ -85,6 +88,7 @@ open class WindowReceptacle(var type: WindowLayout, override var title: String =
8588
}
8689
onClose(viewer!!, this)
8790
viewer!!.setViewingReceptacle(null)
91+
viewer = null
8892
}
8993
}
9094

@@ -98,9 +102,9 @@ open class WindowReceptacle(var type: WindowLayout, override var title: String =
98102
}
99103

100104
override fun property(id: Int, value: Int) {
101-
if (viewer != null) {
102-
nmsProxy<NMS>().sendWindowsUpdateData(viewer!!, id = id, value = value)
103-
}
105+
val player = viewer ?: return
106+
if (player.getViewingReceptacle() != this) return
107+
nmsProxy<NMS>().sendWindowsUpdateData(player, id = id, value = value)
104108
}
105109

106110
override fun callEventClick(event: ReceptacleInteractEvent<ItemStack>) {
@@ -112,7 +116,10 @@ open class WindowReceptacle(var type: WindowLayout, override var title: String =
112116
private fun initializationPackets() {
113117
if (viewer != null) {
114118
nmsProxy<NMS>().sendWindowsOpen(viewer!!, title = title, type = type)
115-
nmsProxy<NMS>().sendWindowsSetSlot(viewer!!, windowId = 0, slot = 45)
119+
if (MinecraftVersion.majorLegacy < 12111) {
120+
// 1.21.11+ can crash on offhand slot update during menu switch
121+
nmsProxy<NMS>().sendWindowsSetSlot(viewer!!, windowId = 0, slot = 45)
122+
}
116123
refresh()
117124
}
118125
}

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.19
2+
version=3.9.21

plugin/src/main/kotlin/trplugins/menu/api/action/impl/menu/SetTitle.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import trplugins.menu.api.action.ActionHandle
66
import trplugins.menu.api.action.base.ActionBase
77
import trplugins.menu.api.action.base.ActionContents
88
import trplugins.menu.module.display.session
9+
import trplugins.menu.util.colorify
10+
import trplugins.menu.util.parseJson
911

1012
/**
1113
* TrMenu
@@ -25,10 +27,15 @@ class SetTitle(handle: ActionHandle) : ActionBase(handle) {
2527
val session = player.session()
2628
val receptacle = session.receptacle ?: return
2729
var title = contents.stringContent().parseContent(placeholderPlayer)
30+
title = if (useComponent && runCatching { title.parseJson() }.isSuccess) {
31+
title
32+
} else {
33+
title.colorify()
34+
}
2835
if (useComponent) {
2936
title = title.component().build().toRawMessage()
3037
}
3138
receptacle.title(title)
3239
}
3340

34-
}
41+
}

plugin/src/main/kotlin/trplugins/menu/module/display/Menu.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import trplugins.menu.module.display.layout.MenuLayout
2121
import trplugins.menu.module.internal.data.Metadata
2222
import trplugins.menu.module.internal.script.evalAction
2323
import trplugins.menu.module.internal.script.evalScript
24+
import trplugins.menu.util.colorify
25+
import trplugins.menu.util.parseJson
2426
import java.util.function.Consumer
2527

2628
/**
@@ -168,9 +170,7 @@ class Menu(
168170
loadTitle(session)
169171
}
170172
} else {
171-
val parseTitle = if (SetTitle.useComponent) {
172-
title.component().build().toRawMessage()
173-
} else title
173+
val parseTitle = formatTitle(title)
174174
session.receptacle?.title(parseTitle, update = false)
175175
}
176176
if (BEDROCK_DELAY > 0 && PlatformProvider.isBedrockPlayer(viewer)) {
@@ -189,18 +189,12 @@ class Menu(
189189
private fun loadTitle(session: MenuSession) {
190190
val title = settings.title(session)
191191
session.receptacle?.title(title.next(session.id)?.let {
192-
val parseTitle = session.parse(it)
193-
if (SetTitle.useComponent) {
194-
parseTitle.component().build().toRawMessage()
195-
} else parseTitle
192+
formatTitle(session.parse(it))
196193
} ?: pluginId, update = false)
197194

198195
val setTitle = {
199196
session.receptacle?.title(title.next(session.id)?.let {
200-
val parseTitle = session.parse(it)
201-
if (SetTitle.useComponent) {
202-
parseTitle.component().build().toRawMessage()
203-
} else parseTitle
197+
formatTitle(session.parse(it))
204198
} ?: pluginId)
205199
}
206200

@@ -211,6 +205,15 @@ class Menu(
211205
}
212206
}
213207

208+
private fun formatTitle(title: String): String {
209+
val colored = if (SetTitle.useComponent && runCatching { title.parseJson() }.isSuccess) {
210+
title
211+
} else {
212+
title.colorify()
213+
}
214+
return if (SetTitle.useComponent) colored.component().build().toRawMessage() else colored
215+
}
216+
214217
private fun loadIcon(session: MenuSession) {
215218
session.shutTemps()
216219
icons

0 commit comments

Comments
 (0)