aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-11-01 23:00:53 +0100
committerLinnea Gräf <nea@nea.moe>2024-11-01 23:00:53 +0100
commit8b410fbdf2cffb3ceaa51bbea150f5165848bc37 (patch)
treee4b4ec4ba24a7edbefa45b7deb2503b74214ee02 /src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt
parent653454e290a1bb6142e2bb40947239c2e450820b (diff)
downloadFirmament-8b410fbdf2cffb3ceaa51bbea150f5165848bc37.tar.gz
Firmament-8b410fbdf2cffb3ceaa51bbea150f5165848bc37.tar.bz2
Firmament-8b410fbdf2cffb3ceaa51bbea150f5165848bc37.zip
Add tint override to texture packs
Diffstat (limited to 'src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt')
-rw-r--r--src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt124
1 files changed, 124 insertions, 0 deletions
diff --git a/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt b/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt
new file mode 100644
index 0000000..b0d5178
--- /dev/null
+++ b/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt
@@ -0,0 +1,124 @@
+package moe.nea.firmament.features.texturepack.predicates
+
+import com.google.gson.JsonElement
+import com.google.gson.JsonPrimitive
+import moe.nea.firmament.util.useMatch
+
+abstract class NumberMatcher {
+ abstract fun test(number: Number): Boolean
+
+
+ companion object {
+ fun parse(jsonElement: JsonElement): NumberMatcher? {
+ if (jsonElement is JsonPrimitive) {
+ if (jsonElement.isString) {
+ val string = jsonElement.asString
+ return parseRange(string) ?: parseOperator(string)
+ }
+ if (jsonElement.isNumber) {
+ val number = jsonElement.asNumber
+ val hasDecimals = (number.toString().contains("."))
+ return MatchNumberExact(if (hasDecimals) number.toLong() else number.toDouble())
+ }
+ }
+ return null
+ }
+
+ private val intervalSpec =
+ "(?<beginningOpen>[\\[\\(])(?<beginning>[0-9.]+)?,(?<ending>[0-9.]+)?(?<endingOpen>[\\]\\)])"
+ .toPattern()
+
+ fun parseRange(string: String): RangeMatcher? {
+ intervalSpec.useMatch<Nothing>(string) {
+ // Open in the set-theory sense, meaning does not include its end.
+ val beginningOpen = group("beginningOpen") == "("
+ val endingOpen = group("endingOpen") == ")"
+ val beginning = group("beginning")?.toDouble()
+ val ending = group("ending")?.toDouble()
+ return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
+ }
+ return null
+ }
+
+ enum class Operator(val operator: String) {
+ LESS("<") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult < 0
+ }
+ },
+ LESS_EQUALS("<=") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult <= 0
+ }
+ },
+ GREATER(">") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult > 0
+ }
+ },
+ GREATER_EQUALS(">=") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult >= 0
+ }
+ },
+ ;
+
+ abstract fun matches(comparisonResult: Int): Boolean
+ }
+
+ private val operatorPattern =
+ "(?<operator>${Operator.entries.joinToString("|") { it.operator }})(?<value>[0-9.]+)".toPattern()
+
+ fun parseOperator(string: String): OperatorMatcher? {
+ return operatorPattern.useMatch(string) {
+ val operatorName = group("operator")
+ val operator = Operator.entries.find { it.operator == operatorName }!!
+ val value = group("value").toDouble()
+ OperatorMatcher(operator, value)
+ }
+ }
+
+ data class OperatorMatcher(val operator: Operator, val value: Double) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ return operator.matches(number.toDouble().compareTo(value))
+ }
+ }
+
+
+ data class MatchNumberExact(val number: Number) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ return when (this.number) {
+ is Double -> number.toDouble() == this.number.toDouble()
+ else -> number.toLong() == this.number.toLong()
+ }
+ }
+ }
+
+ data class RangeMatcher(
+ val beginning: Double?,
+ val beginningInclusive: Boolean,
+ val ending: Double?,
+ val endingInclusive: Boolean,
+ ) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ val value = number.toDouble()
+ if (beginning != null) {
+ if (beginningInclusive) {
+ if (value < beginning) return false
+ } else {
+ if (value <= beginning) return false
+ }
+ }
+ if (ending != null) {
+ if (endingInclusive) {
+ if (value > ending) return false
+ } else {
+ if (value >= ending) return false
+ }
+ }
+ return true
+ }
+ }
+ }
+
+}