From 544fe50ede73c1e182e1fca6386ca57209c6f47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MC=7E=E8=9B=9F=E9=BE=99?= <1610105206@qq.com> Date: Fri, 28 Jun 2024 22:50:46 +0800 Subject: [PATCH] Experimental | Optimize & Update NMS --- .../function/argument/ArgumentFactory.kt | 48 ------------- .../ratziel/function/argument/ArgumentUtil.kt | 8 --- .../argument/DefaultArgumentFactory.kt | 43 ------------ .../cn/fd/ratziel/module/item/ItemElement.kt | 4 +- .../ratziel/module/item/command/NBTCommand.kt | 14 ++-- .../resolver/sectionResolvers/PapiResolver.kt | 1 - .../module/item/impl/component/ItemSundry.kt | 23 +++---- .../cn/fd/ratziel/module/item/nms/NMS12005.kt | 59 +++++++++++++--- .../cn/fd/ratziel/module/item/nms/NMSItem.kt | 69 ++++++++++++++++--- .../fd/ratziel/module/item/nms/RefItemMeta.kt | 2 +- .../ratziel/module/item/nms/RefItemStack.kt | 6 +- 11 files changed, 134 insertions(+), 143 deletions(-) delete mode 100644 project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentFactory.kt delete mode 100644 project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/DefaultArgumentFactory.kt diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentFactory.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentFactory.kt deleted file mode 100644 index 43601163..00000000 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentFactory.kt +++ /dev/null @@ -1,48 +0,0 @@ -package cn.fd.ratziel.function.argument - -import cn.fd.ratziel.function.argument.exception.* - -/** - * ArgumentFactory - 可变参数工厂 - * - * @author TheFloodDragon - * @since 2024/5/1 13:19 - */ -@Deprecated("Use ContextArgument", ReplaceWith("ContextArgument")) -interface ArgumentFactory { - - /** - * 弹出第一个指定类型的参数 - * @throws ArgumentNotFoundException 当无法找到指定类型的参数时抛出 - */ - @Throws(ArgumentNotFoundException::class) - fun pop(type: Class): Argument - - /** - * 弹出第一个指定类型的参数 - * 若无法找到, 则返回空 - */ - fun popOrNull(type: Class): Argument? - - /** - * 弹出第一个指定类型的参数 - * 若无法找到, 则返回默认值 - */ - fun popOr(type: Class, default: T): Argument - - /** - * 弹出所有指定类型的参数 - */ - fun popAll(type: Class): Iterable> - - /** - * 添加一个参数元素 - */ - fun add(element: Argument<*>): Boolean - - /** - * 删除一个参数元素 - */ - fun remove(element: Argument<*>): Boolean - -} \ No newline at end of file diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentUtil.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentUtil.kt index 0200b612..3b923473 100644 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentUtil.kt +++ b/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/ArgumentUtil.kt @@ -34,14 +34,6 @@ fun Argument.ascertain( inline fun ArgumentSupplier.supplyOrNull(): Argument? = supplyOrNull(T::class.java) -inline fun ArgumentFactory.pop() = pop(T::class.java) - -inline fun ArgumentFactory.popAll() = popAll(T::class.java) - -inline fun ArgumentFactory.popOr(default: T): Argument = popOr(T::class.java, default) - -inline fun ArgumentFactory.popOrNull(): Argument? = popOrNull(T::class.java) - inline fun Argument<*>.instanceof(): Boolean = this.instanceof(T::class.java) inline fun Argument.ascertain( diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/DefaultArgumentFactory.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/DefaultArgumentFactory.kt deleted file mode 100644 index 63d05423..00000000 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/function/argument/DefaultArgumentFactory.kt +++ /dev/null @@ -1,43 +0,0 @@ -package cn.fd.ratziel.function.argument - -import cn.fd.ratziel.function.argument.exception.ArgumentNotFoundException -import cn.fd.ratziel.function.util.uncheck -import java.util.concurrent.CopyOnWriteArrayList - -/** - * DefaultArgumentFactory - * - * @author TheFloodDragon - * @since 2024/5/1 13:55 - */ -@Deprecated("Use DefaultContextArgument", ReplaceWith("DefaultContextArgument")) -open class DefaultArgumentFactory( - protected open val list: CopyOnWriteArrayList> -) : ArgumentFactory, MutableList> by list { - - constructor(collection: Collection>) : this(CopyOnWriteArrayList(collection)) - - constructor(vararg arguments: Argument<*>) : this(CopyOnWriteArrayList(arguments)) - - constructor() : this(CopyOnWriteArrayList()) - - override fun popOrNull(type: Class): Argument? = - list.find { type.isAssignableFrom(it.type) }?.let { handledCast(it, type) } - - override fun pop(type: Class) = popOrNull(type) ?: throw ArgumentNotFoundException(type) - - override fun popOr(type: Class, default: T) = popOrNull(type) ?: SingleArgument(default) - - override fun popAll(type: Class): List> = - list.mapNotNull { arg -> - arg.takeIf { - it.type.isAssignableFrom(type) - }?.let { handledCast(it, type) } - } - - /** - * 处理 [SuppliableArgument] - */ - private fun handledCast(arg: Argument<*>, type: Class) = if (arg is SuppliableArgument<*>) arg[type] else uncheck(arg) - -} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemElement.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemElement.kt index ced2ca2c..cc215e98 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemElement.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemElement.kt @@ -48,8 +48,8 @@ object ItemElement : ElementHandler { println(item.data) - val ri = RefItemStack(item.data) - println(ri) + val ri = RefItemStack(item.data) + println(ri.getTag()) val bi = ri.getAsBukkit() println(bi) diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/command/NBTCommand.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/command/NBTCommand.kt index 32ced4ff..878d6f95 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/command/NBTCommand.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/command/NBTCommand.kt @@ -1,6 +1,9 @@ package cn.fd.ratziel.module.item.command import cn.fd.ratziel.module.item.nbt.* +import cn.fd.ratziel.module.item.nms.NMSItem +import cn.fd.ratziel.module.item.nms.RefItemStack +import cn.fd.ratziel.module.item.util.getItemBySlot import cn.fd.ratziel.module.item.util.handleItemTag import org.bukkit.entity.Player import taboolib.common.platform.ProxyCommandSender @@ -39,13 +42,14 @@ object NBTCommand { val view = subCommand { slot { execute { player, _, arg -> - player.cast().inventory.handleItemTag(arg) { tag -> - if (tag.isEmpty()) player.sendLang("NBTAction-EmptyTag") - else { + player.cast().inventory.getItemBySlot(arg) + ?.let { RefItemStack(it).getAsNms() } + ?.let { NMSItem.INSTANCE.getItemTagWithDefault(it) } + ?.takeIf { it.isNotEmpty() } + ?.also { tag -> // 构建消息组件并发送 nbtAsComponent(player, tag, 0, arg).sendTo(player) - } - } ?: player.sendLang("NBTAction-EmptyTag") + } ?: player.sendLang("NBTAction-EmptyTag") } } } diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/PapiResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/PapiResolver.kt index 7a497b69..abd8d774 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/PapiResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/PapiResolver.kt @@ -17,7 +17,6 @@ object PapiResolver : SectionStringResolver { override fun resolve(element: String, arguments: ContextArgument): String { // 获取玩家 val player = arguments.popOrNull() ?: return element // 没玩家处理啥? - println(player) // 处理Papi变量 return element.replacePlaceholder(player) } diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemSundry.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemSundry.kt index 41defff0..b44a0c3a 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemSundry.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemSundry.kt @@ -41,22 +41,24 @@ data class ItemSundry( /** * 添加物品隐藏标签 */ - fun addHideFlags(vararg flags: HideFlag) = fetchHideFlags().addAll(flags) + fun addHideFlags(vararg flags: HideFlag) = (hideFlags ?: HashSet().also { hideFlags = it }).addAll(flags) /** * 删除物品隐藏标签 */ - fun removeHideFlags(vararg flags: HideFlag) = fetchHideFlags().removeAll(flags.toSet()) + fun removeHideFlags(vararg flags: HideFlag) = hideFlags?.removeAll(flags.toSet()) /** * 获取属性修饰符 */ - fun getAttributeModifier(attribute: Attribute) = fetchBukkitAttributes().computeIfAbsent(attribute) { mutableListOf() } + fun getAttributeModifier(attribute: Attribute) = bukkitAttributes?.get(attribute) /** * 添加属性修饰符 */ - fun addAttributeModifiers(attribute: Attribute, vararg modifiers: AttributeModifier) = getAttributeModifier(attribute).addAll(modifiers) + fun addAttributeModifiers(attribute: Attribute, vararg modifiers: AttributeModifier) = + (bukkitAttributes ?: HashMap>().also { bukkitAttributes = it }) + .computeIfAbsent(attribute) { mutableListOf() }.addAll(modifiers) /** * 删除属性修饰符 @@ -66,14 +68,6 @@ data class ItemSundry( fun removeAttributeModifiers(slot: EquipmentSlot) = bukkitAttributes?.forEach { (key, value) -> value.forEach { if (it.slot == slot) bukkitAttributes?.get(key)?.remove(it) } } - /** - * 空->默认值处理 - */ - - private fun fetchHideFlags() = hideFlags ?: HashSet().also { hideFlags = it } - - private fun fetchBukkitAttributes() = bukkitAttributes ?: HashMap>().also { bukkitAttributes = it } - companion object : ItemTransformer { override val node = ItemNode.ROOT @@ -81,9 +75,10 @@ data class ItemSundry( override fun transform(component: ItemSundry): ItemData = ItemDataImpl().apply { val itemMeta = RefItemMeta() // HideFlags - itemMeta.handle.addItemFlags(*component.fetchHideFlags().toTypedArray()) + val flags = component.hideFlags?.toTypedArray() + if (flags != null) itemMeta.handle.addItemFlags(*flags) // BukkitAttributes - component.fetchBukkitAttributes().forEach { (key, value) -> + component.bukkitAttributes?.forEach { (key, value) -> value.forEach { itemMeta.handle.addAttributeModifier(key, it) } } // Merge diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMS12005.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMS12005.kt index a9d0c5d2..9a678d45 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMS12005.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMS12005.kt @@ -1,14 +1,20 @@ package cn.fd.ratziel.module.item.nms +import cn.fd.ratziel.function.util.uncheck import cn.fd.ratziel.module.item.nbt.NMSUtil +import com.mojang.serialization.Codec +import com.mojang.serialization.DynamicOps +import net.minecraft.core.component.DataComponentMap import net.minecraft.core.component.DataComponentPatch import net.minecraft.nbt.DynamicOpsNBT import net.minecraft.nbt.NBTTagCompound +import net.minecraft.resources.RegistryOps +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_20_R4.CraftServer import taboolib.library.reflex.ReflexClass import taboolib.module.nms.MinecraftVersion import taboolib.module.nms.nmsClass import taboolib.module.nms.nmsProxy -import kotlin.jvm.optionals.getOrNull /** * NMS12005 @@ -23,12 +29,22 @@ abstract class NMS12005 { /** * [NBTTagCompound] to [DataComponentPatch] */ - abstract fun parse(nbt: Any): Any? + abstract fun parsePatch(nbt: Any): Any? /** * [DataComponentPatch] to [NBTTagCompound] */ - abstract fun save(dcp: Any): Any? + abstract fun savePatch(dcp: Any): Any? + + /** + * [NBTTagCompound] to [DataComponentMap] + */ + abstract fun parseMap(nbt: Any): Any? + + /** + * [DataComponentMap] to [NBTTagCompound] + */ + abstract fun saveMap(dcm: Any): Any? companion object { @@ -60,12 +76,37 @@ abstract class NMS12005 { @Suppress("unused") class NMS12005Impl : NMS12005() { - override fun parse(nbt: Any): Any? = - DataComponentPatch.CODEC.parse(DynamicOpsNBT.INSTANCE, nbt as NBTTagCompound) - .resultOrPartial { error("Failed to parse: $it") }.getOrNull() + fun parse(codec: Codec, nbt: NBTTagCompound): T? { + val result = codec.parse(createSerializationContext(DynamicOpsNBT.INSTANCE), nbt) + val opt = result.resultOrPartial { error("Failed to parse: $it") } + return if (opt.isPresent) opt.get() else null + } + + fun save(codec: Codec, obj: T): NBTTagCompound? { + val result = codec.encodeStart(createSerializationContext(DynamicOpsNBT.INSTANCE), obj) + val opt = result.resultOrPartial { error("Failed to save: $it") } + return if (opt.isPresent) opt.get() as? NBTTagCompound else null + } + + override fun parsePatch(nbt: Any): Any? = parse(DataComponentPatch.CODEC, nbt as NBTTagCompound) + + override fun savePatch(dcp: Any): Any? = save(DataComponentPatch.CODEC, dcp as DataComponentPatch) + + override fun parseMap(nbt: Any): Any? = parse(DataComponentMap.CODEC, nbt as NBTTagCompound) + + override fun saveMap(dcm: Any): Any? = save(DataComponentMap.CODEC, dcm as DataComponentMap) + + val access by lazy { (Bukkit.getServer() as CraftServer).server.registryAccess() } + + val method by lazy { + val ref = ReflexClass.of(access::class.java, false) + try { + ref.getMethod("a") + } catch (_: NoSuchFieldException) { + ref.getMethod("createSerializationContext") + } + } - override fun save(dcp: Any): Any? = - DataComponentPatch.CODEC.encodeStart(DynamicOpsNBT.INSTANCE, dcp as DataComponentPatch) - .resultOrPartial { error("Failed to save: $it") }.getOrNull() + fun createSerializationContext(dynamicOps: DynamicOps): RegistryOps = uncheck(method.invoke(access, dynamicOps)!!) } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMSItem.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMSItem.kt index 8ec9a7de..b8af3135 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMSItem.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/NMSItem.kt @@ -1,12 +1,14 @@ package cn.fd.ratziel.module.item.nms import cn.fd.ratziel.module.item.nbt.NBTCompound +import net.minecraft.core.component.DataComponentMap import net.minecraft.core.component.DataComponentPatch import net.minecraft.core.component.PatchedDataComponentMap import net.minecraft.nbt.NBTTagCompound import taboolib.library.reflex.ReflexClass import taboolib.module.nms.MinecraftVersion import taboolib.module.nms.nmsProxy +import java.util.concurrent.ConcurrentHashMap import net.minecraft.world.item.ItemStack as NMSItemStack /** @@ -21,13 +23,27 @@ abstract class NMSItem { * 获取 [NMSItemStack]的 NBT (克隆) * @return [NBTCompound] */ - abstract fun getItemNBT(nmsItem: Any): NBTCompound? + abstract fun getItemTag(nmsItem: Any): NBTCompound? /** * 设置 [NMSItemStack]的 NBT (克隆) * @param nbt [NBTTagCompound] */ - abstract fun setItemNBT(nmsItem: Any, nbt: NBTCompound) + abstract fun setItemTag(nmsItem: Any, nbt: NBTCompound) + + /** + * 1.20.5+ + * [getItemTag] 是忽略掉默认值的 + * 而 [getItemTagWithDefault] 会带上默认值 + */ + open fun getItemTagWithDefault(nmsItem: Any): NBTCompound? = getItemTag(nmsItem) + + /** + * 1.20.5+ + * [setItemTag] 是忽略掉默认值的 + * 而 [setItemTagWithDefault] 会带上默认值 + */ + open fun setItemTagWithDefault(nmsItem: Any, nbt: NBTCompound) = setItemTag(nmsItem, nbt) /** * 克隆 [NMSItemStack] @@ -49,10 +65,10 @@ abstract class NMSItem { */ object NMSItemImpl1 : NMSItem() { - override fun getItemNBT(nmsItem: Any): NBTCompound? = + override fun getItemTag(nmsItem: Any): NBTCompound? = RefItemStack.InternalUtil.nmsTagField.get(nmsItem)?.let { NBTCompound(it).clone() } - override fun setItemNBT(nmsItem: Any, nbt: NBTCompound) = + override fun setItemTag(nmsItem: Any, nbt: NBTCompound) = RefItemStack.InternalUtil.nmsTagField.set(nmsItem, nbt.clone().getData()) override fun copyItem(nmsItem: Any): Any = @@ -70,19 +86,54 @@ class NMSItemImpl2 : NMSItem() { ReflexClass.of(RefItemStack.nmsClass).getField("components", remap = true) } - override fun getItemNBT(nmsItem: Any): NBTCompound? { + override fun getItemTag(nmsItem: Any): NBTCompound? { val dcp = (nmsItem as NMSItemStack).componentsPatch - return NMS12005.INSTANCE.save(dcp)?.let { NBTCompound(it) } + return NMS12005.INSTANCE.savePatch(dcp)?.let { NBTCompound(it) } } - override fun setItemNBT(nmsItem: Any, nbt: NBTCompound) { - val dcp = NMS12005.INSTANCE.parse(nbt.getData() as NBTTagCompound) as? DataComponentPatch + override fun setItemTag(nmsItem: Any, nbt: NBTCompound) { + val dcp = NMS12005.INSTANCE.parsePatch(nbt.getData() as NBTTagCompound) as? DataComponentPatch val components = componentsField.get(nmsItem) as? PatchedDataComponentMap - components?.restorePatch(dcp) + if (components != null) { + components.restorePatch(dcp) + } else { + val newComponents = PatchedDataComponentMap(DataComponentMap.EMPTY) + newComponents.restorePatch(dcp) + componentsField.set(nmsItem, newComponents) + } } override fun copyItem(nmsItem: Any): Any { return (nmsItem as NMSItemStack).copy() } + override fun getItemTagWithDefault(nmsItem: Any): NBTCompound? { + val tag = getItemTag(nmsItem) + val default = getItemBasicNBT(nmsItem) ?: return tag + return tag?.merge(NBTCompound(default), false) + } + + override fun setItemTagWithDefault(nmsItem: Any, nbt: NBTCompound) { + var tag = nbt + val default = getItemBasicNBT(nmsItem) + if (default != null) tag = NBTCompound(default).merge(nbt, true) + setItemTag(nmsItem, tag) + } + + val cache: MutableMap = ConcurrentHashMap() + + fun getItemBasicNBT(nmsItem: Any): NBTTagCompound? { + val item = (nmsItem as NMSItemStack).item // 获取物品类 + val id = net.minecraft.world.item.Item.getId(item) // 获取物品ID + val result = cache[id] // 尝试通过缓存 + if (result != null) return result + // 生成并加入到缓存 + val nbt = NMS12005.INSTANCE.saveMap(item.components()) as? NBTTagCompound + if (nbt != null) { + cache[id] = nbt + return nbt + } + return null + } + } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemMeta.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemMeta.kt index 38ed62c8..40d54862 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemMeta.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemMeta.kt @@ -43,7 +43,7 @@ class RefItemMeta(raw: Any) { val applicator = InternalUtil.applicatorConstructor.instance()!! // new Applicator InternalUtil.applyToItemMethod.invoke(handle, applicator) // Apply to the applicator val dcp = InternalUtil.applicatorToDcp(applicator) // Applicator to DataComponentPatch - val newTag = NMS12005.INSTANCE.save(dcp) // DataComponentPatch save to NBT + val newTag = NMS12005.INSTANCE.savePatch(dcp) // DataComponentPatch save to NBT if (newTag != null) tag.putAll(NBTCompound(newTag)) } else { InternalUtil.applyToItemMethod.invoke(handle, tag.getData()) diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemStack.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemStack.kt index 7e721355..a1cd2cef 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemStack.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/RefItemStack.kt @@ -45,14 +45,14 @@ class RefItemStack(raw: Any) { * 获取物品NBT [NBTCompound] */ fun getTag(): NBTCompound? { - return NMSItem.INSTANCE.getItemNBT(getAsNms() ?: return null) + return NMSItem.INSTANCE.getItemTag(getAsNms() ?: return null) } /** * 设置物品NBT标签 [NBTCompound] */ fun setTag(data: NBTCompound) { - NMSItem.INSTANCE.setItemNBT(getAsNms() ?: return, data) + NMSItem.INSTANCE.setItemTag(getAsNms() ?: return, data) } /** @@ -71,8 +71,8 @@ class RefItemStack(raw: Any) { */ fun setData(data: ItemData) { setMaterial(data.material) - setTag(data.tag) setAmount(data.amount) + setTag(data.tag) } /**