Skip to content

Modification

Refaltor77 edited this page Apr 15, 2026 · 1 revision

Modification

The Modification system allows non-intrusive edits to existing JSON UI elements — primarily vanilla Bedrock UI files. This improves compatibility across resource packs by avoiding full file replacements.

Operations

Operation Constant Description
insert_back Modification::OP_INSERT_BACK Insert at end of array
insert_front Modification::OP_INSERT_FRONT Insert at start of array
insert_after Modification::OP_INSERT_AFTER Insert after a target
insert_before Modification::OP_INSERT_BEFORE Insert before a target
move_back Modification::OP_MOVE_BACK Move target to end
move_front Modification::OP_MOVE_FRONT Move target to start
move_after Modification::OP_MOVE_AFTER Move target after another
move_before Modification::OP_MOVE_BEFORE Move target before another
swap Modification::OP_SWAP Swap two elements
replace Modification::OP_REPLACE Replace an element
remove Modification::OP_REMOVE Remove an element

Target Arrays

Constant Value
Modification::ARRAY_CONTROLS controls
Modification::ARRAY_BINDINGS bindings
Modification::ARRAY_VARIABLES variables
Modification::ARRAY_ANIMS anims
Modification::ARRAY_BUTTON_MAPPINGS button_mappings

Factory Methods

Insert Operations

use refaltor\ui\components\Modification;

// Insert at end/start of an array
Modification::insertBack(Modification::ARRAY_CONTROLS)->setValue([...]);
Modification::insertFront(Modification::ARRAY_BINDINGS)->setValue([...]);

// Insert after/before a named control
Modification::insertAfter("target_control")->setValue([...]);
Modification::insertBefore("target_control")->setValue([...]);

// Insert after/before matching a where clause
Modification::insertAfterWhere(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#my_binding"
])->setValue([...]);

Modification::insertBeforeWhere(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#my_binding"
])->setValue([...]);

Move Operations

// Move to end/start
Modification::moveBack(Modification::ARRAY_CONTROLS)->setValue([...]);
Modification::moveFront(Modification::ARRAY_CONTROLS)->setValue([...]);

// Move after/before a named control
Modification::moveAfter("target_control")->setValue([...]);
Modification::moveBefore("target_control")->setValue([...]);

// Move with where + target clauses
Modification::moveBackWhere(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#binding_to_move"
]);

Modification::moveFrontWhere(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#binding_to_move"
]);

Modification::moveAfterWhere(
    Modification::ARRAY_BINDINGS,
    ["binding_name" => "#binding_to_move"],   // where
    ["binding_name" => "#target_binding"]     // target
);

Modification::moveBeforeWhere(
    Modification::ARRAY_BINDINGS,
    ["binding_name" => "#binding_to_move"],
    ["binding_name" => "#target_binding"]
);

Replace, Remove, Swap

// Replace a matching element
Modification::replace(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#old_binding"
])->setValue([
    "binding_name" => "#new_binding",
    "binding_type" => "global",
]);

// Remove a matching element
Modification::remove(Modification::ARRAY_BINDINGS, [
    "binding_name" => "#unwanted_binding"
]);

// Swap two matching elements
Modification::swap(
    Modification::ARRAY_BINDINGS,
    ["binding_name" => "#binding_a"],
    ["binding_name" => "#binding_b"]
);

Chainable Setters

All factory methods return a Modification instance. You can also chain setters manually:

$mod = new Modification("insert_back");
$mod->setArrayName("controls")
    ->setValue([["my_child@common.empty_panel" => []]])
    ->setControlName("target")
    ->setWhere(["binding_name" => "#x"])
    ->setTarget(["binding_name" => "#y"]);

Usage on Elements

Any element can carry modifications via addModification() / addModifications():

$panel = Panel::create("my_panel")
    ->addModification(
        Modification::insertBack(Modification::ARRAY_CONTROLS)
            ->setValue([["new_child@common.empty_panel" => []]])
    )
    ->addModification(
        Modification::remove(Modification::ARRAY_BINDINGS, [
            "binding_name" => "#obsolete"
        ])
    );

Usage on Vanilla Elements

Use Root::modifyVanillaElement() to target vanilla Bedrock UI elements using path syntax:

$root = Root::create("my_namespace");

// Target nested vanilla element: parent/child/grandchild
$root->modifyVanillaElement("hud_title_text/title_frame/title", [
    Modification::insertBack(Modification::ARRAY_BINDINGS)
        ->setValue([
            [
                "binding_type" => "view",
                "source_property_name" => "(not (#text = 'hidden'))",
                "target_property_name" => "#visible",
            ]
        ]),
]);

// Add controls to a vanilla screen
$root->modifyVanillaElement("hud_screen", [
    Modification::insertBack(Modification::ARRAY_CONTROLS)
        ->setValue([
            ["my_element@my_namespace.my_panel" => []]
        ]),
]);

JSON Output

A modification on an element generates:

{
    "my_panel": {
        "type": "panel",
        "modifications": [
            {
                "array_name": "controls",
                "operation": "insert_back",
                "value": [{ "new_child@common.empty_panel": {} }]
            }
        ]
    }
}

A vanilla element modification generates:

{
    "hud_title_text/title_frame/title": {
        "modifications": [
            {
                "array_name": "bindings",
                "operation": "insert_back",
                "value": [{ "binding_type": "view", ... }]
            }
        ]
    }
}

See Also

  • Element — Adding modifications to elements
  • Root — Vanilla element modifications
  • JsonValidator — Validation of modification structures

Clone this wiki locally