diff --git a/project/module-core/src/main/java/cn/fd/ratziel/function/ArgumentContext.java b/project/module-core/src/main/java/cn/fd/ratziel/function/ArgumentContext.java index 3019de3d..4bc454c3 100644 --- a/project/module-core/src/main/java/cn/fd/ratziel/function/ArgumentContext.java +++ b/project/module-core/src/main/java/cn/fd/ratziel/function/ArgumentContext.java @@ -1,5 +1,6 @@ package cn.fd.ratziel.function; +import cn.fd.ratziel.function.exception.ArgumentNotFoundException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,11 +17,11 @@ public interface ArgumentContext { /** * 弹出第一个指定类型的参数 * - * @throws NullPointerException 当无法找到指定类型的参数时抛出 + * @throws ArgumentNotFoundException 当无法找到指定类型的参数时抛出 */ - default <@NotNull T> @NotNull T pop(@NotNull Class type) throws NullPointerException { + default <@NotNull T> @NotNull T pop(@NotNull Class type) throws ArgumentNotFoundException { T result = popOrNull(type); - if (result == null) throw new NullPointerException("Cannot find argument: " + type.getName() + " !"); + if (result == null) throw new ArgumentNotFoundException(type); return result; } diff --git a/project/module-core/src/main/java/cn/fd/ratziel/function/exception/ArgumentNotFoundException.java b/project/module-core/src/main/java/cn/fd/ratziel/function/exception/ArgumentNotFoundException.java new file mode 100644 index 00000000..e3c5f505 --- /dev/null +++ b/project/module-core/src/main/java/cn/fd/ratziel/function/exception/ArgumentNotFoundException.java @@ -0,0 +1,15 @@ +package cn.fd.ratziel.function.exception; + +/** + * ArgumentNotFoundException + * + * @author TheFloodDragon + * @since 2024/8/16 18:28 + */ +public final class ArgumentNotFoundException extends Exception { + + public ArgumentNotFoundException(Class type) { + super("Cannot found the argument: " + type.getName() + " !"); + } + +} diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/Identifier.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/Identifier.kt index b64f7037..9e1d65ae 100644 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/Identifier.kt +++ b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/Identifier.kt @@ -8,19 +8,13 @@ package cn.fd.ratziel.core */ interface Identifier { - - /** - * 判断此标识符是否与另一个对象相同 - */ - override fun equals(other: Any?): Boolean - /** - * 获取标识符的字符串形式 + * 获取标识符的字符串内容 */ - override fun toString(): String + val content: String /** - * 此标识符的Hash码 + * 此标识符的 [hashCode] */ override fun hashCode(): Int diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/IdentifierImpl.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/IdentifierImpl.kt index 625fb016..cc274924 100644 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/IdentifierImpl.kt +++ b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/IdentifierImpl.kt @@ -8,16 +8,13 @@ import java.util.* * @author TheFloodDragon * @since 2024/6/24 13:47 */ -open class IdentifierImpl(val unique: String) : Identifier { +@JvmInline +value class IdentifierImpl(override val content: String) : Identifier { constructor(uuid: UUID) : this(uuid.toString()) constructor() : this(UUID.randomUUID()) - override fun equals(other: Any?): Boolean = unique == other - - override fun toString(): String = unique - - override fun hashCode(): Int = unique.hashCode() + override fun toString() = "Identifier(unique=$content)" } \ No newline at end of file diff --git a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/element/ElementIdentifier.kt b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/element/ElementIdentifier.kt index b5947979..b7234010 100644 --- a/project/module-core/src/main/kotlin/cn/fd/ratziel/core/element/ElementIdentifier.kt +++ b/project/module-core/src/main/kotlin/cn/fd/ratziel/core/element/ElementIdentifier.kt @@ -24,6 +24,8 @@ open class ElementIdentifier( open val file: File?, ) : Identifier { + override val content get() = this.name + override fun toString() = this::class.java.simpleName + '{' + "name=" + name + ";" + "type=" + type + ";" + "path=" + file?.path + '}' override fun equals(other: Any?) = other is ElementIdentifier && this.name == other.name && this.type == other.type && this.file == other.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 4b65bb9d..ee0d8591 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 @@ -4,11 +4,13 @@ import cn.fd.ratziel.common.element.registry.NewElement import cn.fd.ratziel.common.event.WorkspaceLoadEvent import cn.fd.ratziel.core.element.Element import cn.fd.ratziel.core.element.api.ElementHandler -import cn.fd.ratziel.module.item.impl.builder.DefaultItemGenerator +import cn.fd.ratziel.module.item.impl.builder.DefaultGenerator +import cn.fd.ratziel.module.item.impl.builder.DefaultSerializer +import cn.fd.ratziel.module.item.impl.component.* import cn.fd.ratziel.module.item.nms.RefItemStack +import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.cancel +import kotlinx.coroutines.asCoroutineDispatcher import taboolib.common.platform.event.SubscribeEvent import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -35,16 +37,23 @@ object ItemElement : ElementHandler { /** * 协程作用域 */ - val buildScope = CoroutineScope(Dispatchers.Default) + val scope = CoroutineScope(CoroutineName("ItemHandler") + executor.asCoroutineDispatcher()) init { - // 注册默认的东西 - ItemRegistry.registerDefault() + // 注册默认序列化器 + ItemRegistry.register(DefaultSerializer) + // 注册默认转换器 + ItemRegistry.register(ItemDisplay::class.java, ItemDisplay) + ItemRegistry.register(ItemDurability::class.java, ItemDurability) + ItemRegistry.register(ItemSundry::class.java, ItemSundry) + ItemRegistry.register(ItemMetadata::class.java, ItemMetadata) + ItemRegistry.register(ItemCharacteristic::class.java, ItemCharacteristic) + // 注册自定义物品解析器 (默认解析器无需注册, 保持在最后直接使用) } override fun handle(element: Element) { - val generator = DefaultItemGenerator(element) + val generator = DefaultGenerator(element) val item = generator.build().get() @@ -61,8 +70,6 @@ object ItemElement : ElementHandler { @SubscribeEvent fun onLoadStart(event: WorkspaceLoadEvent.Start) { - // 清除协程任务 - buildScope.cancel() // 清除注册的物品 ItemManager.registry.clear() } diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemRegistry.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemRegistry.kt index bfd31edf..2d58419e 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemRegistry.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/ItemRegistry.kt @@ -9,9 +9,6 @@ import cn.fd.ratziel.module.item.api.builder.ItemTransformer import cn.fd.ratziel.module.item.api.registry.ComponentRegistry import cn.fd.ratziel.module.item.api.registry.ResolverRegistry import cn.fd.ratziel.module.item.api.registry.SerializerRegistry -import cn.fd.ratziel.module.item.impl.builder.CommonItemResolver -import cn.fd.ratziel.module.item.impl.builder.CommonItemSerializer -import cn.fd.ratziel.module.item.impl.component.* import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArrayList @@ -24,114 +21,111 @@ import java.util.concurrent.CopyOnWriteArrayList object ItemRegistry { /** - * 注册默认的东西 + * 注册组件 */ - internal fun registerDefault() { - // 注册默认序列化器 - Serializer.register(CommonItemSerializer) - // 注册默认转换器 - Component.register(ItemDisplay::class.java, ItemDisplay) - Component.register(ItemDurability::class.java, ItemDurability) - Component.register(ItemSundry::class.java, ItemSundry) - Component.register(ItemMetadata::class.java, ItemMetadata) - Component.register(ItemCharacteristic::class.java, ItemCharacteristic) - // 注册默认物品解析器 -// Resolver.register(BasicItemResolver) - Resolver.register(CommonItemResolver) - } + fun register(type: Class, transformer: ItemTransformer) = Component.register(type, transformer) + + /** + * 注册解析器 + */ + fun register(resolver: ItemResolver) = Resolver.register(resolver) + + /** + * 注册序列化器 + */ + fun register(serializer: ItemSerializer<*>) = Serializer.register(serializer) object Component : ComponentRegistry { /** * 物品组件注册表 */ - internal val registry: MutableMap, Priority>> = ConcurrentHashMap() + internal val registry: MutableMap, ItemTransformer<*>> = ConcurrentHashMap() - override fun register(type: Class, transformer: ItemTransformer, priority: Byte) { - registry[type] = Priority(priority, transformer) + override fun register(type: Class, transformer: ItemTransformer) { + registry[type] = transformer } override fun unregister(type: Class<*>) { registry.remove(type) } - override fun getPriority(type: Class): Priority>? = uncheck(registry[type]) + override fun get(type: Class): ItemTransformer? = uncheck(registry[type]) - override fun isRegistered(type: Class<*>) = registry.containsKey(type) + @Suppress("UNCHECKED_CAST") + fun getUnsafe(type: Class<*>): ItemTransformer? = registry[type] as? ItemTransformer - override fun getRegistry(): Map, ItemTransformer<*>> = buildMap { - getRegistryPriority().forEach { (k, p) -> put(k, p.value) } - } + override fun isRegistered(type: Class<*>) = registry.containsKey(type) - override fun getRegistryPriority(): Map, Priority>> = registry + override fun getRegistry() = registry } - object Serializer : SerializerRegistry { + object Resolver : ResolverRegistry { /** * 物品序列化器注册表 */ - internal val registry: MutableList> = CopyOnWriteArrayList() + internal val registry: MutableList> = CopyOnWriteArrayList() - override fun register(serializer: ItemSerializer<*>) { - registry.add(serializer) + override fun register(resolver: ItemResolver, priority: Byte) { + registry.add(Priority(priority, resolver)) } - override fun unregister(type: Class>) { + override fun unregister(type: Class) { for (element in registry) { - if (element::class.java == type) registry.remove(element) + if (element.value::class.java == type) registry.remove(element) } } - override fun unregister(serializer: ItemSerializer<*>) { - registry.remove(serializer) + override fun unregister(resolver: ItemResolver) { + for (element in registry) { + if (element.value == resolver) registry.remove(element) + } } - override fun > get(type: Class): T? = uncheck(registry.find { it::class.java == type }) + override fun getWithPriority(type: Class): Priority? = uncheck(registry.find { it::class.java == type }) - override fun isRegistered(type: Class>) = registry.find { it::class.java == type } != null + override fun isRegistered(type: Class) = registry.find { it.value::class.java == type } != null - override fun isRegistered(serializer: ItemSerializer<*>) = registry.contains(serializer) + override fun isRegistered(resolver: ItemResolver) = registry.find { it.value == resolver } != null - override fun getSerializers(): List> = registry + override fun getResolvers() = registry.map { it.value } + + override fun getResolversWithPriority(): Collection> = registry + + fun getResolversSorted(): List = registry.sortPriority() } - object Resolver : ResolverRegistry { + object Serializer : SerializerRegistry { /** * 物品序列化器注册表 */ - internal val registry: MutableList> = CopyOnWriteArrayList() + internal val registry: MutableList> = CopyOnWriteArrayList() - override fun register(resolver: ItemResolver, priority: Byte) { - registry.add(Priority(priority, resolver)) + override fun register(serializer: ItemSerializer<*>) { + registry.add(serializer) } - override fun unregister(type: Class) { + override fun unregister(type: Class>) { for (element in registry) { - if (element.value::class.java == type) registry.remove(element) + if (element::class.java == type) registry.remove(element) } } - override fun unregister(resolver: ItemResolver) { - for (element in registry) { - if (element.value == resolver) registry.remove(element) - } + override fun unregister(serializer: ItemSerializer<*>) { + registry.remove(serializer) } - override fun getPriority(type: Class): Priority? = uncheck(registry.find { it::class.java == type }) - - override fun isRegistered(type: Class) = registry.find { it.value::class.java == type } != null - - override fun isRegistered(resolver: ItemResolver) = registry.find { it.value == resolver } != null + override fun > get(type: Class): T? = uncheck(registry.find { it::class.java == type }) - override fun getResolvers() = registry.map { it.value } + override fun isRegistered(type: Class>) = registry.find { it::class.java == type } != null - override fun getResolversPriority(): Collection> = registry + override fun isRegistered(serializer: ItemSerializer<*>) = registry.contains(serializer) - fun getResolversSorted(): List = registry.sortPriority() + override fun getSerializers(): List> = registry } diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/builder/SectionTagResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/builder/SectionTagResolver.kt index 4655f3a3..9fad9e1b 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/builder/SectionTagResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/builder/SectionTagResolver.kt @@ -8,7 +8,7 @@ import cn.fd.ratziel.module.item.api.ArgumentResolver * @author TheFloodDragon * @since 2024/8/13 14:44 */ -interface SectionTagResolver :ArgumentResolver, String?>{ +interface SectionTagResolver : ArgumentResolver, String?> { /** * 解析器名称 diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolveEvent.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolvedEvent.kt similarity index 62% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolveEvent.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolvedEvent.kt index ee1ca927..356d7347 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolveEvent.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/event/ItemResolvedEvent.kt @@ -1,28 +1,23 @@ package cn.fd.ratziel.module.item.api.event import cn.fd.ratziel.core.Identifier -import cn.fd.ratziel.function.ArgumentContext import kotlinx.serialization.json.JsonElement /** - * ItemResolveEvent + * ItemResolvedEvent * * 构建物品中的所有解析阶段完成后触发 * * @author TheFloodDragon * @since 2024/7/3 15:15 */ -class ItemResolveEvent( +class ItemResolvedEvent( /** * 物品标识符 */ identifier: Identifier, /** - * 解析出的最终结果 + * 解析结果 */ - var result: JsonElement, - /** - * 上下文 - */ - val context: ArgumentContext + val result: JsonElement, ) : ItemEvent(identifier) \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ComponentRegistry.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ComponentRegistry.kt index b40d46a7..a43e58ec 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ComponentRegistry.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ComponentRegistry.kt @@ -1,6 +1,5 @@ package cn.fd.ratziel.module.item.api.registry -import cn.fd.ratziel.core.Priority import cn.fd.ratziel.module.item.api.builder.ItemTransformer /** @@ -15,16 +14,8 @@ interface ComponentRegistry { * 注册组件以及其转换器 * @param type 组件类型 (组件类) * @param transformer 绑定到组件上的物品转换器 - * @param priority 优先级 */ - fun register(type: Class, transformer: ItemTransformer, priority: Byte) - - /** - * 注册组件以及其转换器 - * @param type 组件类型 (组件类) - * @param transformer 绑定到组件上的物品转换器 - */ - fun register(type: Class, transformer: ItemTransformer) = register(type, transformer, Priority.DEFAULT_PRIORITY) + fun register(type: Class, transformer: ItemTransformer) /** * 取消注册组件以及其转换器 @@ -37,14 +28,7 @@ interface ComponentRegistry { * @param type 组件类型 (组件类) * @return 对应组件类型的转化器, 当该组件未注册时, 返回空 */ - fun get(type: Class): ItemTransformer? = getPriority(type)?.value - - /** - * 获取对应组件类型的转化器 - [Priority] - * @param type 组件类型 (组件类) - * @return 对应组件类型的转化器, 当该组件未注册时, 返回空 - */ - fun getPriority(type: Class): Priority>? + fun get(type: Class): ItemTransformer? /** * 判断此组件是否被注册过 @@ -57,9 +41,4 @@ interface ComponentRegistry { */ fun getRegistry(): Map, ItemTransformer<*>> - /** - * 获取注册表的 [Map] 形式 - [Priority] - */ - fun getRegistryPriority(): Map, Priority>> - } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ResolverRegistry.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ResolverRegistry.kt index e4c254a7..6f4d4ae1 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ResolverRegistry.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/ResolverRegistry.kt @@ -9,7 +9,6 @@ import cn.fd.ratziel.module.item.api.builder.ItemResolver * @author TheFloodDragon * @since 2024/6/25 14:13 */ -@Deprecated("独立交给ItemGenerator控制") interface ResolverRegistry { /** @@ -40,12 +39,12 @@ interface ResolverRegistry { /** * 获取指定类型的物品解析器 */ - fun get(type: Class): T? = getPriority(type)?.value + fun get(type: Class): T? = getWithPriority(type)?.value /** * 获取指定类型的物品解析器 - [Priority] */ - fun getPriority(type: Class): Priority? + fun getWithPriority(type: Class): Priority? /** * 判断指定类型的解析器是否被注册过 @@ -67,6 +66,6 @@ interface ResolverRegistry { /** * 获取所有注册的解析器 - [Priority] */ - fun getResolversPriority(): Collection> + fun getResolversWithPriority(): Collection> } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/SerializerRegistry.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/SerializerRegistry.kt index a395c253..8707b1c0 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/SerializerRegistry.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/api/registry/SerializerRegistry.kt @@ -8,7 +8,6 @@ import cn.fd.ratziel.module.item.api.builder.ItemSerializer * @author TheFloodDragon * @since 2024/6/25 13:34 */ -@Deprecated("独立交给ItemGenerator控制") interface SerializerRegistry { /** diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/ItemInfo.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/ItemInfo.kt index dcff45d4..25dd3b5d 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/ItemInfo.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/ItemInfo.kt @@ -36,22 +36,22 @@ data class ItemInfo( /** * [RatzielItem] 物品数据节点 */ - val RATZIEL_NODE = OccupyNode("Ratziel", ItemSheet.CUSTOM_DATA) + val RATZIEL_NODE = SimpleNode("Ratziel", ItemSheet.CUSTOM_DATA) /** * [RatzielItem] 物品标识符 */ - val RATZIEL_IDENTIFIER_NODE = OccupyNode("Identifier", RATZIEL_NODE) + val RATZIEL_IDENTIFIER_NODE = SimpleNode("Identifier", RATZIEL_NODE) /** * [RatzielItem] 物品元素名称 */ - val RATZIEL_ELEMENT_NODE = OccupyNode("Type", RATZIEL_NODE) + val RATZIEL_ELEMENT_NODE = SimpleNode("Type", RATZIEL_NODE) /** * [RatzielItem] 物品元素内容哈希值 */ - val RATZIEL_HASH_NODE = OccupyNode("Hash", RATZIEL_NODE) + val RATZIEL_HASH_NODE = SimpleNode("Hash", RATZIEL_NODE) /** * 向 [NBTCompound] 中写入 [ItemInfo] diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/RatzielItem.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/RatzielItem.kt index a243c762..5debf5e4 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/RatzielItem.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/RatzielItem.kt @@ -56,7 +56,7 @@ open class RatzielItem : NeoItem { * 物品数据节点 */ @JvmField - val RATZIEL_DATA_NODE = OccupyNode("Ratziel", ItemSheet.CUSTOM_DATA) + val RATZIEL_DATA_NODE = SimpleNode("Ratziel", ItemSheet.CUSTOM_DATA) /** * 将目标 [ItemStack] 转为 [RatzielItem] @@ -124,19 +124,19 @@ open class RatzielItem : NeoItem { * 专有信息节点 */ @JvmField - val INTERNAL_NODE = OccupyNode("internal", RATZIEL_DATA_NODE) + val INTERNAL_NODE = SimpleNode("internal", RATZIEL_DATA_NODE) /** * 内部信息 - [id] */ @JvmField - val INFO_TYPE = OccupyNode("type", INTERNAL_NODE) + val INFO_TYPE = SimpleNode("type", INTERNAL_NODE) /** * 内部信息 - [hash] */ @JvmField - val INFO_HASH = OccupyNode("hash", INTERNAL_NODE) + val INFO_HASH = SimpleNode("hash", INTERNAL_NODE) /** * 从 [ItemData] 中读取信息 diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemData.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleData.kt similarity index 97% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemData.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleData.kt index 9ba71d79..5c701458 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemData.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleData.kt @@ -5,12 +5,12 @@ import cn.fd.ratziel.module.item.api.ItemMaterial import cn.fd.ratziel.module.nbt.NBTCompound /** - * SimpleItemData + * SimpleData * * @author TheFloodDragon * @since 2024/5/5 13:33 */ -data class SimpleItemData( +data class SimpleData( /** * 物品材料 */ diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemMaterial.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleMaterial.kt similarity index 57% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemMaterial.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleMaterial.kt index 0f804a66..5d50e492 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleItemMaterial.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleMaterial.kt @@ -4,19 +4,22 @@ import cn.fd.ratziel.module.item.api.ItemMaterial import taboolib.library.reflex.ReflexClass import taboolib.library.xseries.XMaterial +typealias BukkitMaterial = org.bukkit.Material + /** - * SimpleItemMaterial + * SimpleMaterial * * 由于不可抗力的影响(我不会), 仅支持 [BukkitMaterial], 即仅支持原版物品 * * @author TheFloodDragon * @since 2024/4/5 13:26 */ -open class SimpleItemMaterial(private val ref: BukkitMaterial) : ItemMaterial { +@JvmInline +value class SimpleMaterial(private val ref: BukkitMaterial) : ItemMaterial { - constructor(name: String) : this(getBukkitMaterial(name) ?: BukkitMaterial.AIR) + constructor(name: String) : this(findBukkit(name) ?: BukkitMaterial.AIR) - constructor(id: Int) : this(getBukkitMaterial(id) ?: BukkitMaterial.AIR) + constructor(id: Int) : this(findBukkit(id) ?: BukkitMaterial.AIR) constructor(mat: XMaterial) : this(mat.name) @@ -25,7 +28,7 @@ open class SimpleItemMaterial(private val ref: BukkitMaterial) : ItemMaterial { /** * 材料标识符 (低版本) */ - override val id: Int get() = getIdUnsafe(ref) + override val id: Int get() = ref.unsafeId /** * 材料名称 @@ -45,51 +48,50 @@ open class SimpleItemMaterial(private val ref: BukkitMaterial) : ItemMaterial { /** * 材料是否为空气材料 */ - open fun isAir() = ref.isAir || this.isEmpty() + override fun isEmpty() = ref.isAir || super.isEmpty() /** * 获取 [BukkitMaterial] 形式 */ - open fun getAsBukkit(): BukkitMaterial = ref + fun getAsBukkit(): BukkitMaterial = ref /** * 获取 [XMaterial] 形式 */ - open fun getAsXSeries(): XMaterial = XMaterial.matchXMaterial(ref) + fun getAsXSeries(): XMaterial = XMaterial.matchXMaterial(ref) override fun toString() = "SimpleItemMaterial(name=$name,id=$id)" - override fun hashCode() = name.hashCode() - - override fun equals(other: Any?) = equals(this, other) - companion object { - fun equals(material: ItemMaterial, other: Any?) = material === other - || (other as? ItemMaterial)?.name == material.name - || (other as? BukkitMaterial)?.name == material.name - || (other as? XMaterial)?.name == material.name - - /** - * 获取 [BukkitMaterial] 形式的物品材料 - */ - fun getBukkitMaterial(name: String) = BukkitMaterial.getMaterial(name) - - fun getBukkitMaterial(id: Int) = BukkitMaterial.entries.find { getIdUnsafe(it) == id } - /** * 材料大全 */ val materialsMap by lazy { HashMap().apply { - BukkitMaterial.entries.forEach { put(it.name, SimpleItemMaterial(it)) } + BukkitMaterial.entries.forEach { put(it.name, SimpleMaterial(it)) } } } + /** + * 通过名称寻找 [BukkitMaterial] 形式的物品材料 + */ + fun findBukkit(name: String) = BukkitMaterial.getMaterial(name) + + /** + * 通过标识符寻找 [BukkitMaterial] 形式的物品材料 + */ + fun findBukkit(id: Int) = BukkitMaterial.entries.find { it.unsafeId == id } + + /** + * 将 [ItemMaterial] 转换为 [BukkitMaterial] 形式 + */ + fun ItemMaterial.asBukkit(): BukkitMaterial = if (this is SimpleMaterial) this.ref else findBukkit(this.name) ?: BukkitMaterial.AIR + /** * 通过反射获取 [id], 因为 [BukkitMaterial] 不会获取老版物品的 [id] */ - fun getIdUnsafe(material: BukkitMaterial) = bukkitIdField.get(material) as Int + val BukkitMaterial.unsafeId get() = bukkitIdField.get(this) as Int /** * private final int id @@ -100,6 +102,4 @@ open class SimpleItemMaterial(private val ref: BukkitMaterial) : ItemMaterial { } -} - -typealias BukkitMaterial = org.bukkit.Material \ No newline at end of file +} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/OccupyNode.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleNode.kt similarity index 83% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/OccupyNode.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleNode.kt index ab2772dc..86b03815 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/OccupyNode.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/SimpleNode.kt @@ -3,12 +3,12 @@ package cn.fd.ratziel.module.item.impl import cn.fd.ratziel.module.item.api.ItemNode /** - * OccupyNode - [ItemNode] 实现 + * SimpleNode - [ItemNode] 实现 * * @author TheFloodDragon * @since 2024/3/16 11:53 */ -data class OccupyNode( +data class SimpleNode( override val name: String, override val parent: ItemNode ) : ItemNode { diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/action/ActionParser.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/action/ActionParser.kt index dc39bc26..40173c87 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/action/ActionParser.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/action/ActionParser.kt @@ -2,7 +2,7 @@ package cn.fd.ratziel.module.item.impl.action import cn.fd.ratziel.core.serialization.getBy import cn.fd.ratziel.core.serialization.toBasic -import cn.fd.ratziel.module.item.api.event.ItemResolveEvent +import cn.fd.ratziel.module.item.api.event.ItemResolvedEvent import cn.fd.ratziel.script.ScriptBlockBuilder import kotlinx.serialization.json.JsonObject import taboolib.common.platform.event.SubscribeEvent @@ -44,7 +44,7 @@ object ActionParser { } @SubscribeEvent - fun onResolvingFinished(event: ItemResolveEvent) { + fun onResolved(event: ItemResolvedEvent) { val element = event.result as? JsonObject ?: return // 获取原始动作 val raw = element.getBy(nodeNames.asIterable()) ?: return diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultGenerator.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultGenerator.kt new file mode 100644 index 00000000..0c5dc600 --- /dev/null +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultGenerator.kt @@ -0,0 +1,136 @@ +package cn.fd.ratziel.module.item.impl.builder + +import cn.fd.ratziel.core.Identifier +import cn.fd.ratziel.core.IdentifierImpl +import cn.fd.ratziel.core.element.Element +import cn.fd.ratziel.function.ArgumentContext +import cn.fd.ratziel.module.item.ItemElement +import cn.fd.ratziel.module.item.ItemRegistry +import cn.fd.ratziel.module.item.api.ItemData +import cn.fd.ratziel.module.item.api.NeoItem +import cn.fd.ratziel.module.item.api.builder.ItemGenerator +import cn.fd.ratziel.module.item.api.builder.ItemSerializer +import cn.fd.ratziel.module.item.api.event.ItemGenerateEvent +import cn.fd.ratziel.module.item.api.event.ItemResolvedEvent +import cn.fd.ratziel.module.item.impl.RatzielItem +import cn.fd.ratziel.module.item.impl.SimpleData +import kotlinx.coroutines.* +import kotlinx.coroutines.future.asCompletableFuture +import kotlinx.serialization.json.JsonElement +import taboolib.common.platform.function.severe +import java.util.concurrent.CompletableFuture + +/** + * DefaultItemGenerator + * + * @author TheFloodDragon + * @since 2024/4/13 17:34 + */ +class DefaultGenerator( + /** + * 原始物品配置 (元素) + */ + val origin: Element +) : ItemGenerator { + + /** + * 构建物品 + */ + override fun build(context: ArgumentContext) = buildAsync(SimpleData(), context) + + /** + * 异步生成物品 + * + * 注: 此处使用多线程进行 反序列化和应用数据 的操作 + * 因为 [ItemData.tag] 默认是使用一个线程安全的 [Map] + * 开发过程中也尽可能避免将其换成 非线程安全的 + * 同时由于 NBT数据 的处理 不再依赖原版的, 而是独立实现的 + * 所以通过 原版物品 转换到此的 [ItemData.tag] 也是线程安全的 + */ + fun buildAsync(data: ItemData, context: ArgumentContext): CompletableFuture { + // 获取物品唯一标识符 + val identifier = IdentifierImpl(origin.name) + + // 呼出开始生成的事件 + ItemGenerateEvent.Pre(identifier, this, context).call() + + // 解析元素 (同步) + val resolved = resolve(identifier, origin.property, context) + + // 获取序列化器列表 + val serializers = ItemRegistry.Serializer.getSerializers() + + // 处理最终结果 (异步) + return ItemElement.scope.async { + // 生成任务列表 + val tasks: List = serializers.map { createTask(this@async, it, resolved, data) } + // 等待所有任务完成 + tasks.joinAll() + // 合成最终结果 + val info = RatzielItem.Info(identifier, origin.property.hashCode()) + val item = RatzielItem(info, data) + // 呼出生成结束的事件 + val event = ItemGenerateEvent.Post(item.id, this@DefaultGenerator, item, context) + event.call() // 不确定这里在协程中呼出是否会出现问题 + event.item // 返回最终结果 + }.asCompletableFuture() + } + + /** + * 创建任务 + * 流程: 反序列化 -> 转化数据 (应用到 [sourceData]) + */ + fun createTask( + scope: CoroutineScope, + serializer: ItemSerializer<*>, + resolved: JsonElement, + sourceData: ItemData + ) = scope.launch { + // 反序列成物品组件 + val component = try { + serializer.deserialize(resolved) ?: return@launch + } catch (ex: Exception) { + severe("Failed to deserialize element by \"$serializer!\"! Target element: $resolved") + ex.printStackTrace() + return@launch + } + // 获取转化器 + val transformer = ItemRegistry.Component.getUnsafe(component::class.java) + if (transformer == null) { + severe("Transformer is not found for component \"$component\"!") + return@launch + } + try { + // 应用数据 + transformer.transform(sourceData, component) + } catch (ex: Exception) { + severe("Failed to transform component by \"$transformer\"! Target component: $component") + ex.printStackTrace() + } + } + + /** + * 物品解析实现部分 + * 结束后呼出事件 [ItemResolvedEvent] + */ + fun resolve(identifier: Identifier, element: JsonElement, context: ArgumentContext): JsonElement { + var result = element + // 解析器列表 (确保最后一个是默认解析器) + val resolvers = ItemRegistry.Resolver.getResolversSorted() + .plus(DefaultResolver) + // 使用解析器解析 + for (resolver in resolvers) { + try { + result = resolver.resolve(result, context) + } catch (ex: Exception) { + severe("Failed to resolve element by $resolver!") + ex.printStackTrace() + } + } + // 呼出事件 + ItemResolvedEvent(identifier, element).call() + // 返回结果 + return result + } + +} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemGenerator.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemGenerator.kt deleted file mode 100644 index 1e998c3d..00000000 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemGenerator.kt +++ /dev/null @@ -1,126 +0,0 @@ -package cn.fd.ratziel.module.item.impl.builder - -import cn.fd.ratziel.core.IdentifierImpl -import cn.fd.ratziel.core.Priority -import cn.fd.ratziel.core.element.Element -import cn.fd.ratziel.core.util.FutureFactory -import cn.fd.ratziel.core.util.sortPriority -import cn.fd.ratziel.function.ArgumentContext -import cn.fd.ratziel.function.uncheck -import cn.fd.ratziel.module.item.ItemElement -import cn.fd.ratziel.module.item.ItemRegistry -import cn.fd.ratziel.module.item.api.ItemData -import cn.fd.ratziel.module.item.api.NeoItem -import cn.fd.ratziel.module.item.api.builder.ItemGenerator -import cn.fd.ratziel.module.item.api.builder.ItemResolver -import cn.fd.ratziel.module.item.api.builder.ItemSerializer -import cn.fd.ratziel.module.item.api.builder.ItemTransformer -import cn.fd.ratziel.module.item.api.event.ItemGenerateEvent -import cn.fd.ratziel.module.item.api.event.ItemResolveEvent -import cn.fd.ratziel.module.item.impl.RatzielItem -import cn.fd.ratziel.module.item.impl.SimpleItemData -import kotlinx.serialization.json.JsonElement -import taboolib.common.platform.function.severe -import java.util.concurrent.CompletableFuture - -/** - * DefaultItemGenerator - * - * @author TheFloodDragon - * @since 2024/4/13 17:34 - */ -class DefaultItemGenerator( - /** - * 原始物品配置 (元素) - */ - val origin: Element -) : ItemGenerator { - - fun build(sourceData: ItemData, context: ArgumentContext): CompletableFuture { - // 生成物品唯一标识符 - val identifier = IdentifierImpl(origin.name) - - // PreEvent - ItemGenerateEvent.Pre(identifier, this, context).call() - - // Step1: Resolve (with priorities) - val element = resolve(origin.property, context, ItemRegistry.Resolver.getResolversSorted()) - // ResolvedEvent - ItemResolveEvent(identifier, element, context).call() - - // Step2: Serialize (async) - val serializeFactory = FutureFactory() - - // Step3: Transform (async) - val transformFactory = FutureFactory?>() - - // 遍历所有注册的序列化器 - for (serializer in ItemRegistry.Serializer.getSerializers()) { - // 创建序列化任务 (提交至serializeFactory) - val serializeTask = createSerializeTask(element, serializer).also { serializeFactory.submitTask(it) } // 提交序列化任务 - // 创建转换任务 (在序列化任务完成时执行) - createTransformTask(serializeTask).also { transformFactory.submitTask(it) } // 提交转换任务 - } - - // Step4: Merge all (sync 串行) - return transformFactory.thenApply { results -> - // 优先级排列 (优先级低的在前面) - for (data in results.mapNotNull { it }.sortPriority().reversed()) { - SimpleItemData.merge(sourceData, data, true) // 合并数据 - } - // 合成最终结果 - val info = RatzielItem.Info(identifier, origin.property.hashCode()) - val item = RatzielItem(info, sourceData) - // PostEvent - ItemGenerateEvent.Post(item.id, this, item, context) - .also { it.call() }.item - } - } - - override fun build(context: ArgumentContext) = build(SimpleItemData(), context) - - private fun resolve(element: JsonElement, context: ArgumentContext, resolvers: List): JsonElement { - var result = element - for (resolver in resolvers) { - try { - result = resolver.resolve(result, context) - } catch (ex: Exception) { - severe("Failed to resolve element by $resolver!") - ex.printStackTrace() - } - } - return result - } - - private fun createSerializeTask(element: JsonElement, serializer: ItemSerializer<*>): CompletableFuture = CompletableFuture.supplyAsync({ - try { - serializer.deserialize(element) - } catch (ex: Exception) { - severe("Failed to deserialize element by \"$serializer!\"! Target element: $element") - ex.printStackTrace(); null - } - }, ItemElement.executor) - - private fun createTransformTask(serializeTask: CompletableFuture): CompletableFuture?> = - serializeTask.thenApplyAsync({ component -> - // 若组件未空, 则不进行转换 - if (component == null) return@thenApplyAsync null - // 获取转换器 - val prt = ItemRegistry.Component.getPriority(component::class.java) // 用于传递优先级 - val transformer = prt?.value - if (transformer == null) { - severe("Cannot find transformer for component \"$component\"!") - return@thenApplyAsync null - } - // 转换成以顶级节点为根节点的数据 - try { - val data = SimpleItemData() - (uncheck>(transformer)).transform(data, component) - Priority(prt.priority, data) // 封装成优先级对象后传递给合并阶段 - } catch (ex: Exception) { - severe("Failed to transform component by \"$transformer\"! Target component: $component") - ex.printStackTrace(); null - } - }, ItemElement.executor) - -} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemResolver.kt deleted file mode 100644 index cfb4105e..00000000 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemResolver.kt +++ /dev/null @@ -1,19 +0,0 @@ -package cn.fd.ratziel.module.item.impl.builder - -import cn.fd.ratziel.function.ArgumentContext -import cn.fd.ratziel.module.item.api.builder.ItemResolver -import kotlinx.serialization.json.JsonElement - -/** - * DefaultItemResolver - * - * @author TheFloodDragon - * @since 2024/8/13 10:49 - */ -object DefaultItemResolver : ItemResolver { - - override fun resolve(element: JsonElement, context: ArgumentContext): JsonElement { - TODO("Not yet implemented") - } - -} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemSerializer.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemSerializer.kt deleted file mode 100644 index 66cde852..00000000 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultItemSerializer.kt +++ /dev/null @@ -1,57 +0,0 @@ -package cn.fd.ratziel.module.item.impl.builder - -import cn.fd.ratziel.core.serialization.baseJson -import cn.fd.ratziel.core.serialization.serializers.UUIDSerializer -import cn.fd.ratziel.module.item.api.ItemMaterial -import cn.fd.ratziel.module.item.api.builder.ItemSerializer -import cn.fd.ratziel.module.item.impl.component.HideFlag -import cn.fd.ratziel.module.item.impl.component.serializers.* -import cn.fd.ratziel.module.nbt.NBTData -import cn.fd.ratziel.module.nbt.NBTSerializer -import kotlinx.serialization.KSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.modules.SerializersModule -import kotlinx.serialization.modules.plus -import org.bukkit.attribute.Attribute -import org.bukkit.attribute.AttributeModifier -import org.bukkit.enchantments.Enchantment -import java.util.* - -/** - * DefaultItemSerializer - * - * @author TheFloodDragon - * @since 2024/8/15 12:30 - */ -object DefaultItemSerializer { - - val json = Json(baseJson) { - serializersModule += SerializersModule { - // Basic Serializers - contextual(UUID::class, UUIDSerializer) - // Common Serializers - contextual(NBTData::class, NBTSerializer) - contextual(ItemMaterial::class, ItemMaterialSerializer) - // Bukkit Serializers - contextual(Enchantment::class, EnchantmentSerializer) - contextual(HideFlag::class, HideFlagSerializer) - contextual(Attribute::class, AttributeSerializer) - contextual(AttributeModifier::class, AttributeModifierSerializer) - } - } - - /** - * 通过 [KSerializer] 创建一个 [ItemSerializer] - */ - fun createItemSerializer(serializer: KSerializer): ItemSerializer = DelegateItemSerializer(json, serializer) - - /** - * 托管 [KSerializer] 以实现 [ItemSerializer] - */ - private class DelegateItemSerializer(val json: Json, val serializer: KSerializer) : ItemSerializer, KSerializer by serializer { - override fun serialize(component: T) = json.encodeToJsonElement(serializer, component) - override fun deserialize(element: JsonElement) = json.decodeFromJsonElement(serializer, element) - } - -} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultResolver.kt similarity index 74% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemResolver.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultResolver.kt index b344616b..1dc85c3e 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultResolver.kt @@ -7,22 +7,22 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject /** - * CommonItemResolver + * NativeItemResolver * * @author TheFloodDragon * @since 2024/8/13 10:54 */ -object CommonItemResolver : ItemResolver { +object DefaultResolver : ItemResolver { /** - * [SectionItemResolver] 应该访问的节点 + * [SectionResolver] 应该访问的节点 */ - val visitNodes: Array get() = CommonItemSerializer.usedNodes + val visitNodes: Array get() = DefaultSerializer.usedNodes /** * 解析元素 * - * @return 解析完后, 返回值只包含 [visitNodes] 内的节点, 因此 [CommonItemResolver] 需要作为最后一个解析 + * @return 解析完后, 返回值只包含 [visitNodes] 内的节点, 因此 [DefaultResolver] 需要作为最后一个解析 */ override fun resolve(element: JsonElement, context: ArgumentContext): JsonElement { if (element !is JsonObject) return resolveBySection(element, context) @@ -35,7 +35,7 @@ object CommonItemResolver : ItemResolver { } fun resolveBySection(element: JsonElement, context: ArgumentContext): JsonElement { - return JsonHandler.mapPrimitives(element) { SectionItemResolver.resolve(it, context) } + return JsonHandler.mapPrimitives(element) { SectionResolver.resolve(it, context) } } } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemSerializer.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultSerializer.kt similarity index 50% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemSerializer.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultSerializer.kt index c85329d2..e504a7e9 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/CommonItemSerializer.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/DefaultSerializer.kt @@ -2,20 +2,27 @@ package cn.fd.ratziel.module.item.impl.builder -import cn.fd.ratziel.core.serialization.elementAlias -import cn.fd.ratziel.core.serialization.getBy -import cn.fd.ratziel.core.serialization.getElementNames -import cn.fd.ratziel.core.serialization.handle +import cn.fd.ratziel.core.serialization.* +import cn.fd.ratziel.core.serialization.serializers.UUIDSerializer import cn.fd.ratziel.module.item.ItemElement import cn.fd.ratziel.module.item.api.ItemMaterial import cn.fd.ratziel.module.item.api.builder.ItemKSerializer -import cn.fd.ratziel.module.item.impl.builder.DefaultItemSerializer.json +import cn.fd.ratziel.module.item.api.builder.ItemSerializer import cn.fd.ratziel.module.item.impl.component.* -import cn.fd.ratziel.module.item.impl.component.serializers.ItemMaterialSerializer +import cn.fd.ratziel.module.item.impl.component.serializers.* +import cn.fd.ratziel.module.nbt.NBTData +import cn.fd.ratziel.module.nbt.NBTSerializer import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.future.asCompletableFuture +import kotlinx.serialization.KSerializer import kotlinx.serialization.json.* +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.plus +import org.bukkit.attribute.Attribute +import org.bukkit.attribute.AttributeModifier +import org.bukkit.enchantments.Enchantment +import java.util.* /** * CommonItemSerializer @@ -23,7 +30,22 @@ import kotlinx.serialization.json.* * @author TheFloodDragon * @since 2024/4/4 19:58 */ -object CommonItemSerializer : ItemKSerializer { +object DefaultSerializer : ItemKSerializer { + + val json = Json(baseJson) { + serializersModule += SerializersModule { + // Basic Serializers + contextual(UUID::class, UUIDSerializer) + // Common Serializers + contextual(NBTData::class, NBTSerializer) + contextual(ItemMaterial::class, ItemMaterialSerializer) + // Bukkit Serializers + contextual(Enchantment::class, EnchantmentSerializer) + contextual(HideFlag::class, HideFlagSerializer) + contextual(Attribute::class, AttributeSerializer) + contextual(AttributeModifier::class, AttributeModifierSerializer) + } + } /** * 使用到的节点 @@ -49,17 +71,16 @@ object CommonItemSerializer : ItemKSerializer { override fun deserialize(element: JsonElement): ItemMetadata { // 结构化解析 if (isStructured(element)) return json.decodeFromJsonElement(ItemMetadata.serializer(), element) - val deferred = ItemElement.buildScope.async { + val deferred = ItemElement.scope.async { + // 获取材料 (需要优先获取) + val materialName = (element as? JsonObject)?.getBy(NODES_MATERIAL) + val material = if (materialName != null) json.decodeFromJsonElement(ItemMaterialSerializer, materialName) else ItemMaterial.EMPTY // 一般解析 val display = async { json.decodeFromJsonElement(ItemDisplay.serializer(), element) } val durability = async { json.decodeFromJsonElement(ItemDurability.serializer(), element) } val sundry = async { json.decodeFromJsonElement(ItemSundry.serializer(), element) } val characteristic = async { json.decodeFromJsonElement(ItemCharacteristic.serializer(), element) } - val material = async { - val name = (element as? JsonObject)?.getBy(NODES_MATERIAL) - if (name != null) json.decodeFromJsonElement(ItemMaterialSerializer, name) else ItemMaterial.EMPTY - } - ItemMetadata(material.await(), display.await(), durability.await(), sundry.await(), characteristic.await()) + ItemMetadata(material, display.await(), durability.await(), sundry.await(), characteristic.await()) } return deferred.asCompletableFuture().get() } @@ -69,23 +90,40 @@ object CommonItemSerializer : ItemKSerializer { */ override fun serialize(component: ItemMetadata) = forceStructured(json.encodeToJsonElement(ItemMetadata.serializer(), component)) + @Deprecated("Will be removed") val NODES_MATERIAL = ItemMetadata.serializer().descriptor.getElementNames(ItemMetadata::material.name) /** * 结构化解析 */ + @Deprecated("Will be removed") const val NODE_STRUCTURED = "structured" + @Deprecated("Will be removed") private fun isStructured(element: JsonElement): Boolean = try { element.jsonObject[NODE_STRUCTURED]!!.jsonPrimitive.boolean } catch (_: Exception) { false } + @Deprecated("Will be removed") private fun forceStructured(element: JsonElement): JsonElement = try { element.jsonObject.handle { put(NODE_STRUCTURED, JsonPrimitive(true)) } } catch (_: Exception) { element } + /** + * 通过 [KSerializer] 创建一个 [ItemSerializer] + */ + fun createItemSerializer(serializer: KSerializer): ItemSerializer = DelegateItemSerializer(DefaultSerializer.json, serializer) + + /** + * 托管 [KSerializer] 以实现 [ItemSerializer] + */ + private class DelegateItemSerializer(val json: Json, val serializer: KSerializer) : ItemSerializer, KSerializer by serializer { + override fun serialize(component: T) = json.encodeToJsonElement(serializer, component) + override fun deserialize(element: JsonElement) = json.decodeFromJsonElement(serializer, element) + } + } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionItemResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionResolver.kt similarity index 83% rename from project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionItemResolver.kt rename to project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionResolver.kt index 4c069bd4..d3bc951e 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionItemResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/SectionResolver.kt @@ -2,8 +2,10 @@ package cn.fd.ratziel.module.item.impl.builder import cn.fd.ratziel.core.util.splitNonEscaped import cn.fd.ratziel.function.ArgumentContext +import cn.fd.ratziel.function.argument.exception.ArgumentNotFoundException import cn.fd.ratziel.module.item.api.builder.ItemResolver import cn.fd.ratziel.module.item.api.builder.SectionTagResolver +import cn.fd.ratziel.module.item.impl.builder.provided.PapiResolver import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonPrimitive import taboolib.common.util.VariableReader @@ -15,13 +17,18 @@ import java.util.concurrent.CopyOnWriteArrayList * @author TheFloodDragon * @since 2024/8/13 14:42 */ -object SectionItemResolver : ItemResolver { +object SectionResolver : ItemResolver { /** * 标签解析器列表 */ val resolvers: MutableCollection = CopyOnWriteArrayList() + init { + // TODO Shit + resolvers.add(PapiResolver) + } + /** * 只解析字符串形式的 [JsonPrimitive] */ @@ -57,11 +64,21 @@ object SectionItemResolver : ItemResolver { // 获取名称 val name = split.firstOrNull() ?: return null // 获取解析器 - val resolver = matchResolver(name) + val resolver = matchResolver(name) ?: return null // 解析并返回 - return resolver?.resolve(split.drop(1), context) + return try { + resolver.resolve(split.drop(1), context) + } catch (_: ArgumentNotFoundException) { + null + } } + /** + * 匹配 [SectionTagResolver] + * @return 匹配不到时返回空 + */ + fun matchResolver(name: String): SectionTagResolver? = resolvers.find { it.names.contains(name) } + /** * 标签读取器 */ @@ -72,22 +89,4 @@ object SectionItemResolver : ItemResolver { */ const val TAG_ARG_SEPARATION = ":" - /** - * 检查字符串内是否包含标签 - */ - fun checkHasTag(str: String): Boolean { - for (part in reader.readToFlatten(str)) { - if (part.isVariable && - matchResolver(part.text.split(TAG_ARG_SEPARATION).first()) != null - ) return true - } - return false - } - - /** - * 匹配 [SectionTagResolver] - * @return 匹配不到时返回空 - */ - fun matchResolver(name: String): SectionTagResolver? = resolvers.find { it.names.contains(name) } - } \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/provided/PapiResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/provided/PapiResolver.kt new file mode 100644 index 00000000..bb405c3f --- /dev/null +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/provided/PapiResolver.kt @@ -0,0 +1,36 @@ +package cn.fd.ratziel.module.item.impl.builder.provided + +import cn.fd.ratziel.function.ArgumentContext +import cn.fd.ratziel.function.popOrNull +import cn.fd.ratziel.module.item.api.builder.SectionTagResolver +import org.bukkit.OfflinePlayer +import taboolib.common.platform.ProxyPlayer +import taboolib.platform.compat.replacePlaceholder + +/** + * PapiResolver + * + * @author TheFloodDragon + * @since 2024/8/16 19:26 + */ +object PapiResolver : SectionTagResolver { + + override val names = arrayOf("papi", "p") + + override fun resolve(element: List, context: ArgumentContext): String? { + // 获取玩家 + val player = player(context) ?: return null + // 读取内容 + val content = when { + element.size == 1 -> element.first() + element.size > 1 -> element.joinToString("_") + else -> return null + } + // 处理Papi变量 + return content.replacePlaceholder(player) + } + + fun player(context: ArgumentContext) = + context.popOrNull()?.cast() ?: context.popOrNull() + +} \ No newline at end of file diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/BasicItemResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/BasicItemResolver.kt index 9c7dba14..5a5c22f4 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/BasicItemResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/BasicItemResolver.kt @@ -8,7 +8,7 @@ import cn.fd.ratziel.core.util.sortPriority import cn.fd.ratziel.function.ArgumentContext import cn.fd.ratziel.module.item.api.builder.ItemResolver import cn.fd.ratziel.module.item.api.builder.SectionResolver -import cn.fd.ratziel.module.item.impl.builder.CommonItemSerializer +import cn.fd.ratziel.module.item.impl.builder.DefaultSerializer import cn.fd.ratziel.module.item.impl.builder.resolver.sectionResolvers.PapiResolver import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject @@ -27,7 +27,7 @@ object BasicItemResolver : ItemResolver { /** * 可通过的节点 (不在此的节点都会被过滤掉) */ - val accessibleNodes: MutableSet = CommonItemSerializer.usedNodes.toMutableSet() + val accessibleNodes: MutableSet = DefaultSerializer.usedNodes.toMutableSet() /** * 字符串解析器 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 a88968d4..c863a682 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 @@ -13,6 +13,7 @@ import taboolib.platform.compat.replacePlaceholder * @author TheFloodDragon * @since 2024/6/25 20:18 */ +@Deprecated("Will be removed") object PapiResolver : SectionResolver.StringResolver { override fun resolve(element: String, context: ArgumentContext): String { diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/RandomResolver.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/RandomResolver.kt index a7b423df..d67c2469 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/RandomResolver.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/builder/resolver/sectionResolvers/RandomResolver.kt @@ -10,6 +10,7 @@ import taboolib.common.util.random * @author TheFloodDragon * @since 2024/5/18 16:22 */ +@Deprecated("Will be removed") object RandomResolver : SectionResolver.TagResolver { override val names = arrayOf("random", "ran", "rd") diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemCharacteristic.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemCharacteristic.kt index 51ab5e2b..97ccd856 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemCharacteristic.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/impl/component/ItemCharacteristic.kt @@ -6,15 +6,15 @@ import cn.fd.ratziel.module.item.api.ItemData import cn.fd.ratziel.module.item.api.ItemMaterial import cn.fd.ratziel.module.item.api.builder.ItemTransformer import cn.fd.ratziel.module.item.impl.BukkitMaterial -import cn.fd.ratziel.module.item.impl.SimpleItemMaterial +import cn.fd.ratziel.module.item.impl.SimpleMaterial import cn.fd.ratziel.module.item.impl.component.util.SkullData import cn.fd.ratziel.module.item.impl.component.util.SkullUtil -import cn.fd.ratziel.module.nbt.NBTInt import cn.fd.ratziel.module.item.nms.ItemSheet import cn.fd.ratziel.module.item.nms.RefItemMeta import cn.fd.ratziel.module.item.nms.RefItemStack import cn.fd.ratziel.module.item.util.read import cn.fd.ratziel.module.item.util.write +import cn.fd.ratziel.module.nbt.NBTInt import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.Serializable import kotlinx.serialization.json.JsonNames @@ -44,13 +44,16 @@ data class ItemCharacteristic( companion object : ItemTransformer { + @JvmField + val PLAYER_HEAD: ItemMaterial = SimpleMaterial(BukkitMaterial.PLAYER_HEAD) + override fun transform(data: ItemData, component: ItemCharacteristic) { // 头颅处理 (当源数据的材料为空或者是PLAYER_HEAD时, 才处理相关) - if (data.material.isEmpty() || SimpleItemMaterial.equals(data.material, BukkitMaterial.PLAYER_HEAD)) { + if (data.material.isEmpty() || data.material == PLAYER_HEAD) { val skullTag = component.skull?.get()?.let { RefItemStack(it) }?.getTag() if (skullTag != null) { // 设置材质 - data.material = SimpleItemMaterial(BukkitMaterial.PLAYER_HEAD) + data.material = PLAYER_HEAD // 应用标签 data.tag.merge(skullTag, true) } diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/ItemSheet.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/ItemSheet.kt index 205e0967..0ff33b2e 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/ItemSheet.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/nms/ItemSheet.kt @@ -1,7 +1,7 @@ package cn.fd.ratziel.module.item.nms import cn.fd.ratziel.module.item.api.ItemNode -import cn.fd.ratziel.module.item.impl.OccupyNode +import cn.fd.ratziel.module.item.impl.SimpleNode import kotlinx.serialization.json.* import taboolib.common.io.runningResources import taboolib.module.nms.MinecraftVersion @@ -47,10 +47,10 @@ object ItemSheet { if (name.contains(".")) { var node = ItemNode.ROOT for (s in name.split(".")) { - node = OccupyNode(s, node) + node = SimpleNode(s, node) } node - } else OccupyNode(name, ItemNode.ROOT) + } else SimpleNode(name, ItemNode.ROOT) } /** 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 49549890..c55501e2 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 @@ -4,8 +4,9 @@ import cn.fd.ratziel.core.exception.UnsupportedTypeException import cn.fd.ratziel.module.item.api.ItemData import cn.fd.ratziel.module.item.api.ItemMaterial import cn.fd.ratziel.module.item.impl.BukkitMaterial -import cn.fd.ratziel.module.item.impl.SimpleItemData -import cn.fd.ratziel.module.item.impl.SimpleItemMaterial +import cn.fd.ratziel.module.item.impl.SimpleData +import cn.fd.ratziel.module.item.impl.SimpleMaterial +import cn.fd.ratziel.module.item.impl.SimpleMaterial.Companion.unsafeId import cn.fd.ratziel.module.nbt.NBTCompound import taboolib.library.reflex.Reflex.Companion.invokeConstructor import taboolib.library.reflex.Reflex.Companion.invokeMethod @@ -77,8 +78,8 @@ class RefItemStack(raw: Any) { * 获取物品数据 */ fun getData(): ItemData? { - return SimpleItemData( - material = SimpleItemMaterial(getMaterial()), + return SimpleData( + material = SimpleMaterial(getMaterial()), tag = getTag() ?: return null, amount = getAmount() ) @@ -100,7 +101,7 @@ class RefItemStack(raw: Any) { if (MinecraftVersion.isHigherOrEqual(MinecraftVersion.V1_13)) { InternalUtil.obcGetMaterialMethod.invoke(handle)!! as BukkitMaterial } else { - SimpleItemMaterial.getBukkitMaterial(InternalUtil.obcGetMaterialMethodLegacy.invoke(handle)!! as Int)!! + SimpleMaterial.findBukkit(InternalUtil.obcGetMaterialMethodLegacy.invoke(handle)!! as Int)!! } /** @@ -110,12 +111,12 @@ class RefItemStack(raw: Any) { if (MinecraftVersion.isHigherOrEqual(MinecraftVersion.V1_13)) { InternalUtil.obcSetMaterialMethod.invoke(handle, material) } else { - InternalUtil.obcSetMaterialMethodLegacy.invoke(handle, SimpleItemMaterial.getIdUnsafe(material)) + InternalUtil.obcSetMaterialMethodLegacy.invoke(handle, material.unsafeId) } } fun setMaterial(material: ItemMaterial) { - SimpleItemMaterial.getBukkitMaterial(material.name)?.let { setMaterial(it) } + SimpleMaterial.findBukkit(material.name)?.let { setMaterial(it) } } /** diff --git a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/util/MetaMatcher.kt b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/util/MetaMatcher.kt index 7f54df3f..5732d32a 100644 --- a/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/util/MetaMatcher.kt +++ b/project/module-item/src/main/kotlin/cn/fd/ratziel/module/item/util/MetaMatcher.kt @@ -4,7 +4,7 @@ package cn.fd.ratziel.module.item.util import cn.fd.ratziel.module.item.api.ItemMaterial import cn.fd.ratziel.module.item.impl.BukkitMaterial -import cn.fd.ratziel.module.item.impl.SimpleItemMaterial +import cn.fd.ratziel.module.item.impl.SimpleMaterial import cn.fd.ratziel.module.item.impl.component.HideFlag import org.bukkit.attribute.Attribute import org.bukkit.attribute.AttributeModifier @@ -97,8 +97,8 @@ object MetaMatcher { val exactName: String? = BukkitMaterial.getMaterial(name)?.name // BukkitMaterial Match ?: XMaterial.matchXMaterial(name).getOrNull()?.name // XMaterial Match - return if (exactName != null) SimpleItemMaterial(exactName) - else SimpleItemMaterial.materialsMap.maxBy { Strings.similarDegree(it.key, source) }.value // Similar + return if (exactName != null) SimpleMaterial(exactName) + else SimpleMaterial.materialsMap.maxBy { Strings.similarDegree(it.key, source) }.value // Similar } private fun clean(source: String): String = source.uppercase().replace(" ", "_").replace('-', '_')