-
Notifications
You must be signed in to change notification settings - Fork 0
Config Structure Overview
The basic JSON components of all the requirement files consists of a global block followed by each item/block regsitryKey as a base node. The global block looks as follows:
{
"global": {
"paths": {},
"constants": {}
}
}
Under each item node are required one key with two optional keys:
"logic": []
which is an array of anonymous blocks [{},{},{}]
(more on those later)
"paths": {}
NOT IMPLEMENTED YET (optional) path aliases for this specific entry.
"constants": {}
NOT IMPLEMENTED YET (optional) aliases for frequently used values for this specific entry
an oversimplified item entry would look like this:
{
"mymod:myitem": {
"logic": [],
"paths":{},
"constants":{}
}
}
The logic block is the bulk of the config and contains all the desired behavior of your items. The most important aspect of the Logic block is that is is an ordered list. The first entry is evaluated, then the second, then the third, and so on. Each logic entry will also have a specific relation to the entry before it, which is why order matters. Let's look at the basic structure of a logic entry.
{
"behavior_to_previous": "",
"should_cases_add": false,
"cases": []
}
"behavior_to_previous"
tells the logic evaluator how this specific entry should interact with all of the data before it. There are 4 valid options that this block can have. they are:
-
"ADD_TO"
: Adds the results of this entry's cases to the values preceding it -
"SUB_FROM"
: Subtracts the results of this entry's cases from the values preceding it -
"HIGHEST"
: Compares the values preceding it to this case and uses the highest as the new value -
"REPLACE"
: Overrides a previous entry with this entry's
"should_cases_add"
(previously called "summative") determines if cases should aggregate or if only the highest value within a case block should be used.
"cases"
is another major block within an entry and contains all of the actual values being evaluated and applied. Case entries are not ordered in any specific way, but have a specific format as well. case entries are structured as follows:
{
"paths": [],
"criteria": []
}
"paths"
is an array of all the nbt paths that should be evaluated against the succeeding criteria.
"criteria"
is an array of anonymous blocks containing the skill values and evaluation parameters. an example of a criteria entry looks like this:
{
"operator":"",
"comparators":[],
"value":{}
}
"operator"
tells the evaluator how to compare the value found at the path to the value in the comparator key. There are only six valid entries here:
-
"EQUALS"
: nbt value and comparator value must be the same -
"GREATER_THAN"
: nbt value must be greater than the comparator -
"LESS_THAN"
: nbt value must be less than the comparator -
"GREATER_THAN_OR_EQUAL"
: nbt value must be greater than or equal to the comparator -
"LESS_THAN_OR_EQUAL"
: nbt value must be less than or equal to the comparator -
"EXISTS"
: is true if the nbt value exists (if used the comparators key can be omitted)
"comparators": []
is an array of values. each one is evaluated independently so that you can group similar conditions together. e.g. ["mymod:iron", "mymod:wood", "mymod:diamond"]
or [5, 10, 15]
.
"value": {}
is the exact same as regular pmmo configs' section for defining skills. This section is where you say what skills and level should be applied if the expression is true. e.g "value": { "mining": 10 }"
Putting it all together
Here is an example of an item with two logical tiers. In the first tier we say that the value of the item is based on what material is used, then we subtract a value from the requirement if the item is damaged beyond 50. which in this case would mean an item with a head material of diamond and damage of 51 would only require 5 mining.
{
"logic": [
{"behavior_to_previous": "ADD_TO", "should_cases_add": false,
"cases": [
{"paths":["materials{}.head"],
"criteria":[
{"operator":"EQUALS", "comparators":["iron","gold"], "value":{"mining":5}},
{"operator":"EQUALS", "comparators":["diamond"], "value":{"mining":10}},
{"operator":"EQUALS", "comparators":["netherite"], "value":{"mining":15}}
]
}
]
},
{"behavior_to_previous": "SUB_FROM", "should_cases_add": false,
"cases": [
{"paths":["Damage"],
"criteria":[
{"operator":"GREATER_THAN", "comparators":[50], "value":{"mining":5}}
]
}
]
}
]
}
Paths are how you define where in an item's NBT a specific value is located. A path in your config is a string representation of that location. Paths are constructed using key names followed by a type indicator and delimited by a period .
. The 3 path type indicators are:
- Compounds:
{}
eg"compoundExample{}"
- Lists:
[]
eg"listExample[]"
- Values: nothing eg
"valueExample"
An example path from vanilla would be dyed leather armor. The actual NBT of a dyed armor piece looks like this
{
Damage:0b,
display:{
color:16701501
}
}
If we want the color of this armor piece, we need to get the first containing element. in this example the only two keys under the root tag are "Damage" and "display". We know two things: one, display contains our color key, and because of the {
after the colon, we know, two, it's a compound type. So we have the first part of our path "display{}"
. Now that we have told the reader to look in the "display" compound, we need to tell it to get us the value of color. We know color is our value, so there's our type. so we add a delimiter period after our compound and add the value to our path "display{}.color"
which gives us our final path. You can read more about paths HERE.
This path can be used directly in the "paths" array in your cases, or you can use the global and local paths sections to create aliases.
Aliases give you a way to make a shorthand version of a path for use in your configs. for example if I create the following alias:
{
"global": {
"paths": {
"myalias":"someData{}.withALongPath{}.thatWouldBe[].veryBulky{}.toWriteOrPaste{}.repeatedly"
},
"constants":{}
}
}
I could then use that alias in my cases section by putting a #
in front of the alias in my case's paths section "paths":["#myalias"]"
*Note: local path aliases are not yet implemented
Like aliases except for values used in the comparators section, and also not implemented yet. for the time being, you can actually omit the entry entirely since nothing is going to try and read it.