Custom Classes
In NeoOrigins, a class is not a separate system — it’s an ordinary origin that lives in the special neoorigins:class layer. Every player picks an origin (layer 1) and a class (layer 2); the class screen is the second selection screen shown on first join.
Because a class is just an origin, everything in PACK_FORMAT.md about Origin JSON and Power JSON applies directly. This page covers only what’s class-specific.
The class layer
The built-in class layer is defined at data/neoorigins/origins/origin_layers/class.json with order: 2. Classes are intentionally passive: all built-in class powers are passive or condition-gated, so a class never consumes a keybind slot. Keep custom classes to passive/attribute/condition powers — active (keybinded) powers in the class layer are not the intended design and the class power list is treated as always-on, not slotted.
Adding a class (recommended: additive layer file)
You do not need to edit the built-in class.json. Any layer file whose path is class is automatically folded into neoorigins:class, regardless of namespace. So ship your own:
data/<yourpack>/origins/origin_layers/class.json
{
"name": "origins.layer.class",
"origins": [
"yourpack:class_alchemist"
]
}
Your class is appended to the existing list — all built-in classes are kept, and you never have to maintain a copy of the mod’s list. (Opt out of the fold with "standalone": true if you deliberately want a separate screen.)
Alternative: overriding the built-in layer
You can place a file at the exact built-in path data/neoorigins/origins/origin_layers/class.json, but this replaces the list entirely — you must re-list every built-in class you want to keep, and re-sync on every mod update. Prefer the additive method above unless you specifically want to remove built-in classes (the [classes] config toggles are usually the better tool for that).
The class origin JSON
Identical to any origin (data/<yourpack>/origins/origins/<id>.json). Conventions used by the built-ins:
{
"name": "origins.yourpack.class_alchemist.name",
"description": "origins.yourpack.class_alchemist.description",
"icon": "minecraft:brewing_stand",
"impact": "none",
"order": 21,
"powers": [
"yourpack:class_alchemist_resilience",
"yourpack:class_alchemist_antidote"
],
"upgrades": []
}
icon— item shown in the class picker.impact: "none"— classes don’t carry an origin “impact” rating; alwaysnone.order— position in the class screen (built-ins occupy 1–20; use 21+ to append after them).powers— passive/condition powers only (see above).upgrades— optional advancement-driven promotion to another class; see the workingexamples/class_tier_up/datapack and the Upgrades section of the examples README.
Naming convention: prefix the origin id and its powers with class_ (class_alchemist, class_alchemist_resilience). Not required by the code, but it keeps packs consistent with the built-ins.
Lang keys
Same derivation as any origin/power:
origins.<namespace>.<class_id>.name/.descriptionpower.<namespace>.<power_id>.name/.description
Or use literal components ({"text": "Alchemist"}) directly in the JSON if you don’t want a resource/language pack — handy for self-contained datapacks.
Defaults and config
- No class chosen: if a player closes the picker with an origin but no class, NeoOrigins auto-assigns
neoorigins:class_nitwit(a deliberate no-effect default) so starting equipment and pending grants still resolve. - Disabling built-ins: the
[classes]section inconfig/neoorigins/content.tomltoggles each built-in class. Disabled classes are removed after data load (still assignable via/neoorigins set). - No classes at all: if every class is disabled, the class selection screen is skipped entirely and only the origin layer is shown.
See also
- PACK_FORMAT.md — Origin JSON, Power JSON, Layer JSON
examples/class_tier_up/— class promotion via advancement upgradesexamples/custom_class/— a complete copy-paste custom class- SUB_ORIGINS.md — conditioned layer entries (also work in the class layer)
- EVOLUTION.md — how essence evolution interacts with the class layer