Skip to content

Commit

Permalink
Merge pull request #30 from way-zer/server-fix
Browse files Browse the repository at this point in the history
修复一些bug
  • Loading branch information
way-zer authored May 7, 2023
2 parents 0d86b27 + c610b03 commit 181914d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 106 deletions.
31 changes: 10 additions & 21 deletions src/main/kotlin/cf/wayzer/contentsTweaker/PatchHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,39 +63,28 @@ object PatchHandler {
return "Node(key='$key')"
}

interface WithObj {
val obj: Any?
val type: Class<*>?
interface WithObj<T> {
val obj: T
val type: Class<*>
val elementType: Class<*>? get() = null
val keyType: Class<*>? get() = null
}

//Node with obj, not Modifiable, use as simple node
class ObjNode(override val parent: Node, key: String, override val obj: Any, override val type: Class<out Any> = obj.javaClass) :
Node(key), WithObj
class ObjNode<T : Any>(override val parent: Node, key: String, override val obj: T, override val type: Class<T> = obj.javaClass) :
Node(key), WithObj<T>

interface Storable {
val storeDepth: Int
fun doSave()
fun doRecover()
}

interface Modifiable : WithObj, Storable {
// /**
// * 可直接修改[obj]对象.通过其他机制可保证还原
// * true时: [doStore0]负责拷贝对象,并保存,由[recover]负责恢复
// * false时: 由[Modifier]负责产生新对象并[setValue]
// * */
// val mutableObj: Boolean get() = false
fun setValue(value: Any?)
// fun doStore() {
// if (mutableObj) error("mutable Modifiable need impl doStore0 to backup obj")
// }
//
// fun recover() {
// if (mutableObj) error("mutable Modifiable need impl recover to recover obj")
// setValue(obj)
// }
interface Modifiable<T> : WithObj<T>, Storable {
fun setValue(value: T)

@Suppress("UNCHECKED_CAST")
fun setValueAny(value: Any?) = setValue(type.cast(value) as T)
}

fun interface Modifier {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import cf.wayzer.contentsTweaker.TypeRegistry
object BaseModifier : PatchHandler.Resolver {
override fun resolve(node: Node, child: String): Node? {
if (child != "=") return null
if (node !is Node.Modifiable) error("${node.key} is not Modifiable, can't assign")
if (node !is Node.Modifiable<*>) error("${node.key} is not Modifiable, can't assign")
return node.withModifier(child) { json ->
val value = TypeRegistry.resolveType(json, type, elementType, keyType)
beforeModify()
setValue(value)
setValueAny(value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,55 +11,54 @@ import mindustry.world.consumers.*

object BlockConsumesResolver : PatchHandler.Resolver, TypeRegistry.Resolver {
override fun resolve(node: Node, child: String): Node? {
if (node is Node.Modifiable && node.obj is Array<*> && node.elementType == Consume::class.java) {
val block = ((node.parent as Node.WithObj).obj as? Block) ?: return null
fun modifier(body: Array<Consume>.(JsonValue) -> Array<Consume>) = node.withModifier(child) {
beforeModify()
PatchHandler.registerAfterHandler(node.key) {
block.apply {
consPower = consumers.filterIsInstance<ConsumePower>().firstOrNull()
optionalConsumers = consumers.filter { it.optional && !it.ignore() }.toTypedArray()
nonOptionalConsumers = consumers.filter { !it.optional && !it.ignore() }.toTypedArray()
updateConsumers = consumers.filter { it.update && !it.ignore() }.toTypedArray()
hasConsumers = consumers.isNotEmpty()
itemFilter.fill(false)
liquidFilter.fill(false)
consumers.forEach { it.apply(this) }
setBars()
}
if (node !is Node.Modifiable<*> || !Array<Consume>::class.java.isAssignableFrom(node.type))
return null
val block = ((node.parent as Node.WithObj<*>).obj as? Block) ?: return null
fun modifier(body: Array<Consume>.(JsonValue) -> Array<Consume>) = node.withModifier(child) { v ->
beforeModify()
PatchHandler.registerAfterHandler(key) {
block.apply {
consPower = consumers.filterIsInstance<ConsumePower>().firstOrNull()
optionalConsumers = consumers.filter { it.optional && !it.ignore() }.toTypedArray()
nonOptionalConsumers = consumers.filter { !it.optional && !it.ignore() }.toTypedArray()
updateConsumers = consumers.filter { it.update && !it.ignore() }.toTypedArray()
hasConsumers = consumers.isNotEmpty()
itemFilter.fill(false)
liquidFilter.fill(false)
consumers.forEach { it.apply(this) }
setBars()
}
@Suppress("UNCHECKED_CAST") val obj = node.obj as Array<Consume>
setValue(obj.body(it))
}
return when (child) {
"clearItems" -> modifier { filterNot { it is ConsumeItems || it is ConsumeItemFilter }.toTypedArray() }
"item" -> modifier { this + ConsumeItems(arrayOf(ItemStack(TypeRegistry.resolve(it), 1))) }
"items" -> modifier { this + TypeRegistry.resolve<ConsumeItems>(it) }
"itemCharged" -> modifier { this + TypeRegistry.resolve<ConsumeItemCharged>(it) }
"itemFlammable" -> modifier { this + TypeRegistry.resolve<ConsumeItemFlammable>(it) }
"itemRadioactive" -> modifier { this + TypeRegistry.resolve<ConsumeItemRadioactive>(it) }
"itemExplosive" -> modifier { this + TypeRegistry.resolve<ConsumeItemExplosive>(it) }
"itemExplode" -> modifier { this + TypeRegistry.resolve<ConsumeItemExplode>(it) }

"clearLiquids" -> modifier { filterNot { it is ConsumeLiquidBase || it is ConsumeLiquids }.toTypedArray() }
"liquid" -> modifier { this + TypeRegistry.resolve<ConsumeLiquid>(it) }
"liquids" -> modifier { this + TypeRegistry.resolve<ConsumeLiquids>(it) }
"liquidFlammable" -> modifier { this + TypeRegistry.resolve<ConsumeLiquidFlammable>(it) }
"coolant" -> modifier { this + TypeRegistry.resolve<ConsumeCoolant>(it) }
@Suppress("UNCHECKED_CAST")
setValueAny((obj as Array<Consume>).body(v))
}
return when (child) {
"clearItems" -> modifier { filterNot { it is ConsumeItems || it is ConsumeItemFilter }.toTypedArray() }
"item" -> modifier { this + ConsumeItems(arrayOf(ItemStack(TypeRegistry.resolve(it), 1))) }
"items" -> modifier { this + TypeRegistry.resolve<ConsumeItems>(it) }
"itemCharged" -> modifier { this + TypeRegistry.resolve<ConsumeItemCharged>(it) }
"itemFlammable" -> modifier { this + TypeRegistry.resolve<ConsumeItemFlammable>(it) }
"itemRadioactive" -> modifier { this + TypeRegistry.resolve<ConsumeItemRadioactive>(it) }
"itemExplosive" -> modifier { this + TypeRegistry.resolve<ConsumeItemExplosive>(it) }
"itemExplode" -> modifier { this + TypeRegistry.resolve<ConsumeItemExplode>(it) }

"clearPower" -> modifier { filterNot { it is ConsumePower }.toTypedArray() }
"power" -> modifier {
this.filterNot { c -> c is ConsumePower }.toTypedArray() + TypeRegistry.resolve<ConsumePower>(it)
}
"clearLiquids" -> modifier { filterNot { it is ConsumeLiquidBase || it is ConsumeLiquids }.toTypedArray() }
"liquid" -> modifier { this + TypeRegistry.resolve<ConsumeLiquid>(it) }
"liquids" -> modifier { this + TypeRegistry.resolve<ConsumeLiquids>(it) }
"liquidFlammable" -> modifier { this + TypeRegistry.resolve<ConsumeLiquidFlammable>(it) }
"coolant" -> modifier { this + TypeRegistry.resolve<ConsumeCoolant>(it) }

"powerBuffered" -> modifier {
this.filterNot { c -> c is ConsumePower }.toTypedArray() + ConsumePower(0f, it.asFloat(), true)
}
"clearPower" -> modifier { filterNot { it is ConsumePower }.toTypedArray() }
"power" -> modifier {
this.filterNot { c -> c is ConsumePower }.toTypedArray() + TypeRegistry.resolve<ConsumePower>(it)
}

else -> null
"powerBuffered" -> modifier {
this.filterNot { c -> c is ConsumePower }.toTypedArray() + ConsumePower(0f, it.asFloat(), true)
}

else -> null
}
return null
}

override fun <T : Any> resolveType(json: JsonValue, type: Class<T>?, elementType: Class<*>?, keyType: Class<*>?): T? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import cf.wayzer.contentsTweaker.PatchHandler.Node
import cf.wayzer.contentsTweaker.PatchHandler.withModifier
import cf.wayzer.contentsTweaker.TypeRegistry

class ObjectMapItemNode(override val parent: Node, val mapKey: Any?, key: String) : Node(key), Node.Modifiable {
class ObjectMapItemNode(override val parent: Node, val mapKey: Any?, key: String) : Node(key), Node.Modifiable<Any?> {
@Suppress("UNCHECKED_CAST")
private val map = ((parent as WithObj).obj as ObjectMap<Any, Any>)
override val type: Class<*>?
get() = (parent as WithObj).elementType ?: obj?.javaClass
private val map = ((parent as WithObj<*>).obj as ObjectMap<Any, Any>)
override val type: Class<*>
get() = (parent as WithObj<*>).elementType ?: obj?.javaClass ?: Any::class.java

override fun setValue(value: Any?) {
map.put(mapKey, value)
Expand All @@ -36,7 +36,7 @@ class ObjectMapItemNode(override val parent: Node, val mapKey: Any?, key: String

companion object Resolver : PatchHandler.Resolver {
override fun resolve(node: Node, child: String): Node? {
if (node !is WithObj) return null
if (node !is WithObj<*>) return null
val obj = node.obj
if (obj !is ObjectMap<*, *>) return null
val keyType = node.keyType ?: (obj.keys().firstOrNull()?.javaClass)
Expand Down
22 changes: 13 additions & 9 deletions src/main/kotlin/cf/wayzer/contentsTweaker/resolvers/ReflectNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@ import cf.wayzer.contentsTweaker.PatchHandler.Node
import java.lang.reflect.Field


class ReflectNode(override val parent: Node, key: String, val field: Field) : Node(key), Node.Modifiable {
override val obj: Any = field.get((parent as WithObj).obj)
override val type: Class<out Any> get() = this.field.type
private val typeMeta: FieldMetadata by lazy { this.field.let(::FieldMetadata) }
class ReflectNode<T>(override val parent: Node, key: String, val f: Field) : Node(key), Node.Modifiable<T> {
@Suppress("UNCHECKED_CAST")
override val obj: T get() = f.get((parent as WithObj<*>).obj) as T

@Suppress("UNCHECKED_CAST")
override val type: Class<T> get() = this.f.type as Class<T>
private val typeMeta: FieldMetadata by lazy { this.f.let(::FieldMetadata) }
override val elementType: Class<*>? get() = typeMeta.elementType
override val keyType: Class<*>? get() = typeMeta.keyType

override val storeDepth: Int get() = 0
private val bak = obj
override fun doSave() {}//already
override fun doRecover() {
setValue(obj)
setValue(bak)
}

override fun setValue(value: Any?) {
field.set((parent as WithObj).obj, value)
override fun setValue(value: T) {
f.set((parent as WithObj<*>).obj, value)
}

companion object Resolver : PatchHandler.Resolver {
Expand All @@ -38,11 +42,11 @@ class ReflectNode(override val parent: Node, key: String, val field: Field) : No
}

override fun resolve(node: Node, child: String): Node? {
if (node !is WithObj) return null
if (node !is WithObj<*>) return null
val obj = node.obj ?: return null
val field = kotlin.runCatching { getField(obj, child) }
.getOrNull() ?: return null
return ReflectNode(node, node.subKey(child), field)
return ReflectNode<Any>(node, node.subKey(child), field)
}
}
}
42 changes: 19 additions & 23 deletions src/main/kotlin/cf/wayzer/contentsTweaker/resolvers/SeqResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@ import cf.wayzer.contentsTweaker.TypeRegistry
import mindustry.io.JsonIO

object SeqResolver : PatchHandler.Resolver {
class SeqItemNode(override val parent: Node, val index: Int, key: String) : Node(key), Node.Modifiable {
class SeqItemNode<T : Any>(override val parent: Node, val index: Int, key: String) : Node(key), Node.Modifiable<T> {
@Suppress("UNCHECKED_CAST")
private val seq = (parent as WithObj).obj as Seq<Any>

override val obj: Any? = seq.get(index)
override val type: Class<*>?
get() = (parent as WithObj).elementType ?: obj?.javaClass
private val seq = (parent as WithObj<*>).obj as Seq<T>
override val obj: T get() = seq.get(index)
override val type: Class<*> get() = ((parent as WithObj<*>).elementType ?: obj.javaClass)
override val storeDepth: Int get() = 0
private val bak = obj
override fun doSave() {}
override fun doRecover() = setValue(obj)
override fun doRecover() = setValue(bak)

override fun setValue(value: Any?) {
override fun setValue(value: T) {
seq.set(index, value)
}
}

class AsModifiable(override val parent: Node, override val obj: Seq<*>, val deepCopy: Boolean) : Node(parent.key), Node.Modifiable {
private lateinit var backup: Seq<*>
override val type: Class<*> = Seq::class.java
override val elementType: Class<*>? = (parent as WithObj).elementType ?: obj.firstOrNull()?.javaClass
class AsModifiable<T : Any>(override val parent: Node, override val obj: Seq<T>, val deepCopy: Boolean) : Node(parent.key), Node.Modifiable<Seq<T>> {
private lateinit var backup: Seq<T>
override val type: Class<Seq<*>> = Seq::class.java
override val elementType: Class<*>? = (parent as WithObj<*>).elementType ?: obj.firstOrNull()?.javaClass

override val storeDepth: Int get() = if (deepCopy) Int.MAX_VALUE else 0
override fun doSave() {
Expand All @@ -41,41 +40,38 @@ object SeqResolver : PatchHandler.Resolver {
setValue(backup)
}

override fun setValue(value: Any?) {
@Suppress("UNCHECKED_CAST")
val value2 = value as Seq<out Nothing>?
override fun setValue(value: Seq<T>) {
obj.clear()
if (value2 != null)
obj.addAll(value2)
obj.addAll(value)
}
}

override fun resolve(node: Node, child: String): Node? {
if (node !is Node.WithObj) return null
if (node !is Node.WithObj<*>) return null
val obj = node.obj
if (obj !is Seq<*>) return null
//通过数字索引
child.toIntOrNull()?.let { return SeqItemNode(node, it, node.subKey(child)) }
child.toIntOrNull()?.let { return SeqItemNode<Any>(node, it, node.subKey(child)) }
when (child) {
"+=" -> {
if (node !is Node.Modifiable) error("${node.key} is Seq<*>, but not Modifiable, try use `asModifiable`")
if (node !is Node.Modifiable<*>) error("${node.key} is Seq<*>, but not Modifiable, try use `asModifiable`")
return node.withModifier(child) { json ->
val value = TypeRegistry.resolve<Seq<Any>>(json, elementType)
beforeModify()
@Suppress("UNCHECKED_CAST")
setValue(obj.copy().addAll(value as Seq<out Nothing>))
setValueAny(obj.copy().addAll(value as Seq<out Nothing>))
}
}
//不支持-运算符,容易导致索引型的解析错误或者失败

"+" -> {
if (node !is Node.Modifiable) error("${node.key} is Seq<*>, but not Modifiable, try use `asModifiable`")
if (node !is Node.Modifiable<*>) error("${node.key} is Seq<*>, but not Modifiable, try use `asModifiable`")
return node.withModifier(child) { json ->
val value = TypeRegistry.resolveType(json, elementType)
beforeModify()
@Suppress("UNCHECKED_CAST")
val parentSeq = obj as Seq<Any>
setValue(parentSeq.copy().add(value))
setValueAny(parentSeq.copy().add(value))
}
}

Expand Down
10 changes: 6 additions & 4 deletions src/main/kotlin/cf/wayzer/contentsTweaker/resolvers/UIExtNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import arc.scene.ui.layout.Table
import arc.util.Align
import cf.wayzer.contentsTweaker.PatchHandler
import cf.wayzer.contentsTweaker.PatchHandler.withModifier
import mindustry.Vars
import mindustry.gen.Call
import mindustry.ui.Styles

Expand Down Expand Up @@ -50,7 +51,7 @@ import mindustry.ui.Styles
* }
* ```
*/
open class UIExtNode(override val parent: PatchHandler.Node, key: String, val uiNode: Element) : PatchHandler.Node(key), PatchHandler.Node.WithObj {
open class UIExtNode(override val parent: PatchHandler.Node, key: String, val uiNode: Element) : PatchHandler.Node(key), PatchHandler.Node.WithObj<Element> {
private var tableCell: Cell<Element>? = null
val children = mutableMapOf<String, UIExtNode>()
override val obj get() = uiNode
Expand Down Expand Up @@ -157,7 +158,7 @@ open class UIExtNode(override val parent: PatchHandler.Node, key: String, val ui
else -> null
}

object Root : UIExtNode(PatchHandler.Node.Root, "uiExt.", Core.scene.root), Storable {
object Root : UIExtNode(PatchHandler.Node.Root, "uiExt.", Core.scene.root ?: Element()), Storable {
override val storeDepth: Int = Int.MAX_VALUE
override fun doSave() {}
override fun doRecover() {
Expand All @@ -167,15 +168,16 @@ open class UIExtNode(override val parent: PatchHandler.Node, key: String, val ui
}

companion object Resolver : PatchHandler.Resolver {
val alignMap = Align::class.java.declaredFields.associate { it.name to it.getInt(null) }
val stylesMap = Styles::class.java.declaredFields.associate { it.name to it.get(null)!! }
val alignMap by lazy { Align::class.java.declaredFields.associate { it.name to it.getInt(null) } }
val stylesMap by lazy { Styles::class.java.declaredFields.associate { it.name to it.get(null)!! } }
fun createUIElement(type: String): Element = when (type) {
"Table" -> Table()
"Label" -> Label("")
else -> error("TODO: not support Element: $type")
}

override fun resolve(node: PatchHandler.Node, child: String): PatchHandler.Node? {
if (Vars.headless) return null
if (node == PatchHandler.Node.Root && child == "uiExt") return Root
return null
}
Expand Down

0 comments on commit 181914d

Please sign in to comment.