From 0f71ae34e7f1505e5bdd8d3e7b68b28808bfe417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?MC=7E=E8=9B=9F=E9=BE=99?= <1610105206@qq.com> Date: Wed, 14 Aug 2024 11:19:26 +0800 Subject: [PATCH] =?UTF-8?q?Experimental=20|=20=E9=87=8D=E6=9E=84NMS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fd/ratziel/module/item/nbt/NBTAdapter.kt | 2 + .../fd/ratziel/module/item/nbt/NBTCompound.kt | 5 + .../ratziel/module/item/nbt/NBTSerializer.kt | 4 +- .../cn/fd/ratziel/module/item/nbt/NBTType.kt | 2 + .../cn/fd/ratziel/module/item/nbt/NMSUtil.kt | 1 + .../cn/fd/ratziel/module/item/nms/NMS12005.kt | 86 +++---- .../cn/fd/ratziel/module/item/nms/NMSItem.kt | 239 +++++++++++++++--- .../fd/ratziel/module/item/nms/RefItemMeta.kt | 4 +- .../ratziel/module/item/nms/RefItemStack.kt | 23 -- 9 files changed, 252 insertions(+), 114 deletions(-) diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTAdapter.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTAdapter.kt index 1c882725..2de3cf1d 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTAdapter.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTAdapter.kt @@ -17,6 +17,7 @@ object NBTAdapter { else -> BasicAdapter.adapt(target) } ?: throw UnsupportedTypeException(target) + @Deprecated("Use NMSItem.INSTANCE") @JvmStatic fun adaptNms(target: Any) = NmsAdapter.adapt(target)!! @@ -38,6 +39,7 @@ object NBTAdapter { object NmsAdapter { + @Deprecated("Use NMSItem.INSTANCE") @JvmStatic fun adapt(target: Any) = target::class.java.let { c -> when { diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTCompound.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTCompound.kt index 7c13e134..cd62e33c 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTCompound.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTCompound.kt @@ -51,6 +51,11 @@ open class NBTCompound private constructor(rawData: Any) : NBTData(rawData, NBTT */ open fun clone() = this.apply { data = NMSUtil.NtCompound.methodClone.invoke(data)!! } + /** + * 浅克隆数据 + */ + open fun cloneShallow() = NBTCompound(HashMap(sourceMap)) + /** * 合并目标数据 * @param replace 是否替换原有的数据 (false时不会 替换/删除 任何一个节点) diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTSerializer.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTSerializer.kt index 290f018e..eb470191 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTSerializer.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTSerializer.kt @@ -102,9 +102,7 @@ object NBTSerializer : KSerializer { val dataStr = target.substringBeforeLast(EXACT_TYPE_CHAR) // 匹配类型 - val type = NBTType.entries.find { - it.alias.contains(typeStr) || it.simpleName == typeStr - } ?: return adaptString(target) + val type = NBTType.entries.find { it.names.contains(typeStr) } ?: return adaptString(target) return convertBasicString(dataStr, type) ?: convertArrayString(dataStr, type) diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTType.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTType.kt index ed2229f9..31c59700 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTType.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NBTType.kt @@ -26,4 +26,6 @@ enum class NBTType(val id: Int, val alias: Array = emptyArray()) { val simpleName get() = name.lowercase() + val names by lazy { alias.plus(simpleName) } + } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NMSUtil.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NMSUtil.kt index fed04dc6..4dc9bb60 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NMSUtil.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nbt/NMSUtil.kt @@ -14,6 +14,7 @@ import taboolib.module.nms.nmsClass * @author TheFloodDragon * @since 2024/3/15 18:56 */ +@Deprecated("Use NMSItem.INSTANCE") internal sealed class NMSUtil(val type: NBTType) { abstract val nmsClass: Class<*> 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 42f30f3d..f10991cf 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 @@ -9,8 +9,6 @@ import com.mojang.serialization.DynamicOps import net.minecraft.core.IRegistryCustom 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 @@ -21,7 +19,7 @@ import taboolib.module.nms.nmsProxy import java.nio.ByteBuffer import java.util.* import java.util.stream.Stream -import kotlin.streams.toList +import kotlin.streams.asSequence /** @@ -74,7 +72,10 @@ abstract class NMS12005 { } -@Suppress("unused") +/** + * 代码参考自: Taboolib/nms-tag-12005 + */ +@Suppress("unused", "MemberVisibilityCanBePrivate") class NMS12005Impl : NMS12005() { fun parse(codec: Codec, tag: NBTCompound): T? { @@ -89,27 +90,15 @@ class NMS12005Impl : NMS12005() { return if (opt.isPresent) opt.get() as? NBTCompound else null } - fun parse0(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 save0(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(tag: NBTCompound): Any? = parse(DataComponentPatch.CODEC, tag) - override fun parsePatch(tag: NBTCompound): Any? = parse0(DataComponentPatch.CODEC, tag.getRaw() as NBTTagCompound) - .also { println("Test-parse: " + parse(DataComponentPatch.CODEC, tag)) } + override fun savePatch(dcp: Any): NBTCompound? = save(DataComponentPatch.CODEC, dcp as DataComponentPatch) - override fun savePatch(dcp: Any): NBTCompound? = save0(DataComponentPatch.CODEC, dcp as DataComponentPatch)?.let { NBTCompound.of(it) } - .also { println("Test-save: " + save(DataComponentPatch.CODEC, dcp)) } + override fun parseMap(tag: NBTCompound): Any? = parse(DataComponentMap.CODEC, tag) - override fun parseMap(tag: NBTCompound): Any? = parse0(DataComponentMap.CODEC, tag.getRaw() as NBTTagCompound) + override fun saveMap(dcm: Any): NBTCompound? = save(DataComponentMap.CODEC, dcm as DataComponentMap) - override fun saveMap(dcm: Any): NBTCompound? = save0(DataComponentMap.CODEC, dcm as DataComponentMap)?.let { NBTCompound.of(it) } + fun createSerializationContext(dynamicOps: DynamicOps): RegistryOps = uncheck(method.invoke(access, dynamicOps)!!) private val access: IRegistryCustom.Dimension by lazy { (Bukkit.getServer() as CraftServer).server.registryAccess() } @@ -119,50 +108,36 @@ class NMS12005Impl : NMS12005() { ?: ref.structure.getMethodByType("createSerializationContext", DynamicOps::class.java) } - fun createSerializationContext(dynamicOps: DynamicOps): RegistryOps = uncheck(method.invoke(access, dynamicOps)!!) - private object InternalOps : DynamicOps { - override fun empty() = NBTCompound() + override fun empty() = NBTEnd - override fun createNumeric(p0: Number) = NBTAdapter.adapt(p0) + override fun createNumeric(number: Number) = NBTAdapter.adapt(number) // TODO - override fun createString(p0: String) = NBTString(p0) + override fun createString(str: String) = NBTString(str) - override fun remove(raw: NBTData, str: String) = - if (raw is NBTCompound) { - val copied = raw.clone() // TODO shallow - copied.remove(str) - copied - } else raw + override fun remove(tag: NBTData, str: String) = if (tag is NBTCompound) tag.cloneShallow().apply { remove(str) } else tag - override fun createList(stream: Stream) = NBTList(stream.toList()) + override fun createList(stream: Stream) = NBTList().apply { addAll(stream.asSequence()) } - override fun getStream(data: NBTData): DataResult> = - if (data is NBTList) { - DataResult.success(data.stream()) - } else { - DataResult.error { "Not a list" } - } + override fun getStream(tag: NBTData): DataResult> = + if (tag is NBTList) DataResult.success(tag.stream()) else DataResult.error { "Not a list: $tag" } - override fun createMap(stream: Stream>) = NBTCompound().also { tag -> - stream.forEach { tag.put((it.first as NBTData).toString(), it.second) } - } + override fun createMap(stream: Stream>) = + NBTCompound().apply { stream.forEach { put((it.first as NBTString).content, it.second) } } - override fun getMapValues(data: NBTData): DataResult>> = - if (data is NBTCompound) { - DataResult.success(data.entries.stream().map { Pair.of(this.createString(it.key), it.value) }) - } else { - DataResult.error { "Not a map: $data" } - } + override fun getMapValues(tag: NBTData): DataResult>> = + if (tag is NBTCompound) + DataResult.success(tag.entries.stream().map { Pair.of(this.createString(it.key), it.value) }) + else DataResult.error { "Not a map: $tag" } override fun mergeToMap(data1: NBTData, data2: NBTData, data3: NBTData): DataResult { - if (data1 !is NBTCompound) { + if (data1 !is NBTCompound && data1 !is NBTEnd) { return DataResult.error({ "mergeToMap called with not a map: $data1" }, data1) } else if (data2 !is NBTString) { return DataResult.error({ "key is not a string: $data2" }, data1) } else { - val newMap = data1.clone() // TODO shallowCopy() + val newMap = (data1 as? NBTCompound)?.cloneShallow() ?: NBTCompound() newMap.put(data2.content, data3) return DataResult.success(newMap) } @@ -173,13 +148,12 @@ class NMS12005Impl : NMS12005() { DataResult.success(NBTList(data1.plus(data2.content))) // TODO Improve else DataResult.error({ "mergeToList called with not a list: $data1" }, data1) - override fun getStringValue(data: NBTData?): DataResult { - return if (data is NBTString) DataResult.success(data.content) else DataResult.error { "Not a string" } - } + override fun getStringValue(data: NBTData): DataResult = + if (data is NBTString) DataResult.success(data.content) else DataResult.error { "Not a string: $data" } override fun getNumberValue(data: NBTData): DataResult { val number = data.content as? Number - return if (number != null) DataResult.success(number) else DataResult.error { "Not a number" } + return if (number != null) DataResult.success(number) else DataResult.error { "Not a number: $data" } } override fun convertTo(ops: DynamicOps, data: NBTData): U = @@ -202,4 +176,8 @@ class NMS12005Impl : NMS12005() { } +} + +object NBTEnd : NBTData(Unit, NBTType.END) { + override val content = Unit } \ 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 8e7c1617..9a80816c 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,15 +1,18 @@ package cn.fd.ratziel.module.item.nms -import cn.fd.ratziel.module.item.nbt.NBTCompound +import cn.fd.ratziel.module.item.nbt.* +import cn.fd.ratziel.module.item.nbt.NBTList import net.minecraft.core.component.DataComponentMap import net.minecraft.core.component.DataComponentPatch import net.minecraft.core.component.DataComponents import net.minecraft.core.component.PatchedDataComponentMap -import net.minecraft.nbt.NBTTagCompound +import net.minecraft.nbt.* import net.minecraft.world.item.component.CustomData import taboolib.library.reflex.ReflexClass +import taboolib.library.reflex.UnsafeAccess import taboolib.module.nms.MinecraftVersion import taboolib.module.nms.nmsProxy +import java.lang.invoke.MethodHandle import net.minecraft.world.item.ItemStack as NMSItemStack /** @@ -49,47 +52,32 @@ abstract class NMSItem { */ abstract fun copyItem(nmsItem: Any): Any + /** + * [NBTData] to [NBTTagCompound] + */ + abstract fun toNms(data: NBTData): Any + + /** + * [NBTTagCompound] to [NBTData] + */ + abstract fun fromNms(nmsData: Any): NBTData + companion object { val INSTANCE by lazy { - if (MinecraftVersion.majorLegacy >= 12005) nmsProxy("{name}Impl2") else NMSItemImpl1 + if (MinecraftVersion.majorLegacy >= 12005) + nmsProxy("{name}Impl2") + else nmsProxy("{name}Impl1") } } } -/** - * 1.20.4- - */ -object NMSItemImpl1 : NMSItem() { - - override fun getTag(nmsItem: Any): NBTCompound? { - return RefItemStack.InternalUtil.nmsTagField.get(nmsItem)?.let { NBTCompound.of(it).clone() } - } - - override fun setTag(nmsItem: Any, tag: NBTCompound) { - RefItemStack.InternalUtil.nmsTagField.set(nmsItem, tag.clone().getRaw()) - } - - override fun getCustomTag(nmsItem: Any): NBTCompound? { - return getTag(nmsItem)?.get(ItemSheet.CUSTOM_DATA.name) as? NBTCompound - } - - override fun setCustomTag(nmsItem: Any, tag: NBTCompound) { - getTag(nmsItem)?.put(ItemSheet.CUSTOM_DATA.name, tag) - } - - override fun copyItem(nmsItem: Any): Any { - return RefItemStack.InternalUtil.nmsCloneMethod.invoke(nmsItem)!! - } - -} - /** * 1.20.5+ */ -@Suppress("unused") +@Suppress("unused", "MemberVisibilityCanBePrivate") class NMSItemImpl2 : NMSItem() { val componentsField by lazy { @@ -127,4 +115,191 @@ class NMSItemImpl2 : NMSItem() { return (nmsItem as NMSItemStack).copy() } -} \ No newline at end of file + override fun toNms(data: NBTData): NBTBase = when (data) { + is NBTString -> NBTTagString.valueOf(data.content) + is NBTInt -> NBTTagInt.valueOf(data.content) + is NBTByte -> NBTTagByte.valueOf(data.content) + is NBTDouble -> NBTTagDouble.valueOf(data.content) + is NBTFloat -> NBTTagFloat.valueOf(data.content) + is NBTLong -> NBTTagLong.valueOf(data.content) + is NBTShort -> NBTTagShort.valueOf(data.content) + is NBTIntArray -> NBTTagIntArray(data.content.copyOf()) + is NBTByteArray -> NBTTagByteArray(data.content.copyOf()) + is NBTLongArray -> NBTTagLongArray(data.content.copyOf()) + is NBTList -> NBTTagList().also { nmsList -> data.content.forEach { nmsList.add(toNms(it)) } } + is NBTCompound -> NBTTagCompound().also { nmsCompound -> data.content.forEach { nmsCompound.put(it.key, toNms(it.value)) } } + else -> throw UnsupportedOperationException("NBTData cannot convert to NmsNBTData: $data") + } + + override fun fromNms(nmsData: Any): NBTData = when (nmsData) { + is NBTTagString -> NBTString(nmsData.asString) + is NBTTagInt -> NBTInt(nmsData.asInt) + is NBTTagByte -> NBTByte(nmsData.asByte) + is NBTTagDouble -> NBTDouble(nmsData.asDouble) + is NBTTagFloat -> NBTFloat(nmsData.asFloat) + is NBTTagLong -> NBTLong(nmsData.asLong) + is NBTTagShort -> NBTShort(nmsData.asShort) + is NBTTagByteArray -> NBTByteArray(nmsData.asByteArray.copyOf()) + is NBTTagIntArray -> NBTIntArray(nmsData.asIntArray.copyOf()) + is NBTTagLongArray -> NBTLongArray(nmsData.asLongArray.copyOf()) + is NBTTagList -> NBTList().apply { nmsData.forEach { add(fromNms(it)) } } + is NBTTagCompound -> NBTCompound().apply { nmsData.allKeys.forEach { put(it, fromNms(nmsData.get(it)!!)) } } + else -> throw UnsupportedOperationException("NmsNBTData cannot convert to NBTData: $nmsData") + } + +} + +/** + * 1.20.4- + * + * 代码参考自: Taboolib/nms-tag-legacy + */ +@Suppress("unused", "MemberVisibilityCanBePrivate") +class NMSItemImpl1 : NMSItem() { + + override fun getTag(nmsItem: Any): NBTCompound? { + return nmsTagField.get(nmsItem)?.let { fromNms(it) } as? NBTCompound + } + + override fun setTag(nmsItem: Any, tag: NBTCompound) { + nmsTagField.set(nmsItem, toNms(tag)) + } + + override fun getCustomTag(nmsItem: Any): NBTCompound? { + val nmsTag = nmsTagField.get(nmsItem) ?: return null + val map = nbtTagCompoundGetter.get>(nmsTag) + val customTag = map[ItemSheet.CUSTOM_DATA.name] as? NBTTagCompound12 ?: return null + return fromNms(customTag) as NBTCompound + } + + override fun setCustomTag(nmsItem: Any, tag: NBTCompound) { + val nmsTag = nmsTagField.get(nmsItem) ?: return + val map = nbtTagCompoundGetter.get>(nmsTag) + map[ItemSheet.CUSTOM_DATA.name] = toNms(tag) + } + + override fun copyItem(nmsItem: Any): Any { + return nmsCloneMethod.invoke(nmsItem)!! + } + + /** + * private NBTTagCompound A + * private NBTTagCompound tag + */ + val nmsTagField = ReflexClass.of(RefItemStack.nmsClass).structure.getField(if (MinecraftVersion.isUniversal) "A" else "tag") + + /** + * public nms.ItemStack p() + * public nms.ItemStack cloneItemStack() + * public ItemStack s() + */ + val nmsCloneMethod by lazy { + ReflexClass.of(RefItemStack.nmsClass).structure.getMethodByType( + if (MinecraftVersion.majorLegacy >= 12005) "s" + else if (MinecraftVersion.isUniversal) "p" + else "cloneItemStack" + ) + } + + val nbtTagCompoundGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "x" else "map") + val nbtTagListGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "list") + val nbtTagListTypeSetter = unreflectSetter(if (MinecraftVersion.isUniversal) "w" else "type") + val nbtTagByteGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "x" else "data") + val nbtTagShortGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "data") + val nbtTagIntGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "data") + val nbtTagLongGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "data") + val nbtTagFloatGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "w" else "data") + val nbtTagDoubleGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "w" else "data") + val nbtTagStringGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "A" else "data") + val nbtTagByteArrayGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "data") + val nbtTagIntArrayGetter = unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "data") + val nbtTagLongArrayGetter = + if (!MinecraftVersion.isHigherOrEqual(MinecraftVersion.V1_12)) null + else unreflectGetter(if (MinecraftVersion.isUniversal) "c" else "b") + + val new = MinecraftVersion.isHigherOrEqual(MinecraftVersion.V1_15) + + override fun toNms(data: NBTData): Any = when (data) { + is NBTString -> if (new) NBTTagString15.a(data.content) else NBTTagString12(data.content) + is NBTInt -> if (new) NBTTagInt15.a(data.content) else NBTTagInt12(data.content) + is NBTByte -> if (new) NBTTagByte15.a(data.content) else NBTTagByte12(data.content) + is NBTDouble -> if (new) NBTTagDouble15.a(data.content) else NBTTagDouble12(data.content) + is NBTFloat -> if (new) NBTTagFloat15.a(data.content) else NBTTagFloat12(data.content) + is NBTLong -> if (new) NBTTagLong15.a(data.content) else NBTTagLong12(data.content) + is NBTShort -> if (new) NBTTagShort15.a(data.content) else NBTTagShort12(data.content) + is NBTIntArray -> NBTTagIntArray12(data.content.copyOf()) + is NBTByteArray -> NBTTagByteArray12(data.content.copyOf()) + is NBTLongArray -> NBTTagLongArray12(data.content.copyOf()) + is NBTList -> NBTTagList12().also { src -> + // 反射获取字段: + // private final List list; + val list = nbtTagListGetter.get>(src) + val dataList = data.content + if (dataList.isNotEmpty()) { + dataList.forEach { list.add(toNms(it)) } + // 修改 NBTTagList 的类型,不改他妈这条 List 作废,天坑。。。 + nbtTagListTypeSetter.set(src, dataList.first().type.id) + } + } + + is NBTCompound -> NBTTagCompound().also { src -> + // 反射获取字段: + // private final Map map + val map = nbtTagCompoundGetter.get>(src) + data.forEach { map[it.key] = toNms(it.value) } + } + + else -> throw UnsupportedOperationException("NBTData cannot convert to NmsNBTData: $data") + } + + override fun fromNms(nmsData: Any): NBTData = when (nmsData) { + is NBTTagString12 -> NBTString(nbtTagStringGetter.get(nmsData)) + is NBTTagInt12 -> NBTInt(nbtTagIntGetter.get(nmsData)) + is NBTTagByte12 -> NBTByte(nbtTagByteGetter.get(nmsData)) + is NBTTagDouble12 -> NBTDouble(nbtTagDoubleGetter.get(nmsData)) + is NBTTagFloat12 -> NBTFloat(nbtTagFloatGetter.get(nmsData)) + is NBTTagLong12 -> NBTLong(nbtTagLongGetter.get(nmsData)) + is NBTTagShort12 -> NBTShort(nbtTagShortGetter.get(nmsData)) + is NBTTagByteArray12 -> NBTByteArray(nbtTagByteArrayGetter.get(nmsData).copyOf()) + is NBTTagIntArray12 -> NBTIntArray(nbtTagIntArrayGetter.get(nmsData).copyOf()) + is NBTTagLongArray12 -> NBTLongArray(nbtTagLongArrayGetter!!.get(nmsData).copyOf()) + is NBTTagList12 -> NBTList().apply { nbtTagListGetter.get>(nmsData).forEach { add(fromNms(it)) } } + is NBTTagCompound12 -> NBTCompound().apply { nbtTagCompoundGetter.get>(nmsData).forEach { put(it.key, fromNms(it.value)) } } + else -> throw UnsupportedOperationException("NmsNBTData cannot convert to NBTData: $nmsData") + } + + private inline fun unreflectGetter(name: String): MethodHandle { + return UnsafeAccess.lookup.unreflectGetter(T::class.java.getDeclaredField(name).apply { isAccessible = true }) + } + + private inline fun unreflectSetter(name: String): MethodHandle { + return UnsafeAccess.lookup.unreflectSetter(T::class.java.getDeclaredField(name).apply { isAccessible = true }) + } + + @Suppress("UNCHECKED_CAST") + private fun MethodHandle.get(src: Any): T = bindTo(src).invoke() as T + + private fun MethodHandle.set(src: Any, value: T) = bindTo(src).invoke(value) + +} + +typealias NBTTagCompound12 = net.minecraft.server.v1_12_R1.NBTTagCompound +typealias NBTTagList12 = net.minecraft.server.v1_12_R1.NBTTagList +typealias NBTTagByte12 = net.minecraft.server.v1_12_R1.NBTTagByte +typealias NBTTagShort12 = net.minecraft.server.v1_12_R1.NBTTagShort +typealias NBTTagInt12 = net.minecraft.server.v1_12_R1.NBTTagInt +typealias NBTTagLong12 = net.minecraft.server.v1_12_R1.NBTTagLong +typealias NBTTagFloat12 = net.minecraft.server.v1_12_R1.NBTTagFloat +typealias NBTTagDouble12 = net.minecraft.server.v1_12_R1.NBTTagDouble +typealias NBTTagString12 = net.minecraft.server.v1_12_R1.NBTTagString +typealias NBTTagByteArray12 = net.minecraft.server.v1_12_R1.NBTTagByteArray +typealias NBTTagIntArray12 = net.minecraft.server.v1_12_R1.NBTTagIntArray +typealias NBTTagLongArray12 = net.minecraft.server.v1_12_R1.NBTTagLongArray + +typealias NBTTagByte15 = net.minecraft.server.v1_15_R1.NBTTagByte +typealias NBTTagShort15 = net.minecraft.server.v1_15_R1.NBTTagShort +typealias NBTTagInt15 = net.minecraft.server.v1_15_R1.NBTTagInt +typealias NBTTagLong15 = net.minecraft.server.v1_15_R1.NBTTagLong +typealias NBTTagFloat15 = net.minecraft.server.v1_15_R1.NBTTagFloat +typealias NBTTagDouble15 = net.minecraft.server.v1_15_R1.NBTTagDouble +typealias NBTTagString15 = net.minecraft.server.v1_15_R1.NBTTagString \ 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 e468b56b..9fcbc694 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 @@ -95,7 +95,7 @@ class RefItemMeta(raw: T) { } internal fun new(tag: NBTCompound): T { - val handled = if (MinecraftVersion.majorLegacy >= 12005) NMS12005.INSTANCE.parsePatch(tag)!! else tag + val handled = if (MinecraftVersion.majorLegacy >= 12005) NMS12005.INSTANCE.parsePatch(tag)!! else NMSItem.INSTANCE.toNms(tag) return uncheck(craftMetaConstructor.instance(handled)!!) } @@ -112,7 +112,7 @@ class RefItemMeta(raw: T) { val newTag = NMS12005.INSTANCE.savePatch(dcp) // DataComponentPatch save to NBT if (newTag != null) tag.mergeShallow(newTag, true) } else { - applyToItemMethod.invoke(meta, tag.getRaw()) + applyToItemMethod.invoke(meta, NMSItem.INSTANCE.toNms(tag)) } } 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 3f746a7c..081e50c6 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 @@ -234,29 +234,6 @@ class RefItemStack(raw: Any) { internal object InternalUtil { - /** - * private NBTTagCompound A - * private NBTTagCompound tag - */ - val nmsTagField by lazy { - ReflexClass.of(nmsClass).structure.getField( - if (MinecraftVersion.isUniversal) "A" else "tag" - ) - } - - /** - * public nms.ItemStack p() - * public nms.ItemStack cloneItemStack() - * public ItemStack s() - */ - val nmsCloneMethod by lazy { - ReflexClass.of(nmsClass).structure.getMethodByType( - if (MinecraftVersion.majorLegacy >= 12005) "s" - else if (MinecraftVersion.isUniversal) "p" - else "cloneItemStack" - ) - } - // net.minecraft.world.item.ItemStack handle; val obcHandleField by lazy { ReflexClass.of(obcClass).structure.getField("handle")