Slice and splice classes
This commit is contained in:
parent
b1bd0aa2b5
commit
11f876ab57
@ -11,7 +11,8 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
|||||||
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
import ru.dbotthepony.mc.otm.matter.IMatterItem
|
import ru.dbotthepony.mc.otm.matter.IMatterItem
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.matter.MatterManager
|
import ru.dbotthepony.mc.otm.matter.IMatterValue
|
||||||
|
import ru.dbotthepony.mc.otm.matter.MatterValue
|
||||||
|
|
||||||
class MatterDustItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(64)), IMatterItem {
|
class MatterDustItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(64)), IMatterItem {
|
||||||
private fun matter(stack: ItemStack): ImpreciseFraction {
|
private fun matter(stack: ItemStack): ImpreciseFraction {
|
||||||
@ -22,9 +23,9 @@ class MatterDustItem : Item(Properties().tab(OverdriveThatMatters.INSTANCE.CREAT
|
|||||||
stack.orCreateTag["matter"] = matter.serializeNBT()
|
stack.orCreateTag["matter"] = matter.serializeNBT()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMatterValue(stack: ItemStack): MatterManager.IMatterValue? {
|
override fun getMatterValue(stack: ItemStack): IMatterValue? {
|
||||||
val value = stack.tag?.get("matter") ?: return null
|
val value = stack.tag?.get("matter") ?: return null
|
||||||
return MatterManager.MatterValue(ImpreciseFraction.deserializeNBT(value), 0.0)
|
return MatterValue(ImpreciseFraction.deserializeNBT(value), 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canDecompose(stack: ItemStack) = false
|
override fun canDecompose(stack: ItemStack) = false
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.matter
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParseException
|
||||||
|
import com.google.gson.JsonPrimitive
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.tags.ItemTags
|
||||||
|
import net.minecraft.tags.TagKey
|
||||||
|
import net.minecraft.world.item.Item
|
||||||
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
|
||||||
|
sealed class AbstractRegistryAction {
|
||||||
|
sealed class Condition {
|
||||||
|
abstract fun test(): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class CombinedCondition(val conditions: Collection<Condition>) : Condition() {
|
||||||
|
override fun test(): Boolean {
|
||||||
|
return conditions.all { it.test() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val errorOnFailure: Boolean
|
||||||
|
val tag: TagKey<Item>?
|
||||||
|
val key: ResourceLocation?
|
||||||
|
val matter: ImpreciseFraction?
|
||||||
|
val complexity: Double?
|
||||||
|
val priority: Int?
|
||||||
|
|
||||||
|
constructor(json: JsonObject) {
|
||||||
|
errorOnFailure = json["error_on_failure"]?.asBoolean ?: false
|
||||||
|
priority = json["priority"]?.asInt
|
||||||
|
|
||||||
|
val id = json["id"]?.asString ?: throw JsonParseException("Missing `id` value")
|
||||||
|
|
||||||
|
if (id.startsWith("#")) {
|
||||||
|
if (id.startsWith("#:")) {
|
||||||
|
throw JsonSyntaxException("Invalid `id` value: $id")
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = ItemTags.create(
|
||||||
|
ResourceLocation.tryParse(id.substring(1)) ?: throw JsonSyntaxException("Invalid `id` value: $id")
|
||||||
|
)
|
||||||
|
key = null
|
||||||
|
} else {
|
||||||
|
key = ResourceLocation.tryParse(id) ?: throw JsonSyntaxException("Invalid `id` value: $id")
|
||||||
|
tag = null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
matter = json["matter"]?.asString?.let(::ImpreciseFraction)
|
||||||
|
|
||||||
|
if (matter != null && !matter.isPositive) {
|
||||||
|
throw JsonParseException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
} catch(err: NumberFormatException) {
|
||||||
|
throw JsonParseException("Invalid `matter` field: ${json["matter"]}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
complexity = json["complexity"]?.asString?.toDouble()
|
||||||
|
|
||||||
|
if (complexity != null && complexity <= 0.0) {
|
||||||
|
throw JsonParseException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
} catch(err: NumberFormatException) {
|
||||||
|
throw JsonParseException("Invalid `complexity` field: ${json["complexity"]}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
tag: TagKey<Item>,
|
||||||
|
matter: ImpreciseFraction?,
|
||||||
|
complexity: Double?,
|
||||||
|
priority: Int? = null,
|
||||||
|
errorOnFailure: Boolean = false
|
||||||
|
) {
|
||||||
|
this.tag = tag
|
||||||
|
this.key = null
|
||||||
|
this.matter = matter
|
||||||
|
this.complexity = complexity
|
||||||
|
this.priority = priority
|
||||||
|
this.errorOnFailure = errorOnFailure
|
||||||
|
|
||||||
|
if (matter != null && !matter.isPositive) {
|
||||||
|
throw IllegalArgumentException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complexity != null && complexity <= 0.0) {
|
||||||
|
throw IllegalArgumentException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
key: ResourceLocation,
|
||||||
|
matter: ImpreciseFraction?,
|
||||||
|
complexity: Double?,
|
||||||
|
priority: Int? = null,
|
||||||
|
errorOnFailure: Boolean = false
|
||||||
|
) {
|
||||||
|
this.tag = null
|
||||||
|
this.key = key
|
||||||
|
this.matter = matter
|
||||||
|
this.complexity = complexity
|
||||||
|
this.priority = priority
|
||||||
|
this.errorOnFailure = errorOnFailure
|
||||||
|
|
||||||
|
if (matter != null && !matter.isPositive) {
|
||||||
|
throw IllegalArgumentException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complexity != null && complexity <= 0.0) {
|
||||||
|
throw IllegalArgumentException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkConditions(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun update(registry: MutableCollection<MatterManager.MutableEntry>, modifier: ResourceLocation)
|
||||||
|
|
||||||
|
protected inline fun fail(reason: () -> String) {
|
||||||
|
if (errorOnFailure) {
|
||||||
|
throw JsonParseException(reason.invoke())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun toJson(): JsonObject {
|
||||||
|
return JsonObject().also {
|
||||||
|
if (key != null)
|
||||||
|
it["id"] = JsonPrimitive(key.toString())
|
||||||
|
else
|
||||||
|
it["id"] = JsonPrimitive("#${tag!!.location}")
|
||||||
|
|
||||||
|
if (priority != null)
|
||||||
|
it["priority"] = priority
|
||||||
|
|
||||||
|
if (matter != null)
|
||||||
|
it["matter"] = matter.toString()
|
||||||
|
|
||||||
|
if (complexity != null)
|
||||||
|
it["complexity"] = complexity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
src/main/kotlin/ru/dbotthepony/mc/otm/matter/DeleteAction.kt
Normal file
60
src/main/kotlin/ru/dbotthepony/mc/otm/matter/DeleteAction.kt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.matter
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.tags.TagKey
|
||||||
|
import net.minecraft.world.item.Item
|
||||||
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
|
||||||
|
class DeleteAction : AbstractRegistryAction {
|
||||||
|
constructor(
|
||||||
|
tag: TagKey<Item>,
|
||||||
|
errorOnFailure: Boolean = false,
|
||||||
|
) : super(tag = tag, errorOnFailure = errorOnFailure, matter = null, complexity = null)
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
key: ResourceLocation,
|
||||||
|
errorOnFailure: Boolean = false,
|
||||||
|
) : super(key = key, errorOnFailure = errorOnFailure, matter = null, complexity = null)
|
||||||
|
|
||||||
|
constructor(json: JsonObject) : super(json)
|
||||||
|
|
||||||
|
override fun toJson(): JsonObject {
|
||||||
|
return super.toJson().also {
|
||||||
|
it["action"] = "delete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(registry: MutableCollection<MatterManager.MutableEntry>, modifier: ResourceLocation) {
|
||||||
|
if (!checkConditions()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
check(matter == null) { "Delete action can't have matter value (for $modifier)" }
|
||||||
|
check(complexity == null) { "Delete action can't have complexity value (for $modifier)" }
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
val iterator = registry.iterator()
|
||||||
|
|
||||||
|
for (value in iterator) {
|
||||||
|
if (value is MatterManager.MutableKeyEntry && value.key == key) {
|
||||||
|
iterator.remove()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail { "Could not find matter value with key $key" }
|
||||||
|
} else {
|
||||||
|
val iterator = registry.iterator()
|
||||||
|
|
||||||
|
for (value in iterator) {
|
||||||
|
if (value is MatterManager.MutableTagEntry && value.tag == tag) {
|
||||||
|
iterator.remove()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail { "Could not find matter value with tag $tag" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.matter
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
|
|
||||||
interface IMatterItem {
|
interface IMatterItem {
|
||||||
fun getMatterValue(stack: ItemStack): MatterManager.IMatterValue?
|
fun getMatterValue(stack: ItemStack): IMatterValue?
|
||||||
fun hasMatterValue(stack: ItemStack) = getMatterValue(stack) != null
|
fun hasMatterValue(stack: ItemStack) = getMatterValue(stack) != null
|
||||||
fun canDecompose(stack: ItemStack): Boolean
|
fun canDecompose(stack: ItemStack): Boolean
|
||||||
}
|
}
|
||||||
|
43
src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt
Normal file
43
src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.matter
|
||||||
|
|
||||||
|
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
||||||
|
|
||||||
|
interface IMatterValue : Comparable<IMatterValue> {
|
||||||
|
val matter: ImpreciseFraction
|
||||||
|
val complexity: Double
|
||||||
|
|
||||||
|
val hasMatterValue: Boolean get() = matter.isPositive && complexity > 0.0
|
||||||
|
|
||||||
|
operator fun plus(other: IMatterValue): IMatterValue {
|
||||||
|
return MatterValue(matter + other.matter, complexity + other.complexity)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun minus(other: IMatterValue): IMatterValue {
|
||||||
|
return MatterValue(matter - other.matter, complexity - other.complexity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: IMatterValue): Int {
|
||||||
|
val matterComparison = matter.compareTo(other.matter)
|
||||||
|
|
||||||
|
if (matterComparison == 0) {
|
||||||
|
return complexity.compareTo(other.complexity)
|
||||||
|
}
|
||||||
|
|
||||||
|
return matterComparison
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZERO
|
||||||
|
*/
|
||||||
|
companion object : IMatterValue {
|
||||||
|
override val matter: ImpreciseFraction
|
||||||
|
get() = ImpreciseFraction.ZERO
|
||||||
|
override val complexity: Double
|
||||||
|
get() = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MatterValue(
|
||||||
|
override val matter: ImpreciseFraction,
|
||||||
|
override val complexity: Double
|
||||||
|
) : IMatterValue
|
161
src/main/kotlin/ru/dbotthepony/mc/otm/matter/InsertAction.kt
Normal file
161
src/main/kotlin/ru/dbotthepony/mc/otm/matter/InsertAction.kt
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package ru.dbotthepony.mc.otm.matter
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
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.probablyParallelStream
|
||||||
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
|
|
||||||
|
class InsertAction : AbstractRegistryAction {
|
||||||
|
val replaceIfExists: Boolean
|
||||||
|
val comparePriority: Boolean
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
key: ResourceLocation,
|
||||||
|
matter: ImpreciseFraction?,
|
||||||
|
complexity: Double?,
|
||||||
|
priority: Int? = null,
|
||||||
|
errorOnFailure: Boolean = false,
|
||||||
|
replaceIfExists: Boolean = false,
|
||||||
|
comparePriority: Boolean = true,
|
||||||
|
) : super(key = key, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
|
||||||
|
this.replaceIfExists = replaceIfExists
|
||||||
|
this.comparePriority = comparePriority
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
tag: TagKey<Item>,
|
||||||
|
matter: ImpreciseFraction?,
|
||||||
|
complexity: Double?,
|
||||||
|
priority: Int? = null,
|
||||||
|
errorOnFailure: Boolean = false,
|
||||||
|
replaceIfExists: Boolean = false,
|
||||||
|
comparePriority: Boolean = true,
|
||||||
|
) : super(tag = tag, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
|
||||||
|
this.replaceIfExists = replaceIfExists
|
||||||
|
this.comparePriority = comparePriority
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(json: JsonObject) : super(json) {
|
||||||
|
this.replaceIfExists = json["replace_if_exists"]?.asBoolean ?: false
|
||||||
|
this.comparePriority = json["compare_priority"]?.asBoolean ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJson(): JsonObject {
|
||||||
|
checkNotNull(matter) { "Missing matter value, which is required for insert action" }
|
||||||
|
checkNotNull(complexity) { "Missing complexity value, which is required for insert action" }
|
||||||
|
|
||||||
|
return super.toJson().also {
|
||||||
|
it["action"] = "insert"
|
||||||
|
it["replace_if_exists"] = replaceIfExists
|
||||||
|
it["compare_priority"] = comparePriority
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(registry: MutableCollection<MatterManager.MutableEntry>, modifier: ResourceLocation) {
|
||||||
|
checkNotNull(matter) { "Missing matter value, which is required for insert action (for $modifier)" }
|
||||||
|
checkNotNull(complexity) { "Missing complexity value, which is required for insert action (for $modifier)" }
|
||||||
|
|
||||||
|
check(!comparePriority || priority != null) { "If compare_priority is true then priority must not be null (for $modifier)" }
|
||||||
|
|
||||||
|
if (!checkConditions()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
if (replaceIfExists) {
|
||||||
|
// search & replace in parallel, if possible
|
||||||
|
val replaced = registry.probablyParallelStream().anyMatch {
|
||||||
|
if (it is MatterManager.MutableKeyEntry && it.key == key) {
|
||||||
|
if (!comparePriority || it.priority < priority!!) {
|
||||||
|
it.matter = matter
|
||||||
|
it.complexity = complexity
|
||||||
|
it.priority = priority ?: 0
|
||||||
|
it.modificationChain.clear()
|
||||||
|
it.modificationChain.add(modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@anyMatch true
|
||||||
|
} else {
|
||||||
|
return@anyMatch false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!replaced) {
|
||||||
|
registry.add(
|
||||||
|
MatterManager.MutableKeyEntry(
|
||||||
|
key,
|
||||||
|
mutableListOf(modifier),
|
||||||
|
matter,
|
||||||
|
complexity,
|
||||||
|
priority ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (registry.probablyParallelStream().anyMatch { it is MatterManager.MutableKeyEntry && it.key == key }) {
|
||||||
|
fail { "Value with key $key already exists" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.add(
|
||||||
|
MatterManager.MutableKeyEntry(
|
||||||
|
key,
|
||||||
|
mutableListOf(modifier),
|
||||||
|
matter,
|
||||||
|
complexity,
|
||||||
|
priority ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (replaceIfExists) {
|
||||||
|
// search & replace in parallel, if possible
|
||||||
|
val replaced = registry.probablyParallelStream().anyMatch {
|
||||||
|
if (it is MatterManager.MutableTagEntry && it.tag == tag) {
|
||||||
|
if (!comparePriority || it.priority < priority!!) {
|
||||||
|
it.matter = matter
|
||||||
|
it.complexity = complexity
|
||||||
|
it.priority = priority ?: 0
|
||||||
|
it.modificationChain.clear()
|
||||||
|
it.modificationChain.add(modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
return@anyMatch true
|
||||||
|
} else {
|
||||||
|
return@anyMatch false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!replaced) {
|
||||||
|
registry.add(
|
||||||
|
MatterManager.MutableTagEntry(
|
||||||
|
tag!!,
|
||||||
|
mutableListOf(modifier),
|
||||||
|
matter,
|
||||||
|
complexity,
|
||||||
|
priority ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (registry.probablyParallelStream().anyMatch { it is MatterManager.MutableTagEntry && it.tag == tag }) {
|
||||||
|
fail { "Value with tag $tag already exists" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.add(
|
||||||
|
MatterManager.MutableTagEntry(
|
||||||
|
tag!!,
|
||||||
|
mutableListOf(modifier),
|
||||||
|
matter,
|
||||||
|
complexity,
|
||||||
|
priority ?: 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
constructor(event: GatherDataEvent) : this(event.generator, event.modContainer.namespace)
|
constructor(event: GatherDataEvent) : this(event.generator, event.modContainer.namespace)
|
||||||
|
|
||||||
protected val pathProvider: DataGenerator.PathProvider = dataGenerator.createPathProvider(DataGenerator.Target.DATA_PACK, MatterManager.DIRECTORY)
|
protected val pathProvider: DataGenerator.PathProvider = dataGenerator.createPathProvider(DataGenerator.Target.DATA_PACK, MatterManager.DIRECTORY)
|
||||||
protected val actions = LinkedHashMap<ResourceLocation, MatterManager.AbstractRegistryAction>()
|
protected val actions = LinkedHashMap<ResourceLocation, AbstractRegistryAction>()
|
||||||
|
|
||||||
sealed class Configuration(val name: ResourceLocation) {
|
sealed class Configuration(val name: ResourceLocation) {
|
||||||
var errorOnFailure: Boolean = false
|
var errorOnFailure: Boolean = false
|
||||||
@ -54,20 +54,20 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
check(complexity == null || (complexity ?: throw ConcurrentModificationException()) >= 0.0) { "Invalid matter value: ${matter ?: throw ConcurrentModificationException()}" }
|
check(complexity == null || (complexity ?: throw ConcurrentModificationException()) >= 0.0) { "Invalid matter value: ${matter ?: throw ConcurrentModificationException()}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun build(): MatterManager.AbstractRegistryAction
|
abstract fun build(): AbstractRegistryAction
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsertConfiguration(name: ResourceLocation) : Configuration(name) {
|
class InsertConfiguration(name: ResourceLocation) : Configuration(name) {
|
||||||
var replaceIfExists: Boolean = false
|
var replaceIfExists: Boolean = false
|
||||||
var comparePriority: Boolean = false
|
var comparePriority: Boolean = false
|
||||||
|
|
||||||
override fun build(): MatterManager.InsertAction {
|
override fun build(): InsertAction {
|
||||||
checkKeyTag()
|
checkKeyTag()
|
||||||
checkMatterValues()
|
checkMatterValues()
|
||||||
check(matter != null && complexity != null) { "You must define both matter value and complexity for $name" }
|
check(matter != null && complexity != null) { "You must define both matter value and complexity for $name" }
|
||||||
|
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
return MatterManager.InsertAction(
|
return InsertAction(
|
||||||
key = key ?: throw ConcurrentModificationException(),
|
key = key ?: throw ConcurrentModificationException(),
|
||||||
matter = matter,
|
matter = matter,
|
||||||
complexity = complexity,
|
complexity = complexity,
|
||||||
@ -77,7 +77,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
comparePriority = comparePriority
|
comparePriority = comparePriority
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return MatterManager.InsertAction(
|
return InsertAction(
|
||||||
tag = tag ?: throw ConcurrentModificationException(),
|
tag = tag ?: throw ConcurrentModificationException(),
|
||||||
matter = matter,
|
matter = matter,
|
||||||
complexity = complexity,
|
complexity = complexity,
|
||||||
@ -91,19 +91,19 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DeleteConfiguration(name: ResourceLocation) : Configuration(name) {
|
class DeleteConfiguration(name: ResourceLocation) : Configuration(name) {
|
||||||
override fun build(): MatterManager.DeleteAction {
|
override fun build(): DeleteAction {
|
||||||
checkKeyTag()
|
checkKeyTag()
|
||||||
|
|
||||||
check(matter == null) { "Delete action can't have matter value" }
|
check(matter == null) { "Delete action can't have matter value" }
|
||||||
check(complexity == null) { "Delete action can't have complexity value" }
|
check(complexity == null) { "Delete action can't have complexity value" }
|
||||||
|
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
return MatterManager.DeleteAction(
|
return DeleteAction(
|
||||||
key = key ?: throw ConcurrentModificationException(),
|
key = key ?: throw ConcurrentModificationException(),
|
||||||
errorOnFailure = errorOnFailure,
|
errorOnFailure = errorOnFailure,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return MatterManager.DeleteAction(
|
return DeleteAction(
|
||||||
tag = tag ?: throw ConcurrentModificationException(),
|
tag = tag ?: throw ConcurrentModificationException(),
|
||||||
errorOnFailure = errorOnFailure,
|
errorOnFailure = errorOnFailure,
|
||||||
)
|
)
|
||||||
@ -112,29 +112,29 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UpdateConfiguration(name: ResourceLocation) : Configuration(name) {
|
class UpdateConfiguration(name: ResourceLocation) : Configuration(name) {
|
||||||
val matterFunctions = ArrayList<MatterManager.UpdateAction.BoundFunction<ImpreciseFraction>>()
|
val matterFunctions = ArrayList<UpdateAction.BoundFunction<ImpreciseFraction>>()
|
||||||
val complexityFunctions = ArrayList<MatterManager.UpdateAction.BoundFunction<Double>>()
|
val complexityFunctions = ArrayList<UpdateAction.BoundFunction<Double>>()
|
||||||
val priorityFunctions = ArrayList<MatterManager.UpdateAction.BoundFunction<Int>>()
|
val priorityFunctions = ArrayList<UpdateAction.BoundFunction<Int>>()
|
||||||
|
|
||||||
fun addMatterFunction(function: MatterManager.UpdateAction.Function, value: ImpreciseFraction): UpdateConfiguration {
|
fun addMatterFunction(function: UpdateAction.Function, value: ImpreciseFraction): UpdateConfiguration {
|
||||||
matterFunctions.add(MatterManager.UpdateAction.BoundFunction(function, value))
|
matterFunctions.add(UpdateAction.BoundFunction(function, value))
|
||||||
matter = null
|
matter = null
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addComplexityFunction(function: MatterManager.UpdateAction.Function, value: Double): UpdateConfiguration {
|
fun addComplexityFunction(function: UpdateAction.Function, value: Double): UpdateConfiguration {
|
||||||
complexityFunctions.add(MatterManager.UpdateAction.BoundFunction(function, value))
|
complexityFunctions.add(UpdateAction.BoundFunction(function, value))
|
||||||
matter = null
|
matter = null
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addPriorityFunction(function: MatterManager.UpdateAction.Function, value: Int): UpdateConfiguration {
|
fun addPriorityFunction(function: UpdateAction.Function, value: Int): UpdateConfiguration {
|
||||||
priorityFunctions.add(MatterManager.UpdateAction.BoundFunction(function, value))
|
priorityFunctions.add(UpdateAction.BoundFunction(function, value))
|
||||||
matter = null
|
matter = null
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): MatterManager.UpdateAction {
|
override fun build(): UpdateAction {
|
||||||
check(!(matterFunctions.isNotEmpty() && matter != null)) { "Can't have both matter value and matter value functions be defined at the same time" }
|
check(!(matterFunctions.isNotEmpty() && matter != null)) { "Can't have both matter value and matter value functions be defined at the same time" }
|
||||||
check(!(complexityFunctions.isNotEmpty() && complexity != null)) { "Can't have both complexity and complexity functions be defined at the same time" }
|
check(!(complexityFunctions.isNotEmpty() && complexity != null)) { "Can't have both complexity and complexity functions be defined at the same time" }
|
||||||
check(!(priorityFunctions.isNotEmpty() && priority != null)) { "Can't have both priority and priority functions be defined at the same time" }
|
check(!(priorityFunctions.isNotEmpty() && priority != null)) { "Can't have both priority and priority functions be defined at the same time" }
|
||||||
@ -149,7 +149,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
checkKeyTag()
|
checkKeyTag()
|
||||||
|
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
return MatterManager.UpdateAction(
|
return UpdateAction(
|
||||||
key = key ?: throw ConcurrentModificationException(),
|
key = key ?: throw ConcurrentModificationException(),
|
||||||
matter = matter,
|
matter = matter,
|
||||||
complexity = complexity,
|
complexity = complexity,
|
||||||
@ -160,7 +160,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
priorityFunctions = priorityFunctions
|
priorityFunctions = priorityFunctions
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return MatterManager.UpdateAction(
|
return UpdateAction(
|
||||||
tag = tag ?: throw ConcurrentModificationException(),
|
tag = tag ?: throw ConcurrentModificationException(),
|
||||||
matter = matter,
|
matter = matter,
|
||||||
complexity = complexity,
|
complexity = complexity,
|
||||||
@ -735,7 +735,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insert(name: ResourceLocation, configurator: InsertConfiguration.() -> Unit): MatterManager.InsertAction {
|
fun insert(name: ResourceLocation, configurator: InsertConfiguration.() -> Unit): InsertAction {
|
||||||
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
||||||
val config = InsertConfiguration(name)
|
val config = InsertConfiguration(name)
|
||||||
configurator.invoke(config)
|
configurator.invoke(config)
|
||||||
@ -744,7 +744,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
return built
|
return built
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(name: ResourceLocation, configurator: DeleteConfiguration.() -> Unit): MatterManager.DeleteAction {
|
fun delete(name: ResourceLocation, configurator: DeleteConfiguration.() -> Unit): DeleteAction {
|
||||||
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
||||||
val config = DeleteConfiguration(name)
|
val config = DeleteConfiguration(name)
|
||||||
configurator.invoke(config)
|
configurator.invoke(config)
|
||||||
@ -753,7 +753,7 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
return built
|
return built
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(name: ResourceLocation, configurator: UpdateConfiguration.() -> Unit): MatterManager.UpdateAction {
|
fun update(name: ResourceLocation, configurator: UpdateConfiguration.() -> Unit): UpdateAction {
|
||||||
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
check(!actions.containsKey(name)) { "Already has action with name $name" }
|
||||||
val config = UpdateConfiguration(name)
|
val config = UpdateConfiguration(name)
|
||||||
configurator.invoke(config)
|
configurator.invoke(config)
|
||||||
@ -774,42 +774,42 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insert(name: ItemLike, configurator: InsertConfiguration.() -> Unit): MatterManager.InsertAction {
|
fun insert(name: ItemLike, configurator: InsertConfiguration.() -> Unit): InsertAction {
|
||||||
return insert(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
return insert(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
||||||
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(name: ItemLike, configurator: DeleteConfiguration.() -> Unit): MatterManager.DeleteAction {
|
fun delete(name: ItemLike, configurator: DeleteConfiguration.() -> Unit): DeleteAction {
|
||||||
return delete(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
return delete(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
||||||
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(name: ItemLike, configurator: UpdateConfiguration.() -> Unit): MatterManager.UpdateAction {
|
fun update(name: ItemLike, configurator: UpdateConfiguration.() -> Unit): UpdateAction {
|
||||||
return update(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
return update(updateLocation(name.asItem().registryName ?: throw NullPointerException("${name.asItem()} does not have registry name!"), "item/")) {
|
||||||
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
key = name.asItem().registryName ?: throw ConcurrentModificationException()
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun insert(name: TagKey<Item>, configurator: InsertConfiguration.() -> Unit): MatterManager.InsertAction {
|
fun insert(name: TagKey<Item>, configurator: InsertConfiguration.() -> Unit): InsertAction {
|
||||||
return insert(updateLocation(name.location, "tag/")) {
|
return insert(updateLocation(name.location, "tag/")) {
|
||||||
tag = name
|
tag = name
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(name: TagKey<Item>, configurator: DeleteConfiguration.() -> Unit): MatterManager.DeleteAction {
|
fun delete(name: TagKey<Item>, configurator: DeleteConfiguration.() -> Unit): DeleteAction {
|
||||||
return delete(updateLocation(name.location, "tag/")) {
|
return delete(updateLocation(name.location, "tag/")) {
|
||||||
tag = name
|
tag = name
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(name: TagKey<Item>, configurator: UpdateConfiguration.() -> Unit): MatterManager.UpdateAction {
|
fun update(name: TagKey<Item>, configurator: UpdateConfiguration.() -> Unit): UpdateAction {
|
||||||
return update(updateLocation(name.location, "tag/")) {
|
return update(updateLocation(name.location, "tag/")) {
|
||||||
tag = name
|
tag = name
|
||||||
configurator.invoke(this)
|
configurator.invoke(this)
|
||||||
@ -886,8 +886,8 @@ open class MatterDataProvider(protected val dataGenerator: DataGenerator, val na
|
|||||||
*/
|
*/
|
||||||
protected open fun addActions() {}
|
protected open fun addActions() {}
|
||||||
|
|
||||||
protected val added = ArrayList<MatterManager.AbstractRegistryAction>()
|
protected val added = ArrayList<AbstractRegistryAction>()
|
||||||
val addedView: List<MatterManager.AbstractRegistryAction> = Collections.unmodifiableList(added)
|
val addedView: List<AbstractRegistryAction> = Collections.unmodifiableList(added)
|
||||||
|
|
||||||
final override fun run(output: CachedOutput) {
|
final override fun run(output: CachedOutput) {
|
||||||
addActions()
|
addActions()
|
||||||
|
@ -2,21 +2,16 @@ package ru.dbotthepony.mc.otm.matter
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.JsonArray
|
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import com.google.gson.JsonParseException
|
import com.google.gson.JsonParseException
|
||||||
import com.google.gson.JsonPrimitive
|
|
||||||
import com.google.gson.JsonSyntaxException
|
|
||||||
import com.mojang.blaze3d.platform.InputConstants
|
import com.mojang.blaze3d.platform.InputConstants
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectFunction
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
|
||||||
import net.minecraft.ChatFormatting
|
import net.minecraft.ChatFormatting
|
||||||
import net.minecraft.client.Minecraft
|
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.server.packs.resources.ResourceManager
|
import net.minecraft.server.packs.resources.ResourceManager
|
||||||
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener
|
||||||
import net.minecraft.tags.ItemTags
|
|
||||||
import net.minecraft.tags.TagKey
|
import net.minecraft.tags.TagKey
|
||||||
import net.minecraft.util.profiling.ProfilerFiller
|
import net.minecraft.util.profiling.ProfilerFiller
|
||||||
import net.minecraft.world.item.Item
|
import net.minecraft.world.item.Item
|
||||||
@ -36,14 +31,9 @@ import ru.dbotthepony.mc.otm.core.ImpreciseFraction
|
|||||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||||
import ru.dbotthepony.mc.otm.core.formatMatterFull
|
import ru.dbotthepony.mc.otm.core.formatMatterFull
|
||||||
import ru.dbotthepony.mc.otm.core.formatSiComponent
|
import ru.dbotthepony.mc.otm.core.formatSiComponent
|
||||||
import ru.dbotthepony.mc.otm.core.integerDivisionDown
|
|
||||||
import ru.dbotthepony.mc.otm.core.integerDivisionUp
|
|
||||||
import ru.dbotthepony.mc.otm.core.isZero
|
import ru.dbotthepony.mc.otm.core.isZero
|
||||||
import ru.dbotthepony.mc.otm.core.orNull
|
import ru.dbotthepony.mc.otm.core.orNull
|
||||||
import ru.dbotthepony.mc.otm.core.probablyParallelStream
|
|
||||||
import ru.dbotthepony.mc.otm.core.registryName
|
import ru.dbotthepony.mc.otm.core.registryName
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
|
||||||
import ru.dbotthepony.mc.otm.data.stream
|
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
@ -53,599 +43,6 @@ import kotlin.math.pow
|
|||||||
object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_matter") {
|
object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(), "otm_matter") {
|
||||||
const val DIRECTORY = "otm_matter"
|
const val DIRECTORY = "otm_matter"
|
||||||
|
|
||||||
sealed class AbstractRegistryAction {
|
|
||||||
sealed class Condition {
|
|
||||||
abstract fun test(): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
class CombinedCondition(val conditions: Collection<Condition>) : Condition() {
|
|
||||||
override fun test(): Boolean {
|
|
||||||
return conditions.all { it.test() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val errorOnFailure: Boolean
|
|
||||||
val tag: TagKey<Item>?
|
|
||||||
val key: ResourceLocation?
|
|
||||||
val matter: ImpreciseFraction?
|
|
||||||
val complexity: Double?
|
|
||||||
val priority: Int?
|
|
||||||
|
|
||||||
constructor(json: JsonObject) {
|
|
||||||
errorOnFailure = json["error_on_failure"]?.asBoolean ?: false
|
|
||||||
priority = json["priority"]?.asInt
|
|
||||||
|
|
||||||
val id = json["id"]?.asString ?: throw JsonParseException("Missing `id` value")
|
|
||||||
|
|
||||||
if (id.startsWith("#")) {
|
|
||||||
if (id.startsWith("#:")) {
|
|
||||||
throw JsonSyntaxException("Invalid `id` value: $id")
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = ItemTags.create(ResourceLocation.tryParse(id.substring(1)) ?: throw JsonSyntaxException("Invalid `id` value: $id"))
|
|
||||||
key = null
|
|
||||||
} else {
|
|
||||||
key = ResourceLocation.tryParse(id) ?: throw JsonSyntaxException("Invalid `id` value: $id")
|
|
||||||
tag = null
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
matter = json["matter"]?.asString?.let(::ImpreciseFraction)
|
|
||||||
|
|
||||||
if (matter != null && !matter.isPositive) {
|
|
||||||
throw JsonParseException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
} catch(err: NumberFormatException) {
|
|
||||||
throw JsonParseException("Invalid `matter` field: ${json["matter"]}", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
complexity = json["complexity"]?.asString?.toDouble()
|
|
||||||
|
|
||||||
if (complexity != null && complexity <= 0.0) {
|
|
||||||
throw JsonParseException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
} catch(err: NumberFormatException) {
|
|
||||||
throw JsonParseException("Invalid `complexity` field: ${json["complexity"]}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
tag: TagKey<Item>,
|
|
||||||
matter: ImpreciseFraction?,
|
|
||||||
complexity: Double?,
|
|
||||||
priority: Int? = null,
|
|
||||||
errorOnFailure: Boolean = false
|
|
||||||
) {
|
|
||||||
this.tag = tag
|
|
||||||
this.key = null
|
|
||||||
this.matter = matter
|
|
||||||
this.complexity = complexity
|
|
||||||
this.priority = priority
|
|
||||||
this.errorOnFailure = errorOnFailure
|
|
||||||
|
|
||||||
if (matter != null && !matter.isPositive) {
|
|
||||||
throw IllegalArgumentException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (complexity != null && complexity <= 0.0) {
|
|
||||||
throw IllegalArgumentException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
key: ResourceLocation,
|
|
||||||
matter: ImpreciseFraction?,
|
|
||||||
complexity: Double?,
|
|
||||||
priority: Int? = null,
|
|
||||||
errorOnFailure: Boolean = false
|
|
||||||
) {
|
|
||||||
this.tag = null
|
|
||||||
this.key = key
|
|
||||||
this.matter = matter
|
|
||||||
this.complexity = complexity
|
|
||||||
this.priority = priority
|
|
||||||
this.errorOnFailure = errorOnFailure
|
|
||||||
|
|
||||||
if (matter != null && !matter.isPositive) {
|
|
||||||
throw IllegalArgumentException("Can't have non-positive matter value. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (complexity != null && complexity <= 0.0) {
|
|
||||||
throw IllegalArgumentException("Can't have non-positive complexity. To remove an entry from registry please use 'delete' action instead.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkConditions(): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun update(registry: MutableCollection<MutableEntry>, modifier: ResourceLocation)
|
|
||||||
|
|
||||||
protected inline fun fail(reason: () -> String) {
|
|
||||||
if (errorOnFailure) {
|
|
||||||
throw JsonParseException(reason.invoke())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun toJson(): JsonObject {
|
|
||||||
return JsonObject().also {
|
|
||||||
if (key != null)
|
|
||||||
it["id"] = JsonPrimitive(key.toString())
|
|
||||||
else
|
|
||||||
it["id"] = JsonPrimitive("#${tag!!.location}")
|
|
||||||
|
|
||||||
if (priority != null)
|
|
||||||
it["priority"] = priority
|
|
||||||
|
|
||||||
if (matter != null)
|
|
||||||
it["matter"] = matter.toString()
|
|
||||||
|
|
||||||
if (complexity != null)
|
|
||||||
it["complexity"] = complexity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class InsertAction : AbstractRegistryAction {
|
|
||||||
val replaceIfExists: Boolean
|
|
||||||
val comparePriority: Boolean
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
key: ResourceLocation,
|
|
||||||
matter: ImpreciseFraction?,
|
|
||||||
complexity: Double?,
|
|
||||||
priority: Int? = null,
|
|
||||||
errorOnFailure: Boolean = false,
|
|
||||||
replaceIfExists: Boolean = false,
|
|
||||||
comparePriority: Boolean = true,
|
|
||||||
) : super(key = key, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
|
|
||||||
this.replaceIfExists = replaceIfExists
|
|
||||||
this.comparePriority = comparePriority
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
tag: TagKey<Item>,
|
|
||||||
matter: ImpreciseFraction?,
|
|
||||||
complexity: Double?,
|
|
||||||
priority: Int? = null,
|
|
||||||
errorOnFailure: Boolean = false,
|
|
||||||
replaceIfExists: Boolean = false,
|
|
||||||
comparePriority: Boolean = true,
|
|
||||||
) : super(tag = tag, matter = matter, complexity = complexity, priority = priority, errorOnFailure = errorOnFailure) {
|
|
||||||
this.replaceIfExists = replaceIfExists
|
|
||||||
this.comparePriority = comparePriority
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(json: JsonObject) : super(json) {
|
|
||||||
this.replaceIfExists = json["replace_if_exists"]?.asBoolean ?: false
|
|
||||||
this.comparePriority = json["compare_priority"]?.asBoolean ?: true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toJson(): JsonObject {
|
|
||||||
checkNotNull(matter) { "Missing matter value, which is required for insert action" }
|
|
||||||
checkNotNull(complexity) { "Missing complexity value, which is required for insert action" }
|
|
||||||
|
|
||||||
return super.toJson().also {
|
|
||||||
it["action"] = "insert"
|
|
||||||
it["replace_if_exists"] = replaceIfExists
|
|
||||||
it["compare_priority"] = comparePriority
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(registry: MutableCollection<MutableEntry>, modifier: ResourceLocation) {
|
|
||||||
checkNotNull(matter) { "Missing matter value, which is required for insert action (for $modifier)" }
|
|
||||||
checkNotNull(complexity) { "Missing complexity value, which is required for insert action (for $modifier)" }
|
|
||||||
|
|
||||||
check(!comparePriority || priority != null) { "If compare_priority is true then priority must not be null (for $modifier)" }
|
|
||||||
|
|
||||||
if (!checkConditions()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key != null) {
|
|
||||||
if (replaceIfExists) {
|
|
||||||
// search & replace in parallel, if possible
|
|
||||||
val replaced = registry.probablyParallelStream().anyMatch {
|
|
||||||
if (it is MutableKeyEntry && it.key == key) {
|
|
||||||
if (!comparePriority || it.priority < priority!!) {
|
|
||||||
it.matter = matter
|
|
||||||
it.complexity = complexity
|
|
||||||
it.priority = priority ?: 0
|
|
||||||
it.modificationChain.clear()
|
|
||||||
it.modificationChain.add(modifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
return@anyMatch true
|
|
||||||
} else {
|
|
||||||
return@anyMatch false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!replaced) {
|
|
||||||
registry.add(MutableKeyEntry(key, mutableListOf(modifier), matter, complexity, priority ?: 0))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (registry.probablyParallelStream().anyMatch { it is MutableKeyEntry && it.key == key }) {
|
|
||||||
fail { "Value with key $key already exists" }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.add(MutableKeyEntry(key, mutableListOf(modifier), matter, complexity, priority ?: 0))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (replaceIfExists) {
|
|
||||||
// search & replace in parallel, if possible
|
|
||||||
val replaced = registry.probablyParallelStream().anyMatch {
|
|
||||||
if (it is MutableTagEntry && it.tag == tag) {
|
|
||||||
if (!comparePriority || it.priority < priority!!) {
|
|
||||||
it.matter = matter
|
|
||||||
it.complexity = complexity
|
|
||||||
it.priority = priority ?: 0
|
|
||||||
it.modificationChain.clear()
|
|
||||||
it.modificationChain.add(modifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
return@anyMatch true
|
|
||||||
} else {
|
|
||||||
return@anyMatch false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!replaced) {
|
|
||||||
registry.add(MutableTagEntry(tag!!, mutableListOf(modifier), matter, complexity, priority ?: 0))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (registry.probablyParallelStream().anyMatch { it is MutableTagEntry && it.tag == tag }) {
|
|
||||||
fail { "Value with tag $tag already exists" }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.add(MutableTagEntry(tag!!, mutableListOf(modifier), matter, complexity, priority ?: 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DeleteAction : AbstractRegistryAction {
|
|
||||||
constructor(
|
|
||||||
tag: TagKey<Item>,
|
|
||||||
errorOnFailure: Boolean = false,
|
|
||||||
) : super(tag = tag, errorOnFailure = errorOnFailure, matter = null, complexity = null)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
key: ResourceLocation,
|
|
||||||
errorOnFailure: Boolean = false,
|
|
||||||
) : super(key = key, errorOnFailure = errorOnFailure, matter = null, complexity = null)
|
|
||||||
|
|
||||||
constructor(json: JsonObject) : super(json)
|
|
||||||
|
|
||||||
override fun toJson(): JsonObject {
|
|
||||||
return super.toJson().also {
|
|
||||||
it["action"] = "delete"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(registry: MutableCollection<MutableEntry>, modifier: ResourceLocation) {
|
|
||||||
if (!checkConditions()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
check(matter == null) { "Delete action can't have matter value (for $modifier)" }
|
|
||||||
check(complexity == null) { "Delete action can't have complexity value (for $modifier)" }
|
|
||||||
|
|
||||||
if (key != null) {
|
|
||||||
val iterator = registry.iterator()
|
|
||||||
|
|
||||||
for (value in iterator) {
|
|
||||||
if (value is MutableKeyEntry && value.key == key) {
|
|
||||||
iterator.remove()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fail { "Could not find matter value with key $key" }
|
|
||||||
} else {
|
|
||||||
val iterator = registry.iterator()
|
|
||||||
|
|
||||||
for (value in iterator) {
|
|
||||||
if (value is MutableTagEntry && value.tag == tag) {
|
|
||||||
iterator.remove()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fail { "Could not find matter value with tag $tag" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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>>
|
|
||||||
|
|
||||||
constructor(json: JsonObject) : super(json) {
|
|
||||||
matterFunctions = deserializeFunctionTree(json["matter_functions"], "matter_functions")
|
|
||||||
complexityFunctions = deserializeFunctionTree(json["complexity_functions"], "complexity_functions")
|
|
||||||
priorityFunctions = deserializeFunctionTree(json["priority_functions"], "priority_functions")
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
tag: TagKey<Item>,
|
|
||||||
matter: ImpreciseFraction? = null,
|
|
||||||
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(),
|
|
||||||
) : 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"
|
|
||||||
}
|
|
||||||
|
|
||||||
this.matterFunctions = ImmutableList.copyOf(matterFunctions)
|
|
||||||
this.complexityFunctions = ImmutableList.copyOf(complexityFunctions)
|
|
||||||
this.priorityFunctions = ImmutableList.copyOf(priorityFunctions)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
key: ResourceLocation,
|
|
||||||
matter: ImpreciseFraction? = null,
|
|
||||||
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(),
|
|
||||||
) : 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"
|
|
||||||
}
|
|
||||||
|
|
||||||
this.matterFunctions = ImmutableList.copyOf(matterFunctions)
|
|
||||||
this.complexityFunctions = ImmutableList.copyOf(complexityFunctions)
|
|
||||||
this.priorityFunctions = ImmutableList.copyOf(priorityFunctions)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toJson(): JsonObject {
|
|
||||||
return super.toJson().also {
|
|
||||||
it["action"] = "update"
|
|
||||||
|
|
||||||
if (matterFunctions.isNotEmpty()) {
|
|
||||||
it["matter_functions"] = JsonArray().also {
|
|
||||||
for (fn in matterFunctions) {
|
|
||||||
it.add(fn.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (complexityFunctions.isNotEmpty()) {
|
|
||||||
it["complexity_functions"] = JsonArray().also {
|
|
||||||
for (fn in complexityFunctions) {
|
|
||||||
it.add(fn.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priorityFunctions.isNotEmpty()) {
|
|
||||||
it["priority_functions"] = JsonArray().also {
|
|
||||||
for (fn in priorityFunctions) {
|
|
||||||
it.add(fn.toJson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun apply(value: MutableEntry, modifier: ResourceLocation) {
|
|
||||||
if (matterFunctions.isNotEmpty())
|
|
||||||
value.matter = apply(value.matter, matterFunctions)
|
|
||||||
else if (matter != null)
|
|
||||||
value.matter = matter
|
|
||||||
|
|
||||||
if (complexityFunctions.isNotEmpty())
|
|
||||||
value.complexity = apply(value.complexity, complexityFunctions)
|
|
||||||
else if (complexity != null)
|
|
||||||
value.complexity = complexity
|
|
||||||
|
|
||||||
if (priorityFunctions.isNotEmpty())
|
|
||||||
value.priority = apply(value.priority, priorityFunctions)
|
|
||||||
else if (priority != null)
|
|
||||||
value.priority = priority
|
|
||||||
|
|
||||||
value.modificationChain.add(modifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun update(registry: MutableCollection<MutableEntry>, modifier: ResourceLocation) {
|
|
||||||
if(!(
|
|
||||||
matter != null ||
|
|
||||||
complexity != null ||
|
|
||||||
priority != null ||
|
|
||||||
matterFunctions.isNotEmpty() ||
|
|
||||||
complexityFunctions.isNotEmpty() ||
|
|
||||||
priorityFunctions.isNotEmpty()
|
|
||||||
)) {
|
|
||||||
throw JsonParseException("Can't update existing entries without anything specified (for $modifier)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matter != null && matterFunctions.isNotEmpty()) {
|
|
||||||
throw JsonParseException("Can't have both matter and matter functions specified at the same time (for $modifier)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (complexity != null && complexityFunctions.isNotEmpty()) {
|
|
||||||
throw JsonParseException("Can't have both complexity and complexity functions specified at the same time (for $modifier)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priority != null && priorityFunctions.isNotEmpty()) {
|
|
||||||
throw JsonParseException("Can't have both priority and priority functions specified at the same time (for $modifier)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkConditions()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key != null) {
|
|
||||||
val iterator = registry.iterator()
|
|
||||||
|
|
||||||
for (value in iterator) {
|
|
||||||
if (value is MutableKeyEntry && value.key == key) {
|
|
||||||
apply(value, modifier)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fail { "Could not find matter value with key $key" }
|
|
||||||
} else {
|
|
||||||
val iterator = registry.iterator()
|
|
||||||
|
|
||||||
for (value in iterator) {
|
|
||||||
if (value is MutableTagEntry && value.tag == tag) {
|
|
||||||
apply(value, modifier)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fail { "Could not find matter value with tag $tag" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class MutableEntry(
|
sealed class MutableEntry(
|
||||||
val modificationChain: MutableList<ResourceLocation>,
|
val modificationChain: MutableList<ResourceLocation>,
|
||||||
var matter: ImpreciseFraction,
|
var matter: ImpreciseFraction,
|
||||||
@ -679,46 +76,6 @@ object MatterManager : SimpleJsonResourceReloadListener(GsonBuilder().setPrettyP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMatterValue : Comparable<IMatterValue> {
|
|
||||||
val matter: ImpreciseFraction
|
|
||||||
val complexity: Double
|
|
||||||
|
|
||||||
val hasMatterValue: Boolean get() = matter.isPositive && complexity > 0.0
|
|
||||||
|
|
||||||
operator fun plus(other: IMatterValue): IMatterValue {
|
|
||||||
return MatterValue(matter + other.matter, complexity + other.complexity)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun minus(other: IMatterValue): IMatterValue {
|
|
||||||
return MatterValue(matter - other.matter, complexity - other.complexity)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun compareTo(other: IMatterValue): Int {
|
|
||||||
val matterComparison = matter.compareTo(other.matter)
|
|
||||||
|
|
||||||
if (matterComparison == 0) {
|
|
||||||
return complexity.compareTo(other.complexity)
|
|
||||||
}
|
|
||||||
|
|
||||||
return matterComparison
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ZERO
|
|
||||||
*/
|
|
||||||
companion object : IMatterValue {
|
|
||||||
override val matter: ImpreciseFraction
|
|
||||||
get() = ImpreciseFraction.ZERO
|
|
||||||
override val complexity: Double
|
|
||||||
get() = 0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class MatterValue(
|
|
||||||
override val matter: ImpreciseFraction,
|
|
||||||
override val complexity: Double
|
|
||||||
) : IMatterValue
|
|
||||||
|
|
||||||
sealed class Entry(
|
sealed class Entry(
|
||||||
val modificationChain: List<ResourceLocation>,
|
val modificationChain: List<ResourceLocation>,
|
||||||
final override val matter: ImpreciseFraction,
|
final override val matter: ImpreciseFraction,
|
||||||
|
@ -220,14 +220,14 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDetermined(index: Item): MatterManager.IMatterValue {
|
fun getDetermined(index: Item): IMatterValue {
|
||||||
return determinedValues[index] ?: MatterManager.IMatterValue.Companion
|
return determinedValues[index] ?: IMatterValue.Companion
|
||||||
}
|
}
|
||||||
|
|
||||||
private var input2Recipes: Map<Item, Collection<ResolvedRecipe>> = mapOf()
|
private var input2Recipes: Map<Item, Collection<ResolvedRecipe>> = mapOf()
|
||||||
private var output2Recipes: Map<Item, Collection<ResolvedRecipe>> = mapOf()
|
private var output2Recipes: Map<Item, Collection<ResolvedRecipe>> = mapOf()
|
||||||
|
|
||||||
private val determinedValues = Reference2ObjectOpenHashMap<Item, MatterManager.IMatterValue>()
|
private val determinedValues = Reference2ObjectOpenHashMap<Item, IMatterValue>()
|
||||||
private val commentary = Reference2ObjectOpenHashMap<Item, Component>()
|
private val commentary = Reference2ObjectOpenHashMap<Item, Component>()
|
||||||
private val seenItems = ArrayDeque<Item>()
|
private val seenItems = ArrayDeque<Item>()
|
||||||
|
|
||||||
@ -235,8 +235,8 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
|||||||
return commentary[item]?.copy()
|
return commentary[item]?.copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Result(val type: Type, val value: MatterManager.IMatterValue? = null) {
|
private data class Result(val type: Type, val value: IMatterValue? = null) {
|
||||||
constructor(value: MatterManager.IMatterValue) : this(Type.RESOLVED, value)
|
constructor(value: IMatterValue) : this(Type.RESOLVED, value)
|
||||||
|
|
||||||
val isSkipped get() = type === Type.SKIPPED
|
val isSkipped get() = type === Type.SKIPPED
|
||||||
val isMissing get() = type === Type.MISSING
|
val isMissing get() = type === Type.MISSING
|
||||||
@ -280,7 +280,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
|||||||
var accumulatedComplexity: Double? = null
|
var accumulatedComplexity: Double? = null
|
||||||
|
|
||||||
inputsLoop@ for ((i, inputs) in recipe.inputs.withIndex()) {
|
inputsLoop@ for ((i, inputs) in recipe.inputs.withIndex()) {
|
||||||
var minimal: MatterManager.IMatterValue? = null
|
var minimal: IMatterValue? = null
|
||||||
var minimalMultiplier = 0.0
|
var minimalMultiplier = 0.0
|
||||||
|
|
||||||
for (input in inputs) {
|
for (input in inputs) {
|
||||||
@ -341,7 +341,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
|||||||
return Result.MISSING
|
return Result.MISSING
|
||||||
}
|
}
|
||||||
|
|
||||||
val result = MatterManager.MatterValue(minimalMatter, minimalComplexity)
|
val result = MatterValue(minimalMatter, minimalComplexity)
|
||||||
|
|
||||||
changes = true
|
changes = true
|
||||||
determinedValues[item] = result
|
determinedValues[item] = result
|
||||||
@ -357,7 +357,7 @@ object RecipeResolverManager : SimpleJsonResourceReloadListener(GsonBuilder().se
|
|||||||
return getResult
|
return getResult
|
||||||
}
|
}
|
||||||
|
|
||||||
var value: MatterManager.IMatterValue? = MatterManager.getDirect(item)
|
var value: IMatterValue? = MatterManager.getDirect(item)
|
||||||
|
|
||||||
if (value?.hasMatterValue == true) {
|
if (value?.hasMatterValue == true) {
|
||||||
return Result(value)
|
return Result(value)
|
||||||
|
309
src/main/kotlin/ru/dbotthepony/mc/otm/matter/UpdateAction.kt
Normal file
309
src/main/kotlin/ru/dbotthepony/mc/otm/matter/UpdateAction.kt
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
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 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
|
||||||
|
|
||||||
|
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>>
|
||||||
|
|
||||||
|
constructor(json: JsonObject) : super(json) {
|
||||||
|
matterFunctions = deserializeFunctionTree(json["matter_functions"], "matter_functions")
|
||||||
|
complexityFunctions = deserializeFunctionTree(json["complexity_functions"], "complexity_functions")
|
||||||
|
priorityFunctions = deserializeFunctionTree(json["priority_functions"], "priority_functions")
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
tag: TagKey<Item>,
|
||||||
|
matter: ImpreciseFraction? = null,
|
||||||
|
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(),
|
||||||
|
) : 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
this.matterFunctions = ImmutableList.copyOf(matterFunctions)
|
||||||
|
this.complexityFunctions = ImmutableList.copyOf(complexityFunctions)
|
||||||
|
this.priorityFunctions = ImmutableList.copyOf(priorityFunctions)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
key: ResourceLocation,
|
||||||
|
matter: ImpreciseFraction? = null,
|
||||||
|
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(),
|
||||||
|
) : 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
this.matterFunctions = ImmutableList.copyOf(matterFunctions)
|
||||||
|
this.complexityFunctions = ImmutableList.copyOf(complexityFunctions)
|
||||||
|
this.priorityFunctions = ImmutableList.copyOf(priorityFunctions)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toJson(): JsonObject {
|
||||||
|
return super.toJson().also {
|
||||||
|
it["action"] = "update"
|
||||||
|
|
||||||
|
if (matterFunctions.isNotEmpty()) {
|
||||||
|
it["matter_functions"] = JsonArray().also {
|
||||||
|
for (fn in matterFunctions) {
|
||||||
|
it.add(fn.toJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complexityFunctions.isNotEmpty()) {
|
||||||
|
it["complexity_functions"] = JsonArray().also {
|
||||||
|
for (fn in complexityFunctions) {
|
||||||
|
it.add(fn.toJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priorityFunctions.isNotEmpty()) {
|
||||||
|
it["priority_functions"] = JsonArray().also {
|
||||||
|
for (fn in priorityFunctions) {
|
||||||
|
it.add(fn.toJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun apply(value: MatterManager.MutableEntry, modifier: ResourceLocation) {
|
||||||
|
if (matterFunctions.isNotEmpty())
|
||||||
|
value.matter = apply(value.matter, matterFunctions)
|
||||||
|
else if (matter != null)
|
||||||
|
value.matter = matter
|
||||||
|
|
||||||
|
if (complexityFunctions.isNotEmpty())
|
||||||
|
value.complexity = apply(value.complexity, complexityFunctions)
|
||||||
|
else if (complexity != null)
|
||||||
|
value.complexity = complexity
|
||||||
|
|
||||||
|
if (priorityFunctions.isNotEmpty())
|
||||||
|
value.priority = apply(value.priority, priorityFunctions)
|
||||||
|
else if (priority != null)
|
||||||
|
value.priority = priority
|
||||||
|
|
||||||
|
value.modificationChain.add(modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(registry: MutableCollection<MatterManager.MutableEntry>, modifier: ResourceLocation) {
|
||||||
|
if(!(
|
||||||
|
matter != null ||
|
||||||
|
complexity != null ||
|
||||||
|
priority != null ||
|
||||||
|
matterFunctions.isNotEmpty() ||
|
||||||
|
complexityFunctions.isNotEmpty() ||
|
||||||
|
priorityFunctions.isNotEmpty()
|
||||||
|
)) {
|
||||||
|
throw JsonParseException("Can't update existing entries without anything specified (for $modifier)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matter != null && matterFunctions.isNotEmpty()) {
|
||||||
|
throw JsonParseException("Can't have both matter and matter functions specified at the same time (for $modifier)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (complexity != null && complexityFunctions.isNotEmpty()) {
|
||||||
|
throw JsonParseException("Can't have both complexity and complexity functions specified at the same time (for $modifier)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priority != null && priorityFunctions.isNotEmpty()) {
|
||||||
|
throw JsonParseException("Can't have both priority and priority functions specified at the same time (for $modifier)")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkConditions()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
val iterator = registry.iterator()
|
||||||
|
|
||||||
|
for (value in iterator) {
|
||||||
|
if (value is MatterManager.MutableKeyEntry && value.key == key) {
|
||||||
|
apply(value, modifier)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail { "Could not find matter value with key $key" }
|
||||||
|
} else {
|
||||||
|
val iterator = registry.iterator()
|
||||||
|
|
||||||
|
for (value in iterator) {
|
||||||
|
if (value is MatterManager.MutableTagEntry && value.tag == tag) {
|
||||||
|
apply(value, modifier)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail { "Could not find matter value with tag $tag" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user