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. Most class powers are passive or condition-gated, but a class may also carry an active power.
A class gets one keybind slot. The class layer does not use the six skill slots that the origin layer does. Instead, the first active power in a class’s powers list is bound to the dedicated Class Skill key (default H), shown as C in the HUD when the key is unbound. Every later active power in the same class is silently left unbound, so if you want two of them, only the first one will ever fire.
The built-in Step Assist switch on the Explorer, Rogue and Scout is the worked example: a hidden neoorigins:toggle holds the state, an neoorigins:active_ability flips it, and the step-height attribute_modifier is gated on the toggle.
That pattern (a hidden toggle plus an active that flips it) is the intended way to give a class a switchable passive, because it keeps the passive itself condition-gated while spending only the one class slot.
The Rogue is the one built-in class that wants two: it carries both the Step Assist switch and class_rogue_stealth. Step Assist is listed first and holds the key, so Stealth has none. Both powers are still granted, and because a toggle no key can reach is switched back on at every login (see the toggle notes in POWER_TYPES.md), the Rogue’s Stealth is simply always on: sneak for ten seconds and you turn invisible. A Rogue who switched Stealth off before 2.2.28 gets it back the next time they log in.
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
A file at the exact built-in path data/neoorigins/origins/origin_layers/class.json is merged with the built-in one like any other same-id layer file (its origins are appended). To replace the list entirely, add "replace": true; you must then 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: the built-in classes use"none", except Fisher, Mason and Paladin, which use"medium".order: position in the class screen (built-ins occupy 1–20; use 21+ to append after them).powers: passive, condition-gated or attribute powers, plus at most one active power, which takes the Class Skill key (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.
Stacking with the origin layer
A class and an origin are separate layers, and their powers add together; neither replaces the other. A player who is a Golem (origin, 1.3x size) and a Titan (class, 1.25x size) ends up 1.55x, and re-picking either layer leaves the other layer’s contribution alone. The same holds for attribute_modifier bonuses: health, armor and reach from the origin survive a class change.
Design classes on that assumption. If a class is meant to be an alternative to something an origin already grants rather than an addition to it, express that with a condition on the class power, not by expecting it to overwrite the origin’s.
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 stay registered (so/neoorigins setcan still assign them) but are hidden from the selection screen. - No classes at all: if every class is disabled, the class selection screen is skipped entirely and only the origin layer is shown.
- Skip initial selection: the
[skip_initial_selection]section inconfig/neoorigins/gameplay.tomlhas anenabledflag (defaultfalse). When set totrue, new players spawn with no origin and the selection screen never opens on first join; they play as an origin-less player until granted one later (for example via an Orb of Origin or/neoorigins set). Unlike auto-human mode this assigns nothing; the player’s selection is marked complete, so the join check doesn’t re-prompt on every relog. It takes priority over auto-human and random-assignment modes.
The Orb of Origin
neoorigins:orb_of_origin re-picks only the neoorigins:origin layer. Right-clicking it reopens the selection screen scoped to that layer alone, so the player’s class (and any other layer) is kept: changing class is the Orb of Class’s job. Any sub-layer whose conditions no longer pass under the new origin is cleared automatically. Like the Orb of Class the commit is deferred, so closing the picker without choosing is a free cancel (the orb is refunded and the previous origin restored). Cost comes from the [orb_of_origins] section of config/neoorigins/gameplay.toml: with scale_cost = true (the default) it is levels_per_use (default 5) times the player’s previous orb uses, so the first use is free; with scale_cost = false every use costs levels_per_use.
The Orb of Class
neoorigins:orb_of_class is the cheaper, class-only sibling of the Orb of Origin. Right-clicking it resets only the neoorigins:class layer and reopens the picker scoped to just that layer: the player’s main origin is kept, so only the class screen is shown.
- Cost: a flat XP-level cost, configured by
class_levels_per_usein the[orb_of_origins]section ofconfig/neoorigins/gameplay.toml(default2). Unlike the Orb of Origin’slevels_per_use(default5, which can ramp with prior uses), the class cost never scales. Creative players pay nothing. - Deferred commit: the XP is charged and the orb is consumed only when the player actually picks a new class. Closing the picker without picking is a free cancel: the orb is refunded and the previous class is restored.
- No class yet: using the orb before a class has been chosen does nothing (there is no class to reset).
Reopening the picker for arbitrary layers
The Orb of Class is one preset of a general mechanism: the picker can be reopened for any layer subset, not just the class layer. Two author paths expose it:
- Datapack action
neoorigins:open_layer_picker: give any power (item use, keybind, on-hit, …) alayerslist to re-pick, withcommit_mode(deferred/immediate), an XPcost, an optionalmessageshown when the picker opens, andconsume_itemto spend the triggering item on commit. This lets a pack build its own re-pick items or powers for whatever layers it defines. - Admin command
/origin gui <player> <layers>: opens the picker scoped to one or more comma- or space-separated layers for a single target player (permission level 2).
Recipe
Same shape as the Orb of Origin, but with ingots instead of blocks:
G D G G = minecraft:gold_ingot
D N D D = minecraft:diamond
G D G N = minecraft:netherite_ingot
See also
- PACK_FORMAT.md: Origin JSON, Power JSON, Layer JSON
neoorigins:open_layer_picker: reopen the picker for the class layer (or any other layer subset) from a power, the mechanism the Orb of Class is a preset ofexamples/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