Kzeroko KTM2

Gem data

Define gem rolls, sockets, difficulty scaling, curses and consumables with their validation and reload rules.

Updated Sep 18, 2026 17 min read

Gem resources control which bonuses can be rolled and where they fit. The server loads all gem families as one snapshot: an invalid resource keeps the previous snapshot active.

Where the files live

Except global settings, these paths are relative to data/<namespace>/; any namespace can contribute definitions. Global settings are read only from data/isekaiexpansion/gem_system/settings.json.

gem_system/settings.json
gem_attributes/random_roll/*.json
gem_attributes/fixed_attributes/*.json
gem_attributes/element_attributes/*.json
gem_attributes/skill_attributes/*.json
socket_profiles/*.json
curses/*.json
gem_consumables/*.json

Each file contains one object. A higher-priority pack replaces a resource with the same namespaced path; definitions at different paths are still checked for duplicate IDs, attributes and item ownership. Global settings use the highest resource, not a field-by-field merge. A socket profile’s ID is its namespaced path below socket_profiles/, without .json.

Minimal example

Save this as data/example/socket_profiles/iron_sword.json. It gives an iron sword an unlocked attribute socket and outranks the bundled melee profile. The explicit priority prevents the example being hidden by that existing profile; it is optional to the parser.

{
  "priority": 120,
  "match": {
    "items": [
      "minecraft:iron_sword"
    ]
  },
  "sockets": [
    {
      "kind": "ATTRIBUTE",
      "min_item_level": 0
    }
  ]
}

Fields

Use actual JSON numbers and booleans. Missing required fields or numeric conversion failures reject the reload. Unknown fields are ignored except the explicitly removed keys under Validation. The table calls out intentional fallbacks for wrong container types.

Global settings

FieldTypeDefaultWhat it does
random_roll_countarray<object>[{count:1,weight:80},{count:2,weight:17},{count:3,weight:3}]Weighted line counts. Missing, non-array, empty or all-zero-weight lists use this fallback.
random_roll_count[].countinteger1Positive line count; cannot exceed the number of distinct eligible attributes actually available.
random_roll_count[].weightinteger0Non-negative; zero entries are removed.
random_requirement_rollobject{}Controls whether a random gem receives an equipment restriction.
random_requirement_roll.base_chancenumber0.42Finite probability 0–1; used outside a difficulty context and for missing difficulty overrides.
random_requirement_roll.dungeon_difficulty_chancesobject{}Difficulty-to-probability map, finite 0–1. Keys: common, uncommon, rare, epic, legendary, unique.
random_requirement_poolarray<object>[]Restriction candidates. Empty means no restriction can be rolled.
random_requirement_pool[].ididentifierrequiredUnique restriction ID; stored on the gem and used for its translation key.
random_requirement_pool[].weightinteger1Non-negative default weight. At least this or a difficulty override must be positive.
random_requirement_pool[].dungeon_difficulty_weightsobject{}Same difficulty keys; exact non-negative integer weights override the default.
random_requirement_pool[].matchobjectrequiredAt least one constraint is required; all populated groups must match.
random_requirement_pool[].match.itemsarray<item id>[]Any listed item; IDs are syntax-checked, not required to exist in the item registry.
random_requirement_pool[].match.all_tagsarray<tag id>[]Every listed item tag must match; leading # is accepted but not required.
random_requirement_pool[].match.any_tagsarray<tag id>[]At least one listed tag must match.
random_requirement_pool[].match.weapon_typesarray<string>[]At least one resolved weapon type; see the complete list below.
random_requirement_pool[].match.nbtarray<object>[]Every NBT predicate must match.
random_requirement_pool[].match.nbt[].pathstringrequiredNonblank dot-separated compound keys; empty segments and list indexing are unsupported.
random_requirement_pool[].match.nbt[].regexstringrequiredValid nonblank regular expression, at most 512 characters. Matches the complete value string; input over 4096 characters never matches.
insertobject{}Insertion settings; non-object uses defaults.
insert.base_successnumber0.85Finite 0–1, no greater than success_cap.
insert.success_capnumber0.95Finite 0–1 maximum insertion probability.
insert.crack_chance_on_failnumber0.2Finite 0–1 probability, rolled only after insertion fails.
insert.fatigueobject{}Equipment-wide insertion strain; non-object uses defaults.
insert.fatigue.maxinteger10Non-negative stored strain cap.
insert.fatigue.on_fail_addinteger1Non-negative strain added on a valid failed attempt.
insert.fatigue.on_success_changeinteger-2Non-positive strain change on success; resulting strain clamps to 0–max.
insert.fatigue.success_bonus_curveobject{}Non-object uses defaults.
insert.fatigue.success_bonus_curve.typeenum(LINEAR)LINEARTrimmed and case-insensitive; other curves reject the reload.
insert.fatigue.success_bonus_curve.per_fatiguenumber0.06Finite non-negative probability added per strain point.

Random and fixed attributes

FieldTypeDefaultWhat it does
attributeidentifierrequiredRandom definition: registered attribute ID; unique across random definitions.
domainenum(BASE, OFFENSE, DEFENSE, UTILITY, RESOURCE)requiredStat group for random and fixed definitions.
weightnumber1Random definition only: finite positive sampling weight.
damage_categoriesarray<enum(MELEE, RANGE, MAGIC)>[]Random, fixed and element definitions: missing, null or empty allows all categories.
operationsarray<object>requiredRandom definition: nonempty list; each operation name may occur only once.
operations[].nameenum(ADDITION, MULTIPLY_BASE, MULTIPLY_TOTAL)requiredAttribute operation; trimmed and case-insensitive.
operations[].minnumberrequiredFinite minimum rolled value.
operations[].maxnumberrequiredFinite maximum, at least min.
operations[].formatobject{decimals:2}Rounding format below; an integer shorthand is also accepted.
operations[].difficulty_scalingobject{}Optional multiplier formulas described below; a formula string is also accepted.
ididentifierrequiredFixed, element, skill, curse and consumable definitions: unique within that definition family.
itemitem idrequiredFixed, element, skill and consumable definitions: registered item; unique within that family. A fixed/element/skill item cannot belong to another of those gem families.
modifiersarray<object>requiredFixed definition: nonempty modifier list.
modifiers[].attributeidentifierrequiredRegistered attribute, unique within this fixed gem.
modifiers[].operationsarray<object>requiredNonempty list; operation names cannot repeat for this attribute.
modifiers[].operations[].nameenum(ADDITION, MULTIPLY_BASE, MULTIPLY_TOTAL)requiredSame operation names as random rolls.
modifiers[].operations[].valuenumberrequiredFinite fixed value, rounded by format.
modifiers[].operations[].formatobject{decimals:2}Same rounding format.
modifiers[].operations[].difficulty_scalingobject{}Same difficulty scaling format.

Value formatting and difficulty scaling

FieldTypeDefaultWhat it does
format.decimalsinteger20–6 decimal places; values are rounded, not merely displayed with fewer digits.
difficulty_scaling.formulastringabsentFallback multiplier formula.
difficulty_scaling.defaultstringabsentOverrides formula as the fallback.
difficulty_scaling.formulasobject{}Map of band names to formula strings; overrides earlier fallback keys.
difficulty_scaling.<band>stringabsentTop-level formula keys override formulas. Runtime bands: common, default, dangerous, mythic.
difficulty_scaling.min_multipliernumber0Finite non-negative lower bound; min is an alias.
difficulty_scaling.minnumber0Used only when min_multiplier is absent.
difficulty_scaling.max_multipliernumber1.7976931348623157E308Finite upper bound, at least the lower bound; max is an alias.
difficulty_scaling.maxnumber1.7976931348623157E308Used only when max_multiplier is absent.

Element and skill gems

FieldTypeDefaultWhat it does
schoolidentifierrequiredElement only: registered spell school. Full ID or case-insensitive school path resolves.
triggerenum(MELEE_HIT, RANGED_HIT, MAGIC_HIT, ON_HURT, ON_KILL, TRIGGERABLE)requiredElement and skill definitions. TRIGGERABLE is skill-only and requires proc.chance 1.
procobjectrequiredTrigger probability and per-socket cooldown.
proc.chancenumberrequiredFinite 0–1 probability.
proc.cooldown_ticksintegerrequiredNon-negative ticks; 20 ticks = 1 second.
damageobjectrequiredElement only: uniformly rolled damage range.
damage.minnumberrequiredFinite non-negative minimum.
damage.maxnumberrequiredFinite maximum, at least damage.min.
damage.formatobject{decimals:2}Same rounding format.
skillidentifierrequiredSkill only: an already registered triggerable skill.
costobject{}Skill only; missing or non-object means no energy cost.
cost.energyinteger0Non-negative astral energy cost.
scalingobjectabsentSkill-level scaling; missing or non-object disables it.
scaling.chance_addnumber0Finite probability added per non-negative skill level, then clamped 0–1; ignored for manual activation.
scaling.cooldown_multnumber0Finite non-negative reduction per skill level: round(base cooldown × max(0, 1 − value × level)).

Socket profiles

FieldTypeDefaultWhat it does
priorityinteger0Higher first; ties use ascending namespaced profile ID.
matchobject{}All populated groups combine with AND. Missing or non-object matches everything.
match.itemsarray<item id>[]Restrict to listed item IDs.
match.all_tagsarray<tag id>[]Require every tag.
match.any_tagsarray<tag id>[]Require at least one tag.
match.deny_itemsarray<item id>[]Reject listed items before positive checks.
match.deny_tagsarray<tag id>[]Reject if any listed tag matches.
socketsarray<object>[]Ordered socket slots. Missing or non-array produces no sockets.
sockets[].kindenum(ATTRIBUTE, FIXED, ELEMENT, SKILL)requiredAccepted gem family; mutable item state can override the kind.
sockets[].domainsarray<enum(BASE, OFFENSE, DEFENSE, UTILITY, RESOURCE)>[]Random/fixed restrictions; missing, null or empty permits all.
sockets[].damage_categoriesarray<enum(MELEE, RANGE, MAGIC)>[]Random/fixed/element definitions need at least one overlapping category. Empty permits all.
sockets[].schoolsarray<identifier>[]Element restrictions; missing, null or empty permits all registered schools.
sockets[].allowed_skillsarray<identifier>[]Skill restrictions; empty allows all. Every supplied ID must name a registered triggerable skill.
sockets[].min_item_levelintegerrequiredNon-negative equipment level required to unlock this slot.

Curses

FieldTypeDefaultWhat it does
multiplierobjectrequiredStrength range rolled when binding the curse.
multiplier.minnumberrequiredFinite, strictly greater than 1.
multiplier.maxnumberrequiredFinite, at least multiplier.min.
downsidesarray<object>requiredNonempty downside list.
downsides[].typeenum(attribute, status_effect, damage_taken_mult)requiredCase-insensitive downside kind; write the canonical form without surrounding whitespace.
downsides[].dataobject{}Per-kind fields below. Missing or non-object becomes empty and fails if required fields are absent.
downsides[].data.attributeidentifierrequired for attributeRegistered attribute.
downsides[].data.operationenum(ADDITION, MULTIPLY_BASE, MULTIPLY_TOTAL)required for attributeAttribute operation.
downsides[].data.valuenumberrequired for attribute / damage_taken_multFinite negative attribute value, or finite positive incoming-damage bonus. Both multiply by the stored curse strength.
downsides[].data.namestringise_curse_downsideAttribute modifier label.
downsides[].data.effectidentifierrequired for status_effectRegistered status effect.
downsides[].data.durationinteger40Positive status duration in ticks: 40 ticks (2 seconds) before curse scaling.
downsides[].data.amplifierinteger0Non-negative, zero-based effect amplifier; not multiplied by curse strength.
downsides[].data.ambientbooleanfalseAmbient effect display.
downsides[].data.show_particlesbooleantrueShow effect particles.
downsides[].data.show_iconbooleantrueShow effect icon.

Consumables

FieldTypeDefaultWhat it does
targetenum(EQUIPMENT, GEM, ANY)requiredEQUIPMENT requires a socket profile and a non-gem item; GEM requires a recognized gem; ANY accepts any nonempty stack.
success_chancenumber1Finite probability 0–1.
consume_ruleenum(ALWAYS, ON_SUCCESS, NEVER)ON_SUCCESSConsumption after a valid attempt; creative players are exempt.
on_successarray<object>[]Ordered actions for a successful roll. Missing or non-array means empty.
on_failarray<object>[]Ordered actions for a failed roll. At least one branch must contain an action.
on_success[].type / on_fail[].typeidentifierrequiredRegistered action ID from the table below.
on_success[].data / on_fail[].dataobject{}Action-specific data; missing or non-object becomes empty.
data.indexintegeraction-dependentZero-based socket index; the selection UI overrides it. Removal defaults to the last eligible filled socket; reroll defaults to eligible slots in order. State, kind and repair actions need an index.
data.countinteger2147483647reroll_socketed_random_gems: positive limit. UI selection supplies 1 when omitted.
data.break_chancenumber0remove_socketed_gem: finite 0–1 shatter probability. extract_safe forces 0.
data.lockedbooleanunchangedset_socket_state: explicit seal state; requires this or toggle_locked. Overrides the toggle result when both exist.
data.toggle_lockedbooleanfalseset_socket_state: toggle the seal of an empty, level-unlocked socket.
data.crackedbooleanunchangedset_socket_state: changes the crack flag alongside a required lock option; repair_crack removes it directly.
data.kindenum(ATTRIBUTE, FIXED, ELEMENT, SKILL)absentreroll_socket_kind: explicit replacement kind, takes precedence over pool; cannot equal current kind.
data.poolarray<enum(ATTRIBUTE, FIXED, ELEMENT, SKILL)>all kindsreroll_socket_kind: at least 2 distinct kinds if supplied; the current kind is removed before choosing.
data.ididentifierrandom configured curseapply_curse: configured curse ID; target must be uncursed.
data.amountinteger1reduce_insert_fatigue: positive reduction, floored at 0 remaining strain.

Enumerations and formulas

Weapon restrictions accept none, sword, rapier, greatsword, glaive, dagger, lance, scythe, axe, halberd, spear, mace, hammer, wand, staff, katana, chakram, gauntlet, boomerang, bow, crossbow, gun, magigun. Matching ignores case and surrounding whitespace. Unknown names reject the reload.

Formulas produce a multiplier, then the operation’s rounding format applies to base × multiplier. Variables areaLv and level both hold area level; base and value both hold the unscaled attribute value. Formula bands differ from the requirement-map keys:

Dungeon difficultyFormula band
common, uncommoncommon
rare, epicdefault
legendarydangerous
uniquemythic

A missing band falls back to default. Missing formulas, non-finite results and evaluation errors use multiplier 1; evaluation errors log at use, not reload. The bundled exp4j dependency evaluates formulas. Formula keys and expressions cross the network with limits of 64 and 512 characters respectively; stay within those limits even though loading does not enforce them. Scaling applies to random and fixed attributes, not element or skill gems.

Consumable actions

All IDs below use the isekaiexpansion: namespace. Action fields belong inside data.

ActionEffect
isekaiexpansion:reroll_random_linesReplace random attributes, values and target requirement.
isekaiexpansion:reroll_random_valuesKeep attributes, operations and requirement; reroll values.
isekaiexpansion:reroll_socketed_random_gemsReroll socketed random gems; locked or cracked slots are excluded.
isekaiexpansion:remove_socketed_gemRemove with break_chance; a lock blocks removal, a crack does not.
isekaiexpansion:extract_safeRemove with zero shatter probability.
isekaiexpansion:set_socket_stateChange an empty socket’s seal after its level unlock.
isekaiexpansion:reroll_socket_kindChange an empty, unlocked, uncracked socket to another kind.
isekaiexpansion:apply_curseBind a curse to an uncursed target.
isekaiexpansion:cleanse_curseRemove existing curse data.
isekaiexpansion:repair_crackRepair a cracked slot whose level requirement is met; a seal is allowed.
isekaiexpansion:reduce_insert_fatigueReduce positive equipment strain.

Eligibility is checked before rolling and consuming, against both branches. The chosen branch runs in order; successful earlier mutations are not rolled back if a later action does nothing. A successful roll with no applied action does not consume. A failed roll can consume under ALWAYS even with an empty failure branch. An empty target is never eligible. Registration alone does not add an eligibility rule for a new code action.

Curse attribute values and status durations scale by the stored multiplier. Incoming damage becomes damage × (1 + sum(value × curse multiplier)); status amplifiers do not scale. Multiple curses providing the same effect take the greatest duration and amplifier, combine ambient with OR, and particle/icon visibility with AND.

Full example

Save this as data/example/gem_attributes/random_roll/attack_damage.json after replacing or removing any other active random definition for this attribute. It follows the bundled random files’ structure; different filenames do not permit duplicate attribute IDs.

{
  "attribute": "minecraft:generic.attack_damage",
  "domain": "OFFENSE",
  "weight": 1,
  "damage_categories": [
    "MELEE"
  ],
  "operations": [
    {
      "name": "ADDITION",
      "min": 1,
      "max": 2,
      "format": {
        "decimals": 2
      },
      "difficulty_scaling": {
        "formula": "1 + areaLv * 0.02",
        "min_multiplier": 1,
        "max_multiplier": 2
      }
    }
  ]
}

Validation

  • Malformed, empty or non-object file: records a resource error and rejects the gem snapshot. Required arrays must be nonempty where specified.
  • Unknown registry ID: gem items, attributes, schools, effects and triggerable skills reject the reload. Profile and requirement item/tag filters validate syntax only; an absent optional-mod item remains a non-match.
  • Duplicate definition: random attribute IDs, same-family definition IDs, same-family item IDs and cross-family fixed/element/skill item reuse reject the reload. Equal-priority profiles are allowed and sort by ID.
  • Invalid range: finite, probability and positive checks reject rather than clamp. Some integer fields use numeric conversion; supply integers explicitly. Difficulty weight maps additionally reject fractional values and duplicate keys differing only in case.
  • Removed fields: insert.cost_curve rejects; use insert.crack_chance_on_fail. Element extras rejects; use typed element fields.
  • Conditional compatibility: Fabric’s fabric:load_conditions is checked before gem fields. A failing condition excludes the file; failing settings conditions use defaults. Condition syntax belongs to Fabric. Passing conditions do not relax registry validation.

Unknown action-data keys are normally ignored; set_socket_state copies unrecognized keys into saved state. Wrong optional action-data types can bypass readers and fall back rather than fail. JSON action data becomes NBT: booleans become bytes, integral in-range numbers become integers, other numbers become doubles, and null becomes an empty string. Use homogeneous arrays.

A restriction translates as gem_requirement.<namespace>.<path>, with path slashes changed to dots. Removing its definition leaves existing gems with that ID unable to match equipment; it does not remove the restriction.

Reloading

Resources load on the server resource reload. Joining sends the active snapshot; a successful data-pack reload broadcasts it to connected clients. Replacement clears the item-to-profile cache. A gem-local validation failure retains its previous snapshot; this is not a transaction across unrelated reload listeners.

Existing item NBT remains separate. Reloading does not reroll stored random values. It can change compatibility, fixed-definition values and the profile selected for an item. Reducing a profile’s socket count can discard excess saved slots when a mutating operation normalizes the item; inspect occupied equipment before making that change.

Gems and sockets explains the player loop. Gem runtime covers item NBT, integration and verification.