-
Notifications
You must be signed in to change notification settings - Fork 1
Test Operation
The test patch type allows testing of a given condition, and only continuing patch application if the result of the condition is true. Specifically, following patches at the same level will not be executed if a test patch defined before them fails.
These patches have a few different forms. The first one tests for equality:
// a value equality test patch, which tests equality between the target element and the value element
{
"op": "test", // specifies this is a test patch
"path": "/path/to/element", // specifies the path to the target element
"value": "expected value", // specifies the element the target must be equal to for the test to succeed
"inverse": false // optional, if true, means the test succeeds only if the target *isn't* equal to the value
}Another form tests for existence:
// an existence test patch, which tests for the existence of the target element
{
"op": "test", // specifies this is a test patch
"path": "/path/to/element", // specifies the path to the element that must exist for the test to succeed
"inverse": false // optional, if true, means the test succeeds only if the target *doesn't* exist
}Finally, the last form is used for other kinds of tests (called 'custom tests'), depending on the type parameter:
{
"op": "test", // specifies this is a test patch
"type": "patched:mod_loaded", // specifies the condition to test, in this case 'patched:mod_loaded'
"path": "/path/to/input/element", // optional, specifies the path to an element to pass to the condition
"value": "mymod" // optional, specifies an input value to pass to the condition, in this case 'mymod'
}Note that for the last form the path and value are not required from a patch validity standpoint — that is, it's still a valid patch if both fields are omitted. However, many conditions require the value field, and some may require the path field too. Always check the condition in question for what fields may be required, and for the expected content of the value field (if the value field is required).
Let's look at some examples. For the first form:
// the_nether.json
{
// ...
"ultrawarm": true
}// the_nether.json.patch
{
"op": "test",
"path": "/ultrawarm",
"value": true
}
// result: true (true = true)// the_nether.json.patch
{
"op": "test",
"path": "/ultrawarm",
"value": 3
}
// result: false (true ≠ 3)// the_nether.json.patch
{
"op": "test",
"path": "/ultrawarm",
"value": false,
"inverse": true
}
// result: true (true ≠ false)The first form also works for objects and arrays, also since their contents are more easily changed it's frequently a better idea to check their contents, rather than the enclosing object/array.
One of the primary uses of the first form is to guard against error conditions, such as removing a nonexistent element (or the wrong element):
// elytrian.json
{
// ...
"powers": [
"origins:elytra",
"origins:launch_into_air",
"origins:aerial_combatant",
"origins:light_armor",
"origins:claustrophobia",
"origins:more_kinetic_damage"
],
// ...
}// elytrian.json.patch
[
{ // check if the power at this position is the claustrophobia power
"op": "test",
"path": "/powers/4",
"value": "origins:claustrophobia"
},
{ // remove it if so
"op": "remove",
"path": "/powers/4"
}
]If the power here was already removed (or replaced) then the patch won't try to remove an unrelated power. Moreover, it clarifies intent; someone looking at this patch can clearly tell it's supposed to remove this power and nothing else. If the test patch was not present, it wouldn't be obvious what the patch is supposed to remove. It's also forward-thinking — the patch won't cause damage if in the future this power is moved elsewhere in the list.
Here's the second form:
// adventuring_time.json
{
// ...
"criteria": {
"minecraft:badlands": { ... },
// ...
},
// ...
}// adventuring_time.json.patch
{
"op": "test",
"path": "/criteria/minecraft:badlands"
}
// result: true (it exists)// adventuring_time.json.patch
{
"op": "test",
"path": "/criteria/ae2:void"
}
// result: false (it doesn't exist)Finally, the last form:
{
"op": "test",
"type": "patched:mod_loaded",
"value": "patched"
}
// result: true (the mod 'patched' is present){
"op": "test",
"type": "patched:item_registered",
"value": "minecraft:stick"
}
// result: true (the item 'minecraft:stick' is registered)// in data pack 'Test'
{
"op": "test",
"type": "patched:pack_enabled",
"value": "file/Test"
}
// result: true (the folder pack 'Test' is enabled)For more on these and other test conditions, see the test conditions page, which goes into much greater detail on all of these.