Transmutation System Overview
Transmutation System Overview
Section titled “Transmutation System Overview”The transmutation system is the core feature of Alchemy, providing powerful and flexible item data conversion through JSON-configured rules.
How It Works
Section titled “How It Works”1. Interception
Section titled “1. Interception”Alchemy intercepts Minecraft’s item deserialization process using a mixin on the ItemStack codec. This means conversions happen automatically when:
- Players join the server (inventory loading)
- Chunks are loaded (container blocks)
- Items are dropped or picked up
- Any item data is read from NBT
2. Rule Matching
Section titled “2. Rule Matching”When an item is being deserialized:
- Rules are evaluated in priority order (highest first)
- Each rule’s condition is checked against the item
- The first matching rule is applied
- If a rule matches, no other rules are checked
3. Operation Application
Section titled “3. Operation Application”Once a rule matches:
- The rule’s operations are applied in sequence
- Each operation receives the output of the previous operation
- The final result replaces the original item
Configuration Structure
Section titled “Configuration Structure”A transmutation configuration file has this structure:
{ "conversions": [ { "id": "unique_identifier", "priority": 100, "condition": { /* condition object */ }, "operations": [ /* array of operations */ ] } ]}Root Fields
Section titled “Root Fields”| Field | Type | Required | Description |
|---|---|---|---|
conversions | Array | Yes | List of conversion rules |
Conversion Rule Fields
Section titled “Conversion Rule Fields”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | String | Yes | - | Unique identifier for this rule |
priority | Integer | No | 0 | Priority for rule evaluation (higher = checked first) |
condition | Object | Yes | - | Condition that determines if this rule applies |
operations | Array | Yes | - | List of operations to apply when condition matches |
Execution Order
Section titled “Execution Order”Understanding the execution order is crucial:
Item Loading ↓Load All Rules from config/alchemy/transmutations/*.json ↓Sort Rules by Priority (highest → lowest) ↓For Each Item Being Deserialized: ↓ Check Rule 1 Condition → No Match ↓ Check Rule 2 Condition → Match! ✓ ↓ Apply Rule 2 Operations in Sequence: Operation 1 → Operation 2 → Operation 3 ↓ Return Transformed Item (skip remaining rules)Priority System
Section titled “Priority System”Priority determines the order in which rules are evaluated:
- Higher numbers = checked first
- Same priority = order is undefined (use different priorities for predictable behavior)
- Default priority =
0
Priority Guidelines
Section titled “Priority Guidelines”1000+ : Critical conversions that must run first100-999 : High priority conversions1-99 : Normal conversions0 : Default priority-1 to -99 : Low priority conversions-100+ : Catch-all or fallback conversionsPath Syntax
Section titled “Path Syntax”Paths use dot-notation to navigate item data structures:
id # Item IDcomponents # Components containercomponents.minecraft:custom_data # Custom data componentcomponents.minecraft:custom_data.my_key # Nested custom datacomponents.custom:my_component # Custom namespace componentImportant Notes:
- Always include namespace prefixes (e.g.,
minecraft:custom_data, notcustom_data) - Paths are case-sensitive
- Missing paths result in
nullvalues (safe to check withcomponent_exists)
Example: Complete Workflow
Section titled “Example: Complete Workflow”Here’s a complete example showing how a rule works:
{ "conversions": [ { "id": "legacy_magic_items", "priority": 150, "condition": { "type": "all", "all": [ { "type": "component_exists", "path": "components.minecraft:custom_data.legacy_item" }, { "type": "component_equals", "path": "components.minecraft:custom_data.legacy_item.type", "value": "magic" } ] }, "operations": [ { "type": "set_item_id_from_component", "source": "components.minecraft:custom_data.legacy_item.new_id" }, { "type": "set_component", "component": "custom:magic_data", "value": { "type": "map", "map": { "power": { "type": "from_source", "fromPath": "components.minecraft:custom_data.legacy_item.power" }, "element": { "type": "from_source", "fromPath": "components.minecraft:custom_data.legacy_item.element" }, "version": { "type": "number", "number": 2 } } } }, { "type": "remove_custom_data_key", "path": "legacy_item" } ] } ]}What This Does:
- Condition: Matches items that have
legacy_itemdata withtype: "magic" - Operation 1: Changes the item ID based on the
new_idfield - Operation 2: Creates a new
custom:magic_datacomponent with restructured data - Operation 3: Removes the old
legacy_itemdata
Best Practices
Section titled “Best Practices”1. Use Descriptive IDs
Section titled “1. Use Descriptive IDs”"id": "oraxen_to_custom_weapons" // Good"id": "conversion_1" // Bad2. Set Appropriate Priorities
Section titled “2. Set Appropriate Priorities”// Specific conversions should run before generic ones{ "id": "specific_diamond_sword", "priority": 100, "condition": { /* ... */ }}{ "id": "generic_swords", "priority": 50, "condition": { /* ... */ }}3. Test Conditions Thoroughly
Section titled “3. Test Conditions Thoroughly”Always test your conditions don’t accidentally match unintended items:
// Good: Specific condition{ "type": "all", "all": [ {"type": "component_exists", "path": "..."}, {"type": "component_equals", "path": "...", "value": "..."} ]}
// Risky: May match too broadly{ "type": "component_exists", "path": "components.minecraft:custom_data"}4. Clean Up After Conversion
Section titled “4. Clean Up After Conversion”Always remove old data to prevent duplicate conversions:
{ "operations": [ {"type": "set_item_id", "itemId": "new:item"}, {"type": "remove_component", "path": "old_marker"} // Clean up! ]}Next Steps
Section titled “Next Steps”- Conditions Reference - All available condition types
- Operations Reference - All available operation types
- Example Configurations - Real-world conversion examples
- Transmutation Builder - Interactive config builder tool