Extract functions from updateaction

This commit is contained in:
DBotThePony 2022-11-11 00:47:42 +07:00
parent 00c02aab82
commit 1330fe6925
Signed by: DBot
GPG Key ID: DCC23B5715498507
5 changed files with 200 additions and 165 deletions

View File

@ -0,0 +1,90 @@
package ru.dbotthepony.mc.otm.matter
import com.google.common.collect.ImmutableList
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParseException
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.data.stream
class BoundMatterFunction<T : Number>(val function: MatterFunction, val value: T) {
fun apply(self: T): T {
return function.updateValue(self, value)
}
fun toJson(): JsonObject {
return JsonObject().also {
it["type"] = function.name
if (value is Int || value is Double)
it["value"] = value
else
it["value"] = value.toString()
}
}
companion object {
inline fun <reified T : Number> getValue(value: JsonElement): T {
return when (T::class) {
ImpreciseFraction::class -> ImpreciseFraction(value.asString) as T
Double::class -> value.asDouble as T
Int::class -> value.asInt as T
else -> throw RuntimeException("Unknown number type: ${T::class.qualifiedName}")
}
}
inline fun <reified T : Number> deserializeFunctionTree(input: JsonElement?, name: String): List<BoundMatterFunction<T>> {
if (input == null) {
return listOf()
}
if (input !is JsonArray) {
throw JsonParseException("Expected $name to be JsonArray, ${input::class.qualifiedName} given")
}
return input.stream().map {
if (it !is JsonObject) {
throw JsonParseException("All elements in function tree must be JsonObjects, ${it::class.qualifiedName} given")
}
val type = it["type"]?.asString ?: throw JsonParseException("Invalid `type` value in function object")
val value = it["value"] ?: throw JsonParseException("Missing `value` value in function object")
val parsedValue: T = getValue(value)
val fn: MatterFunction
try {
fn = MatterFunction.valueOf(type.uppercase())
} catch (err: NoSuchElementException) {
throw JsonParseException("No such function: $type", err)
}
return@map BoundMatterFunction(fn, parsedValue)
}.collect(ImmutableList.toImmutableList())
}
fun <T : Number> apply(value: T, funcs: Collection<BoundMatterFunction<T>>): T {
if (funcs.isEmpty()) {
return value
}
var newValue = value
for (func in funcs) {
newValue = func.apply(newValue)
}
return newValue
}
fun <T : Number> apply(funcs: Collection<BoundMatterFunction<T>>, value: T): T {
return apply(value, funcs)
}
}
}
fun <T : Number> Collection<BoundMatterFunction<T>>.apply(value: T): T {
return BoundMatterFunction.apply(this, value)
}

View File

@ -112,24 +112,24 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
}
class UpdateConfiguration(name: ResourceLocation) : Configuration(name) {
val matterFunctions = ArrayList<UpdateAction.BoundFunction<ImpreciseFraction>>()
val complexityFunctions = ArrayList<UpdateAction.BoundFunction<Double>>()
val priorityFunctions = ArrayList<UpdateAction.BoundFunction<Int>>()
val matterFunctions = ArrayList<BoundMatterFunction<ImpreciseFraction>>()
val complexityFunctions = ArrayList<BoundMatterFunction<Double>>()
val priorityFunctions = ArrayList<BoundMatterFunction<Int>>()
fun addMatterFunction(function: UpdateAction.Function, value: ImpreciseFraction): UpdateConfiguration {
matterFunctions.add(UpdateAction.BoundFunction(function, value))
fun addMatterFunction(function: MatterFunction, value: ImpreciseFraction): UpdateConfiguration {
matterFunctions.add(BoundMatterFunction(function, value))
matter = null
return this
}
fun addComplexityFunction(function: UpdateAction.Function, value: Double): UpdateConfiguration {
complexityFunctions.add(UpdateAction.BoundFunction(function, value))
fun addComplexityFunction(function: MatterFunction, value: Double): UpdateConfiguration {
complexityFunctions.add(BoundMatterFunction(function, value))
matter = null
return this
}
fun addPriorityFunction(function: UpdateAction.Function, value: Int): UpdateConfiguration {
priorityFunctions.add(UpdateAction.BoundFunction(function, value))
fun addPriorityFunction(function: MatterFunction, value: Int): UpdateConfiguration {
priorityFunctions.add(BoundMatterFunction(function, value))
matter = null
return this
}

View File

@ -0,0 +1,76 @@
package ru.dbotthepony.mc.otm.matter
import com.google.gson.JsonParseException
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.integerDivisionDown
import ru.dbotthepony.mc.otm.core.integerDivisionUp
enum class MatterFunction {
ADD {
override fun updateValue(self: Int, other: Int): Int = self + other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self + other
override fun updateValue(self: Double, other: Double): Double = self + other
},
SUBTRACT {
override fun updateValue(self: Int, other: Int): Int = self - other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self - other
override fun updateValue(self: Double, other: Double): Double = self - other
},
MULTIPLY {
override fun updateValue(self: Int, other: Int): Int = self * other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self * other
override fun updateValue(self: Double, other: Double): Double = self * other
},
DIVIDE {
override fun updateValue(self: Int, other: Int): Int = self / other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self / other
override fun updateValue(self: Double, other: Double): Double = self / other
},
DIVIDE_UP {
override fun updateValue(self: Int, other: Int): Int = integerDivisionUp(self, other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = throw JsonParseException(
"Integer division up is available only for integers"
)
override fun updateValue(self: Double, other: Double): Double = throw JsonParseException(
"Integer division up is available only for integers"
)
},
DIVIDE_DOWN {
override fun updateValue(self: Int, other: Int): Int = integerDivisionDown(self, other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = throw JsonParseException(
"Integer division down is available only for integers"
)
override fun updateValue(self: Double, other: Double): Double = throw JsonParseException(
"Integer division down is available only for integers"
)
},
MODULO {
override fun updateValue(self: Int, other: Int): Int = self % other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self % other
override fun updateValue(self: Double, other: Double): Double = self % other
},
AT_LEAST {
override fun updateValue(self: Int, other: Int): Int = self.coerceAtLeast(other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self.coerceAtLeast(other)
override fun updateValue(self: Double, other: Double): Double = self.coerceAtLeast(other)
},
AT_MOST {
override fun updateValue(self: Int, other: Int): Int = self.coerceAtMost(other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self.coerceAtMost(other)
override fun updateValue(self: Double, other: Double): Double = self.coerceAtMost(other)
},
;
protected abstract fun updateValue(self: Int, other: Int): Int
protected abstract fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction
protected abstract fun updateValue(self: Double, other: Double): Double
fun <T : Number> updateValue(self: T, other: T): T {
return when (self) {
is ImpreciseFraction -> updateValue(self, other)
is Double -> updateValue(self, other)
is Int -> updateValue(self, other)
else -> throw RuntimeException("Unknown number type: ${self::class.qualifiedName}")
}
}
}

View File

@ -113,6 +113,18 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
private val computedEntries = Reference2ObjectOpenHashMap<Item, Entry>()
val computedEntriesView: Map<Item, Entry> = Collections.unmodifiableMap(computedEntries)
fun searchKeyEntry(index: ResourceLocation): KeyEntry? {
return keyEntries[index]
}
fun searchTagEntry(index: ResourceLocation): TagEntry? {
return tagEntries.firstOrNull { it.tag.location == index }
}
fun searchTagEntry(index: TagKey<Item>): TagEntry? {
return tagEntries.firstOrNull { it.tag == index }
}
private fun doGetDirectInner(value: Item): Entry? {
val key = value.registryName ?: throw NullPointerException("$value has no registry name!")

View File

@ -9,157 +9,14 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.TagKey
import net.minecraft.world.item.Item
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.integerDivisionDown
import ru.dbotthepony.mc.otm.core.integerDivisionUp
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.data.stream
import ru.dbotthepony.mc.otm.matter.BoundMatterFunction.Companion.deserializeFunctionTree
class UpdateAction : AbstractRegistryAction {
enum class Function {
ADD {
override fun updateValue(self: Int, other: Int): Int = self + other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self + other
override fun updateValue(self: Double, other: Double): Double = self + other
},
SUBTRACT {
override fun updateValue(self: Int, other: Int): Int = self - other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self - other
override fun updateValue(self: Double, other: Double): Double = self - other
},
MULTIPLY {
override fun updateValue(self: Int, other: Int): Int = self * other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self * other
override fun updateValue(self: Double, other: Double): Double = self * other
},
DIVIDE {
override fun updateValue(self: Int, other: Int): Int = self / other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self / other
override fun updateValue(self: Double, other: Double): Double = self / other
},
DIVIDE_UP {
override fun updateValue(self: Int, other: Int): Int = integerDivisionUp(self, other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = throw JsonParseException(
"Integer division up is available only for integers"
)
override fun updateValue(self: Double, other: Double): Double = throw JsonParseException(
"Integer division up is available only for integers"
)
},
DIVIDE_DOWN {
override fun updateValue(self: Int, other: Int): Int = integerDivisionDown(self, other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = throw JsonParseException(
"Integer division down is available only for integers"
)
override fun updateValue(self: Double, other: Double): Double = throw JsonParseException(
"Integer division down is available only for integers"
)
},
MODULO {
override fun updateValue(self: Int, other: Int): Int = self % other
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self % other
override fun updateValue(self: Double, other: Double): Double = self % other
},
AT_LEAST {
override fun updateValue(self: Int, other: Int): Int = self.coerceAtLeast(other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self.coerceAtLeast(other)
override fun updateValue(self: Double, other: Double): Double = self.coerceAtLeast(other)
},
AT_MOST {
override fun updateValue(self: Int, other: Int): Int = self.coerceAtMost(other)
override fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction = self.coerceAtMost(other)
override fun updateValue(self: Double, other: Double): Double = self.coerceAtMost(other)
},
;
protected abstract fun updateValue(self: Int, other: Int): Int
protected abstract fun updateValue(self: ImpreciseFraction, other: ImpreciseFraction): ImpreciseFraction
protected abstract fun updateValue(self: Double, other: Double): Double
fun <T : Number> updateValue(self: T, other: T): T {
return when (self) {
is ImpreciseFraction -> updateValue(self, other)
is Double -> updateValue(self, other)
is Int -> updateValue(self, other)
else -> throw RuntimeException("Unknown number type: ${self::class.qualifiedName}")
}
}
}
class BoundFunction<T : Number>(val function: Function, val value: T) {
fun apply(self: T): T {
return function.updateValue(self, value)
}
fun toJson(): JsonObject {
return JsonObject().also {
it["type"] = function.name
if (value is Int || value is Double)
it["value"] = value
else
it["value"] = value.toString()
}
}
}
companion object {
inline fun <reified T : Number> getValue(value: JsonElement): T {
return when (T::class) {
ImpreciseFraction::class -> ImpreciseFraction(value.asString) as T
Double::class -> value.asDouble as T
Int::class -> value.asInt as T
else -> throw RuntimeException("Unknown number type: ${T::class.qualifiedName}")
}
}
inline fun <reified T : Number> deserializeFunctionTree(input: JsonElement?, name: String): List<BoundFunction<T>> {
if (input == null) {
return listOf()
}
if (input !is JsonArray) {
throw JsonParseException("Expected $name to be JsonArray, ${input::class.qualifiedName} given")
}
return input.stream().map {
if (it !is JsonObject) {
throw JsonParseException("All elements in function tree must be JsonObjects, ${it::class.qualifiedName} given")
}
val type = it["type"]?.asString ?: throw JsonParseException("Invalid `type` value in function object")
val value = it["value"] ?: throw JsonParseException("Missing `value` value in function object")
val parsedValue: T = getValue(value)
val fn: Function
try {
fn = Function.valueOf(type.uppercase())
} catch (err: NoSuchElementException) {
throw JsonParseException("No such function: $type", err)
}
return@map BoundFunction(fn, parsedValue)
}.collect(ImmutableList.toImmutableList())
}
fun <T : Number> apply(value: T, funcs: Collection<BoundFunction<T>>): T {
if (funcs.isEmpty()) {
return value
}
var newValue = value
for (func in funcs) {
newValue = func.apply(newValue)
}
return newValue
}
}
val matterFunctions: List<BoundFunction<ImpreciseFraction>>
val complexityFunctions: List<BoundFunction<Double>>
val priorityFunctions: List<BoundFunction<Int>>
val matterFunctions: List<BoundMatterFunction<ImpreciseFraction>>
val complexityFunctions: List<BoundMatterFunction<Double>>
val priorityFunctions: List<BoundMatterFunction<Int>>
constructor(json: JsonObject) : super(json) {
matterFunctions = deserializeFunctionTree(json["matter_functions"], "matter_functions")
@ -173,9 +30,9 @@ class UpdateAction : AbstractRegistryAction {
complexity: Double? = null,
priority: Int? = null,
errorOnFailure: Boolean = false,
matterFunctions: List<BoundFunction<ImpreciseFraction>> = ImmutableList.of(),
complexityFunctions: List<BoundFunction<Double>> = ImmutableList.of(),
priorityFunctions: List<BoundFunction<Int>> = ImmutableList.of(),
matterFunctions: List<BoundMatterFunction<ImpreciseFraction>> = ImmutableList.of(),
complexityFunctions: List<BoundMatterFunction<Double>> = ImmutableList.of(),
priorityFunctions: List<BoundMatterFunction<Int>> = ImmutableList.of(),
) : super(tag = tag, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
check(matter != null || complexity != null || priority != null || matterFunctions.isNotEmpty() || complexityFunctions.isNotEmpty() || priorityFunctions.isNotEmpty()) {
"Can't update existing entries without anything specified"
@ -192,9 +49,9 @@ class UpdateAction : AbstractRegistryAction {
complexity: Double? = null,
priority: Int? = null,
errorOnFailure: Boolean = false,
matterFunctions: List<BoundFunction<ImpreciseFraction>> = ImmutableList.of(),
complexityFunctions: List<BoundFunction<Double>> = ImmutableList.of(),
priorityFunctions: List<BoundFunction<Int>> = ImmutableList.of(),
matterFunctions: List<BoundMatterFunction<ImpreciseFraction>> = ImmutableList.of(),
complexityFunctions: List<BoundMatterFunction<Double>> = ImmutableList.of(),
priorityFunctions: List<BoundMatterFunction<Int>> = ImmutableList.of(),
) : super(key = key, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
check(matter != null || complexity != null || priority != null || matterFunctions.isNotEmpty() || complexityFunctions.isNotEmpty() || priorityFunctions.isNotEmpty()) {
"Can't update existing entries without anything specified"
@ -237,17 +94,17 @@ class UpdateAction : AbstractRegistryAction {
fun apply(value: MatterManager.MutableEntry, modifier: ResourceLocation) {
if (matterFunctions.isNotEmpty())
value.matter = apply(value.matter, matterFunctions)
value.matter = matterFunctions.apply(value.matter)
else if (matter != null)
value.matter = matter
if (complexityFunctions.isNotEmpty())
value.complexity = apply(value.complexity, complexityFunctions)
value.complexity = complexityFunctions.apply(value.complexity)
else if (complexity != null)
value.complexity = complexity
if (priorityFunctions.isNotEmpty())
value.priority = apply(value.priority, priorityFunctions)
value.priority = priorityFunctions.apply(value.priority)
else if (priority != null)
value.priority = priority