Skip to content

Commit

Permalink
Experimental | Update ItemGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFloodDragon committed Jun 24, 2024
1 parent 4a2e5cb commit 4fbd600
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ object ItemElement : ElementHandler {

override fun handle(element: Element) {

val generator = DefaultItemGenerator(element)

val item = generator.build().get()
val item = DefaultItemGenerator.build(element).get()

println(item.data)

Expand All @@ -55,7 +53,7 @@ object ItemElement : ElementHandler {
println(test.getData())

// 注册
ItemManager.registry[element.name] = generator
ItemManager.registry[element.name] = DefaultItemGenerator
}

@SubscribeEvent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cn.fd.ratziel.module.item.api.builder

import cn.fd.ratziel.core.element.Element
import cn.fd.ratziel.function.argument.ArgumentFactory
import cn.fd.ratziel.function.argument.DefaultArgumentFactory
import cn.fd.ratziel.module.item.api.NeoItem
Expand All @@ -17,12 +18,12 @@ interface ItemGenerator {
* 构建物品
* @return [CompletableFuture] - [NeoItem]
*/
fun build(): CompletableFuture<out NeoItem> = build(DefaultArgumentFactory())
fun build(origin: Element): CompletableFuture<out NeoItem> = build(origin, DefaultArgumentFactory())

/**
* 构建物品 (带参数)
* @return [CompletableFuture] - [NeoItem]
*/
fun build(arguments: ArgumentFactory): CompletableFuture<out NeoItem>
fun build(origin: Element, arguments: ArgumentFactory): CompletableFuture<out NeoItem>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cn.fd.ratziel.module.item.impl.builder

import cn.fd.ratziel.module.item.api.ItemData
import cn.fd.ratziel.module.item.api.ItemNode
import cn.fd.ratziel.module.item.api.ItemTransformer
import cn.fd.ratziel.module.item.impl.TheItemData
import cn.fd.ratziel.module.item.nbt.NBTCompound
import cn.fd.ratziel.module.item.nbt.NBTData

/**
* ComponentUtil
*
* @author TheFloodDragon
* @since 2024/6/24 17:15
*/
object ComponentUtil {

/**
* 通过 [transformer] 将 [component] 转化成 [ItemData]
*/
fun <T> toData(component: T, transformer: ItemTransformer<T>): ItemData {
val data = transformer.transform(component) // 获取底层数据
val newTag = NBTCompound() // 创建新NBT
setByNode(newTag, transformer.node, data.tag) // 设置新NBT
return TheItemData(data.material, newTag, data.amount)
}

/**
* 通过 [transformer] 将 [data] 转化成 物品组件
*/
fun <T> toComponent(data: ItemData, transformer: ItemTransformer<T>): T {
val find = findByNode(data.tag, transformer.node)
return transformer.detransform(TheItemData(data.material, find, data.amount))
}

fun findByNode(source: NBTCompound, tailNode: ItemNode) = findByNode(source, fold(tailNode))

fun findByNode(source: NBTCompound, nodes: Iterable<ItemNode>): NBTCompound {
var find = source
for (node in nodes) {
find = find.computeIfAbsent(node.name) { NBTCompound() } as NBTCompound
}
return find
}

fun setByNode(source: NBTCompound, tailNode: ItemNode, data: NBTData) {
val node = tailNode.parent ?: return // 去掉最后一层节点, 若为尾节点顶级节点, 则直接返回
val find = findByNode(source, node) // 寻找节点
find[tailNode.name] = data // 设置最后一层
}

fun fold(tailNode: ItemNode) = buildList {
var node: ItemNode = tailNode
while (node.parent != null) {
add(node)
node = node.parent ?: break
}
}.reversed()

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ package cn.fd.ratziel.module.item.impl.builder

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.priority
import cn.fd.ratziel.core.util.sortPriority
import cn.fd.ratziel.function.argument.ArgumentFactory
import cn.fd.ratziel.module.item.ItemElement
import cn.fd.ratziel.module.item.api.ItemData
import cn.fd.ratziel.module.item.api.ItemTransformer
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.impl.RatzielItem
import cn.fd.ratziel.module.item.impl.TheItemData
import cn.fd.ratziel.module.item.impl.component.VItemDisplay
import cn.fd.ratziel.module.item.util.toApexDataUncheck
import taboolib.common.platform.function.severe
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CopyOnWriteArraySet

Expand All @@ -20,12 +26,7 @@ import java.util.concurrent.CopyOnWriteArraySet
* @author TheFloodDragon
* @since 2024/4/13 17:34
*/
class DefaultItemGenerator(
/**
* 原始物品配置 (元素)
*/
val origin: Element
) : ItemGenerator {
object DefaultItemGenerator : ItemGenerator {

/**
* 物品序列化器
Expand All @@ -44,7 +45,8 @@ class DefaultItemGenerator(
/**
* 物品转换器
*/
val transformers = CopyOnWriteArraySet<Priority<ItemTransformer<*>>>().apply {
val transformers = HashMap<Class<*>, Priority<ItemTransformer<*>>>().apply {
put(VItemDisplay::class.java, VItemDisplay.priority())
}

// /**
Expand Down Expand Up @@ -97,19 +99,47 @@ class DefaultItemGenerator(
// }
// }

fun build(data: ItemData, arguments: ArgumentFactory): CompletableFuture<RatzielItem> {
// // 解析成 JsonElement
// val element = resolve(origin.property, arguments)
// // 并行序列化并收集结果
// val serializeTask = serialize(element)
// // 合成最终产物
// return serializeTask.thenApply { components ->
// transform(data, components.mapNotNull { it })
// RatzielItem(data)
// }
TODO()
fun build(origin: Element, data: ItemData, arguments: ArgumentFactory): CompletableFuture<RatzielItem> {
var element = origin.property
// Resolve
for (resolver in resolvers.sortPriority()) {
try {
element = resolver.resolve(element, arguments)
} catch (ex: Exception) {
severe("Failed to resolve element by $resolver!")
ex.printStackTrace()
}
}
// S
val serializeFactory = FutureFactory<Any?>()
val transformFactory = FutureFactory<ItemData?>()

for (serializer in serializers) {
val serializeTask = serializeFactory.submitAsync(ItemElement.executor) {
try {
serializer.deserialize(element)
} catch (ex: Exception) {
severe("Failed to deserialize element by $serializer!")
ex.printStackTrace(); null
}
}
//
val transformTask = serializeTask.thenApply {
if (it == null) return@thenApply null
val transformer = (transformers[it::class.java] ?: return@thenApply null).value
transformer.toApexDataUncheck(it)
}
transformFactory.submitTask(transformTask)
}

return transformFactory.thenApply { list ->
list.forEach {
if (it != null) TheItemData.mergeShallow(data, it, true)
}
RatzielItem(data)
}
}

override fun build(arguments: ArgumentFactory) = build(TheItemData(), arguments)
override fun build(origin: Element, arguments: ArgumentFactory) = build(origin, TheItemData(), arguments)

}
Original file line number Diff line number Diff line change
@@ -1,72 +1,25 @@
@file:Suppress("NOTHING_TO_INLINE")

package cn.fd.ratziel.module.item.util

import cn.fd.ratziel.function.util.uncheck
import cn.fd.ratziel.module.item.api.ItemData
import cn.fd.ratziel.module.item.api.ItemNode
import cn.fd.ratziel.module.item.api.ItemTransformer
import cn.fd.ratziel.module.item.impl.TheItemData
import cn.fd.ratziel.module.item.nbt.NBTCompound
import cn.fd.ratziel.module.item.impl.builder.ComponentUtil
import cn.fd.ratziel.module.item.nbt.NBTData
import java.util.function.Consumer

fun <T> ItemTransformer<T>.toApexData(component: T): ItemData = ComponentUtil.toData(component, this)
inline fun <T> ItemTransformer<T>.toApexData(component: T): ItemData = ComponentUtil.toData(component, this)

fun <T> ItemTransformer<T>.toApexComponent(data: ItemData): T = ComponentUtil.toComponent(data, this)
inline fun <T> ItemTransformer<T>.toApexComponent(data: ItemData): T = ComponentUtil.toComponent(data, this)

/**
* 转换[NBTData], 若成功转换(不为空), 则执行 [action]
*/
inline fun <reified T : NBTData> NBTData?.castThen(action: Consumer<T>) = (this as? T)?.let { action.accept(it) }
inline fun ItemTransformer<*>.toApexDataUncheck(component: Any): ItemData = ComponentUtil.toData(component, uncheck(this))

inline fun <reified T : NBTData> ItemData?.castThen(node: String, action: Consumer<T>) = this?.tag?.get(node)?.castThen<T>(action)
inline fun ItemTransformer<*>.toApexComponentUncheck(data: ItemData): Any = ComponentUtil.toComponent(data, uncheck(this))

/**
* ComponentUtil
*
* @author TheFloodDragon
* @since 2024/5/18 08:15
* 转换[NBTData], 若成功转换(不为空), 则执行 [action]
*/
object ComponentUtil {

/**
* 通过 [transformer] 将 [component] 转化成 [ItemData]
*/
fun <T> toData(component: T, transformer: ItemTransformer<T>): ItemData {
val data = transformer.transform(component) // 获取底层数据
val newTag = NBTCompound() // 创建新NBT
setByNode(newTag, transformer.node, data.tag) // 设置新NBT
return TheItemData(data.material, newTag, data.amount)
}

/**
* 通过 [transformer] 将 [data] 转化成 物品组件
*/
fun <T> toComponent(data: ItemData, transformer: ItemTransformer<T>): T {
val find = findByNode(data.tag, transformer.node)
return transformer.detransform(TheItemData(data.material, find, data.amount))
}

fun findByNode(source: NBTCompound, tailNode: ItemNode) = findByNode(source, fold(tailNode))

fun findByNode(source: NBTCompound, nodes: Iterable<ItemNode>): NBTCompound {
var find = source
for (node in nodes) {
find = find.computeIfAbsent(node.name) { NBTCompound() } as NBTCompound
}
return find
}

fun setByNode(source: NBTCompound, tailNode: ItemNode, data: NBTData) {
val node = tailNode.parent ?: return // 去掉最后一层节点, 若为尾节点顶级节点, 则直接返回
val find = findByNode(source, node) // 寻找节点
find[tailNode.name] = data // 设置最后一层
}

fun fold(tailNode: ItemNode) = buildList {
var node: ItemNode = tailNode
while (node.parent != null) {
add(node)
node = node.parent ?: break
}
}.reversed()
inline fun <reified T : NBTData> NBTData?.castThen(action: Consumer<T>) = (this as? T)?.let { action.accept(it) }

}
inline fun <reified T : NBTData> ItemData?.castThen(node: String, action: Consumer<T>) = this?.tag?.get(node)?.castThen<T>(action)

0 comments on commit 4fbd600

Please sign in to comment.