Skip to content

Commit 1ee5dfa

Browse files
committed
feat(receptacle): 适配至 26.1.1 Minecraft
- 在 api/receptacle 模块中添加了新的 v260100 依赖 - 新增 InputAnvil 类实现铁砧输入功能,支持自定义标题和物品显示 - 创建 NMSImpl 类实现跨版本 NMS 窗口操作,支持 1.16 到 1.21+ 版本 - 实现 WindowListener 监听器处理窗口点击、关闭和拖拽事件 - 重构 NMS 抽象类将 toNMSCopy 方法返回类型改为通用类型 - 添加静态库存储支持和跨版本数据包兼容处理 - 实现动态标题更新和窗口状态同步机制
1 parent 2469ebf commit 1ee5dfa

7 files changed

Lines changed: 89 additions & 11 deletions

File tree

api/receptacle/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ repositories {
55
dependencies {
66
compileOnly(project(":common"))
77
compileOnly("ink.ptms:nms-all:1.0.0")
8+
compileOnly("ink.ptms.core:v260100:260100")
89
compileOnly("dependencies.core:paper:12104-min")
910
compileOnly("ink.ptms.core:v12002:12002-minimize:universal")
1011
compileOnly("ink.ptms.core:v12002:12002-minimize:mapped")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,5 @@ abstract class NMS {
8080
*/
8181
abstract fun sendWindowsUpdateData(player: Player, windowId: Int = windowId(player), id: Int, value: Int)
8282

83-
abstract fun toNMSCopy(itemStack: ItemStack?): net.minecraft.server.v1_16_R3.ItemStack?
83+
abstract fun toNMSCopy(itemStack: ItemStack?): Any?
8484
}

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

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import org.bukkit.event.inventory.InventoryType
1010
import org.bukkit.inventory.InventoryView
1111
import org.bukkit.inventory.ItemStack
1212
import taboolib.library.reflex.Reflex.Companion.getProperty
13+
import taboolib.library.reflex.Reflex.Companion.invokeMethod
1314
import taboolib.library.reflex.Reflex.Companion.setProperty
1415
import taboolib.library.reflex.Reflex.Companion.unsafeInstance
1516
import taboolib.module.nms.MinecraftVersion
17+
import taboolib.module.nms.nmsClass
1618
import taboolib.module.nms.sendPacket
1719
import taboolib.platform.util.isAir
1820
import trplugins.menu.api.receptacle.vanilla.window.StaticInventory.inventoryView
@@ -24,10 +26,16 @@ import trplugins.menu.api.receptacle.vanilla.window.StaticInventory.staticInvent
2426
*/
2527
class NMSImpl : NMS() {
2628

27-
private val emptyItemStack: net.minecraft.server.v1_16_R3.ItemStack? = CraftItemStack.asNMSCopy((ItemStack(Material.AIR)))
2829
private val version = MinecraftVersion.majorLegacy
30+
private val isUnobfuscated = MinecraftVersion.isUnobfuscated
2931
private val windowIds = HashMap<String, Int>()
3032

33+
private val emptyItemStack: Any? = if (isUnobfuscated) {
34+
craftItemStackCopy(ItemStack(Material.AIR))
35+
} else {
36+
CraftItemStack.asNMSCopy(ItemStack(Material.AIR))
37+
}
38+
3139
private val Player.windowId get() = windowIds[this.name] ?: 119
3240

3341
override fun windowId(player: Player, create: Boolean): Int {
@@ -44,7 +52,13 @@ class NMSImpl : NMS() {
4452
StaticInventory.close(player)
4553
} else {
4654
windowIds.remove(player.name)
47-
player.sendPacket(PacketPlayOutCloseWindow(windowId))
55+
if (isUnobfuscated) {
56+
val packet = nmsClass("network.protocol.game.ClientboundContainerClosePacket")
57+
.getDeclaredConstructor(Int::class.java).newInstance(windowId)
58+
player.sendPacket(packet)
59+
} else {
60+
player.sendPacket(PacketPlayOutCloseWindow(windowId))
61+
}
4862
}
4963
}
5064

@@ -59,6 +73,16 @@ class NMSImpl : NMS() {
5973
inventory.setItem(index, item)
6074
}
6175
}
76+
isUnobfuscated -> {
77+
sendPacket(
78+
player,
79+
nmsClass("network.protocol.game.ClientboundContainerSetContentPacket").unsafeInstance(),
80+
"containerId" to windowId,
81+
"stateId" to 1,
82+
"items" to items.map { i -> toNMSCopy(i) }.toList(),
83+
"carriedItem" to emptyItemStack
84+
)
85+
}
6286
version >= 11701 -> {
6387
sendPacket(
6488
player,
@@ -101,6 +125,17 @@ class NMSImpl : NMS() {
101125
player.useStaticInventory() -> {
102126
StaticInventory.open(player, type, title)
103127
}
128+
isUnobfuscated -> {
129+
val menuType = nmsClass("world.inventory.MenuType").getProperty<Any>(type.vanillaId, isStatic = true)
130+
val chatComponent = craftChatMessageComponent(title)
131+
sendPacket(
132+
player,
133+
nmsClass("network.protocol.game.ClientboundOpenScreenPacket").unsafeInstance(),
134+
"containerId" to windowId,
135+
"type" to menuType,
136+
"title" to chatComponent
137+
)
138+
}
104139
version >= 11900 -> {
105140
sendPacket(
106141
player,
@@ -153,6 +188,16 @@ class NMSImpl : NMS() {
153188
}
154189
}
155190
}
191+
isUnobfuscated -> {
192+
sendPacket(
193+
player,
194+
nmsClass("network.protocol.game.ClientboundContainerSetSlotPacket").unsafeInstance(),
195+
"containerId" to windowId,
196+
"stateId" to -1,
197+
"slot" to slot,
198+
"itemStack" to toNMSCopy(itemStack)
199+
)
200+
}
156201
version >= 11701 -> {
157202
sendPacket(
158203
player,
@@ -164,7 +209,7 @@ class NMSImpl : NMS() {
164209
)
165210
}
166211
else -> {
167-
player.sendPacket(PacketPlayOutSetSlot(windowId, slot, toNMSCopy(itemStack)))
212+
player.sendPacket(PacketPlayOutSetSlot(windowId, slot, toNMSCopy(itemStack) as? net.minecraft.server.v1_16_R3.ItemStack))
168213
}
169214
}
170215
if (version >= 12104) {
@@ -186,6 +231,15 @@ class NMSImpl : NMS() {
186231
val property = getInventoryProperty(inventory.type, id) ?: return
187232
view.setProperty(property, value)
188233
}
234+
isUnobfuscated -> {
235+
sendPacket(
236+
player,
237+
nmsClass("network.protocol.game.ClientboundContainerSetDataPacket").unsafeInstance(),
238+
"containerId" to windowId,
239+
"id" to id,
240+
"value" to value
241+
)
242+
}
189243
MinecraftVersion.isUniversal -> {
190244
sendPacket(
191245
player,
@@ -201,8 +255,13 @@ class NMSImpl : NMS() {
201255
}
202256
}
203257

204-
override fun toNMSCopy(itemStack: ItemStack?): net.minecraft.server.v1_16_R3.ItemStack? {
205-
return if (itemStack.isAir()) emptyItemStack else CraftItemStack.asNMSCopy(itemStack)
258+
override fun toNMSCopy(itemStack: ItemStack?): Any? {
259+
if (itemStack.isAir()) return emptyItemStack
260+
return if (isUnobfuscated) {
261+
craftItemStackCopy(itemStack)
262+
} else {
263+
CraftItemStack.asNMSCopy(itemStack)
264+
}
206265
}
207266

208267
private fun sendPacket(player: Player, packet: Any, vararg fields: Pair<String, Any?>) {
@@ -214,4 +273,16 @@ class NMSImpl : NMS() {
214273
return InventoryView.Property.entries.find { (it.type == type || (it.type == InventoryType.FURNACE && type == InventoryType.BLAST_FURNACE)) && it.id == id }
215274
}
216275

276+
private fun craftItemStackCopy(itemStack: ItemStack): net.minecraft.world.item.ItemStack? {
277+
return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemStack)
278+
}
279+
280+
private fun craftChatMessageComponent(text: String): Any {
281+
val clazz = Class.forName("org.bukkit.craftbukkit.util.CraftChatMessage")
282+
return if (text.startsWith('{') && text.endsWith('}')) {
283+
clazz.invokeMethod<Any>("fromJSON", text, isStatic = true)!!
284+
} else {
285+
(clazz.invokeMethod<Array<Any>>("fromString", text, isStatic = true))!![0]
286+
}
287+
}
217288
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ object WindowListener {
4040
if (MinecraftVersion.isUniversal) {
4141
slot = e.packet.read<Int>("slotNum")!!
4242
button = e.packet.read<Int>("buttonNum")!!
43-
clickType = ReceptacleClickType.from(e.packet.read<Any>("clickType").toString(), button, slot) ?: return
43+
val clickTypeField = if (MinecraftVersion.isUnobfuscated) "containerInput" else "clickType"
44+
clickType = ReceptacleClickType.from(e.packet.read<Any>(clickTypeField).toString(), button, slot) ?: return
4445
} else if (MinecraftVersion.majorLegacy >= 10900) {
4546
slot = e.packet.read<Int>("slot")!!
4647
button = e.packet.read<Int>("button")!!

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ subprojects {
7272
disableOnSkippedVersion = false
7373
}
7474
version {
75-
taboolib = "6.2.4-99fb800"
75+
taboolib = "6.3.0-0e96352"
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.10.5
2+
version=3.11.0

plugin/src/main/kotlin/trplugins/menu/module/internal/inputer/inputs/InputAnvil.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.bukkit.inventory.ItemStack
55
import taboolib.common.platform.event.SubscribeEvent
66
import taboolib.library.reflex.Reflex.Companion.getProperty
77
import taboolib.library.xseries.XMaterial
8+
import taboolib.module.nms.MinecraftVersion
89
import taboolib.module.nms.PacketReceiveEvent
910
import taboolib.module.nms.getI18nName
1011
import taboolib.platform.util.buildItem
@@ -83,11 +84,15 @@ class InputAnvil(
8384

8485
@SubscribeEvent
8586
fun e(e: PacketReceiveEvent) {
86-
if (e.packet.name != "PacketPlayInItemName") {
87+
if (e.packet.name != "PacketPlayInItemName" && e.packet.name != "ServerboundRenameItemPacket") {
8788
return
8889
}
8990
val input = inputs[e.player] ?: return
90-
val inputText = e.packet.source.getProperty<String>("a")!!
91+
val inputText = if (MinecraftVersion.isUnobfuscated) {
92+
e.packet.read<String>("name")!!
93+
} else {
94+
e.packet.source.getProperty<String>("a")!!
95+
}
9196

9297
input.receptacle.getElement(2)?.let { it ->
9398
it.itemMeta?.let {

0 commit comments

Comments
 (0)