aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/Texture Pack Format.md119
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt1
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt23
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt2
5 files changed, 166 insertions, 1 deletions
diff --git a/docs/Texture Pack Format.md b/docs/Texture Pack Format.md
index 587bcd3..9b5a66e 100644
--- a/docs/Texture Pack Format.md
+++ b/docs/Texture Pack Format.md
@@ -24,3 +24,122 @@ replacement texture at `firmskyblock:textures/placedskulls/<thathash>.png`. Keep
the texture with another skin texture, meaning that skin texture has it's own hash. Do not mix those up, you need to use
the hash of the old skin.
+## Predicates
+
+Firmament adds the ability for more complex [item model predicates](https://minecraft.wiki/w/Tutorials/Models#Item_predicates).
+Those predicates work on any model, including models for vanilla items, but they don't mix very well with vanilla model overrides.
+Vanilla predicates only ever get parsed at the top level, so including a vanilla predicate inside of a more complex
+firmament parser will result in an ignored predicate.
+
+### Example usage
+
+```json
+{
+ "parent": "minecraft:item/handheld",
+ "textures": {
+ "layer0": "firmskyblock:item/bat_wand"
+ },
+ "overrides": [
+ {
+ "predicate": {
+ "firmament:display_name": {
+ "regex": ".*§d.*",
+ "color": "preserve"
+ }
+ },
+ "model": "firmskyblock:item/recombobulated_bat_wand"
+ }
+ ]
+}
+```
+
+You specify an override like normally, with a `model` that will replace the current model and a list of `predicate`s
+that must match before that override takes place.
+
+At the top level `predicate` you can still use all the normal vanilla predicates, as well as the custom ones, which are
+all prefixed with `firmament:`.
+
+#### Display Name
+
+Matches the display name against a [string matcher](#string-matcher)
+
+```json
+"firmament:display_name": "Display Name Test"
+```
+
+#### Lore
+
+Tries to find at least one lore line that matches the given [string matcher](#string-matcher).
+
+```json
+"firmament:lore": {
+ "regex": "Mode: Red Mushrooms",
+ "color": "strip"
+}
+```
+
+#### Logic Operators
+
+Logic operators allow to combine other firmament predicates into one. This is done by building boolean operators:
+
+```json5
+"firmament:any": [
+ {
+ "firmament:display_name": "SkyBlock Menu (Click)"
+ },
+ {
+ "firmament:display_name": "SkyBlock",
+ "firmament:lore": "Some Lore Requirement"
+ }
+]
+```
+
+This `firmament:any` test if the display name is either "SkyBlock Menu (Click)" or "SkyBlock" (aka any of the child predicates match).
+
+Similarly, there is `firmament:all`, which requires all of its children to match.
+
+There is also `firmament:not`, which requires none of its children to match. Unlike `any` or `all`, however, `not`
+only takes in one predicate `{}` directly, not an array of predicates `[{}]`.
+
+Note also that by default all predicate dictionaries require all predicates in it to match, so you can imagine that all
+things are wrapped in an implicit `firmament:all` element.
+
+### String Matcher
+
+A string matcher allows you to match almost any string. Whenever a string matcher is expected, you can use any of these
+styles of creating one.
+
+#### Direct
+
+```json
+"firmament:display_name": "Test"
+```
+
+Directly specifying a raw string value expects the string to be *exactly* equal, after removing all formatting codes.
+
+#### Complex
+
+A complex string matcher allows you to specify whether the string will get its color codes removed or not before matching
+
+
+```json5
+"firmament:display_name": {
+ "color": "strip",
+ "color": "preserve",
+ // When omitting the color property alltogether, you will fall back to "strip"
+}
+```
+In that same object you can then also specify how the string will be matched using another property. You can only ever
+specify one of these other matchers and one color preserving property.
+
+```json5
+"firmament:display_name": {
+ "color": "strip",
+ // You can use a "regex" property to use a java.util.Pattern regex. It will try to match the entire string.
+ "regex": "So[me] Regex",
+ // You can use an "equals" property to test if the entire string is equal to some value.
+ // Equals is faster than regex, but also more limited.
+ "equals": "Some Text"
+}
+```
+
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt
new file mode 100644
index 0000000..ec4c1d3
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt
@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+package moe.nea.firmament.features.texturepack
+
+import com.google.gson.JsonElement
+import net.minecraft.item.ItemStack
+
+object AlwaysPredicate : FirmamentModelPredicate {
+ override fun test(stack: ItemStack): Boolean {
+ return true
+ }
+
+ object Parser : FirmamentModelPredicateParser {
+ override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
+ return AlwaysPredicate
+ }
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
index ac62eaa..ad1f436 100644
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
@@ -23,6 +23,7 @@ object CustomModelOverrideParser {
registerPredicateParser("lore", LorePredicate.Parser)
registerPredicateParser("all", AndPredicate.Parser)
registerPredicateParser("any", OrPredicate.Parser)
+ registerPredicateParser("not", NotPredicate.Parser)
}
fun parsePredicates(predicates: JsonObject): List<FirmamentModelPredicate> {
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt
new file mode 100644
index 0000000..9d584cf
--- /dev/null
+++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt
@@ -0,0 +1,23 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+package moe.nea.firmament.features.texturepack
+
+import com.google.gson.JsonElement
+import com.google.gson.JsonObject
+import net.minecraft.item.ItemStack
+
+class NotPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
+ override fun test(stack: ItemStack): Boolean {
+ return children.none { it.test(stack) }
+ }
+
+ object Parser : FirmamentModelPredicateParser {
+ override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
+ return NotPredicate(CustomModelOverrideParser.parsePredicates(jsonElement as JsonObject).toTypedArray())
+ }
+ }
+}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt
index 0fb8e00..e9d39a8 100644
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt
+++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt
@@ -52,7 +52,7 @@ interface StringMatcher {
}
if (jsonElement is JsonObject) {
val regex = jsonElement["regex"] as JsonPrimitive?
- val text = jsonElement["text"] as JsonPrimitive?
+ val text = jsonElement["equals"] as JsonPrimitive?
val shouldStripColor = when (val color = (jsonElement["color"] as JsonPrimitive?)?.asString) {
"preserve" -> false
"strip", null -> true