Content Types & Merging
What packs can extend, and how pack content combines with the defaults and the server owner's files
How merging works
- By id, additive. Each content entry has an id. A pack entry with a new id adds content; an entry whose id already exists overrides it. If two packs define the same id, the last-loaded pack wins.
- The server owner always wins. Content the owner authored locally (their own files under
mods/mmoskilltree/) is never overridden or dropped by a pack. - Defaults < pack < owner. Packs override the plugin's built-in defaults, but not the owner's explicit customizations.
Add vs. replace (the Control file)
By default a pack adds to existing content. To make a pack replace the built-in defaults for a content type (e.g. a total-conversion quest pack), include a control file at Server/MMOSkillTree/Control/<YourPackName>.json:
{
"Name": "MyMmoPack",
"Quests": "replace",
"Achievements": "add"
}replace drops the plugin's default content for that type and uses the pack's instead — but the server owner's own authored content is still kept and still wins. The Name must match your manifest Name.
Valid type keys (PascalCase, like all asset JSON keys): Quests, Achievements, XpMaps, MobKillXp, LuckLoot, ItemRequirements, ActionRequirements, BoostTemplates, Masteries, Currencies, CommandRewards, Classes, UIThemes. If your pack ships templates, also add the matching template store (MasteryTemplates, QuestTemplates, AchievementTemplates, CommandRewardTemplates, ClassTemplates) as "add".
Feature gating (requiresFeatures)
Quests and achievements can declare a dependency on one or more server features. When any listed feature is disabled, the entry is hidden everywhere — it does not appear in the UI, accrues no progress, and cannot be claimed. Re-enable the feature (config flip + server restart) and the entry returns.
{
"Name": "mastery_tithe",
"Payload": {
"id": "mastery_tithe",
"displayName": "Mastery Tithe",
"requiresFeatures": ["mastery"],
"objectives": [ { "id": "kill", "type": "KILL_ENTITY", "target": "*", "amount": 10 } ],
"rewards": [ { "type": "CURRENCY", "currencyId": "mastery_point", "amount": 1 } ]
}
}| Feature id | Gates on |
|---|---|
mastery | Mastery system enabled |
abilities (alias active_abilities) | Active abilities enabled |
currency (alias currencies) | Currency system enabled |
elite_mobs (alias elites) | Elite mobs enabled |
xp_tokens (alias tokens) | XP tokens enabled |
command_rewards | Command rewards enabled |
item_requirements | Item requirements enabled |
action_requirements | Action requirements enabled |
- Lenient parse. Either a bare string (
"mastery") or an array is accepted. - AND-combined. When multiple ids are listed, the entry is hidden if any one is off.
- Templates inherit. A template's
requiresFeaturesapplies to every entry that extends it; a concrete entry can override it (or set[]to ungate). - Unknown ids fail closed. An unrecognized feature id hides the entry and logs a one-time
Unknown feature idwarning at server start.
File formats
All content lives under Server/MMOSkillTree/<Type>/. Files may be nested in subfolders freely. Two payload styles are used.
Per-entry "payload" types
One file per entry; the asset key is derived from the filename (e.g. dragon_hunt.json → dragon_hunt), and the top-level Name field echoes that key. Payload is the entry as a nested JSON object.
| Type | Folder | Payload | Docs |
|---|---|---|---|
| Quests | Quests/ | A single quest object | Quests config |
| Achievements | Achievements/ | A single achievement object | Achievements |
| Masteries | Masteries/ | A single mastery-track object | below |
| Currencies | Currencies/ | A single currency-definition object | below |
| Classes | Classes/ | A single class-definition object | below |
| UI Themes | UIThemes/ | A theme palette + per-class accents + optional template overrides | — |
Per-pack "map" types
One file per pack; Name is your pack name and Payload is the config's natural map.
| Type | Folder | Payload shape | Docs |
|---|---|---|---|
| XP maps | XpMaps/ | { "SKILL": { "pattern": value } } | XP Values |
| Mob-kill XP | MobKillXp/ | { "MobPattern": value } | Mob Kill XP |
| Luck loot | LuckLoot/ | { "BlockPattern": "ItemId" } | Luck |
| Item requirements | ItemRequirements/ | { "ItemPattern": { …override… } } | Item Requirements |
| Action requirements | ActionRequirements/ | { "blockTool": {…}, "mobWeapon": {…} } | Item Requirements |
| Boost templates | BoostTemplates/ | { "templateId": { "multiplier": … } } | XP Boosts |
| Command rewards | CommandRewards/ | { "<SKILL|TOTAL|GLOBAL_SKILL>": { "<level>": [ … ] } } | Command Rewards |
// Server/MMOSkillTree/XpMaps/MyMmoPack.json
{
"Name": "MyMmoPack",
"Payload": { "MINING": { "Ore_Adamantite": 25.0 } }
}Masteries
A mastery track targets a skill (skill:MINING) or an ability (ability:fireball) and lists purchasable nodes. Each node has an id, tier, cost (a currency map plus optional raw items and an optional stat sacrifice), and modifiers. Repeatable Eternal nodes set maxPurchases: -1 with costScaling. See the player-facing Mastery guide for how this looks in-game.
// Server/MMOSkillTree/Masteries/Mining_Mastery.json
{
"Name": "Mining_Mastery",
"Payload": {
"target": "skill:MINING",
"displayName": "Mining Mastery",
"refundPercent": 50,
"requirements": { "skillLevels": [ { "skill": "MINING", "level": 5 } ] },
"nodes": [
{
"id": "min_t1", "tier": 1, "displayName": "Mining Mastery I",
"cost": {
"combine": "all",
"currencies": { "mastery_point": 2, "life_essence": 500 },
"items": [ { "id": "Ingredient_Crystal_Blue", "count": 1 } ]
},
"modifiers": [ { "shape": "PERCENT", "key": "lootMultiplier", "value": 0.03, "targetSkill": "MINING" } ]
},
{
"id": "min_eternal", "tier": 9, "displayName": "Mining Mastery: Eternal",
"maxPurchases": -1,
"costScaling": { "mode": "EXPONENTIAL", "multiplier": 1.1 },
"cost": { "combine": "all", "currencies": { "mastery_point": 1, "life_essence": 200 } },
"modifiers": [ { "shape": "PERCENT", "key": "lootMultiplier", "value": 0.005, "targetSkill": "MINING" } ]
}
]
}
}Currencies
Currencies come in two flavors. Counter-backed currencies are a number stored on the player (no inventory item) — set iconItemId for the display icon and leave hytaleItemId unset. Item-backed currencies wrap a real Hytale item — set hytaleItemId to the item id. The currency id is the filename, lowercased. See the player-facing Currencies guide.
// Counter-backed — Server/MMOSkillTree/Currencies/Mastery_Point.json
{
"Name": "Mastery_Point",
"Payload": {
"displayName": "Mastery Points",
"iconItemId": "Ingredient_Crystal_Purple",
"color": "#c08aff",
"cap": 0,
"showOnSidebar": true,
"showOnMasteryPage": true
}
}
// Item-backed — Server/MMOSkillTree/Currencies/Life_Essence.json
{
"Name": "Life_Essence",
"Payload": {
"displayName": "Life Essence",
"hytaleItemId": "Ingredient_Life_Essence",
"color": "#a7e0a7",
"cap": 0
}
}Grant currency from quests/achievements (CURRENCY reward), from command rewards, or from the admin command. Always use the named-arg form:
/mmocurrency give --player={player} --currency=mastery_point --amount=1Classes
The plugin ships no built-in classes — without a class pack the class system stays dormant. A class definition carries base grants applied while the class is selected, plus additive advancements (ranks) unlocked by meeting prerequisites.
| Field | Type | Notes |
|---|---|---|
displayName / flavor / description / icon | string | UI surface; icon is a Hytale item id. |
unlockRequirements | PrerequisiteGroup | Gate selection (quests, skill levels, total level, achievements, currency). Empty = freely selectable. |
switchPolicy | SwitchPolicy | Per-class override of the global switch cost/cooldown. |
baseGrants | ClassGrants | Applied while the class is selected. |
advancements | ClassAdvancement[] | Additive ranks; grants deep-merge over base. |
ClassGrants (used by base and each advancement):
| Field | Notes |
|---|---|
xpMultipliers | map of skill → multiplier (0.0 = no XP, 1.25 = +25%). |
abilityWhitelist / abilityBlacklist | Gate which abilities are usable. Blacklist always wins. |
masteryWhitelist / masteryBlacklist | Gate mastery purchases (by trackId or trackId:nodeId). |
skillRewardWhitelist / skillRewardBlacklist | Gate skill-tree reward claims. |
passiveRewards | SkillRewards applied while the class is active. |
startingItems / startingMasteryNodes / classQuests | Granted/unlocked on selection. |
SwitchPolicy defaults: firstSwitchFree: true, costCurrencyId: "mastery_points", costAmount: 100, cooldownMs: 24h, escalationMultiplier: 1.0, permanentLock: false. Build classes from a template — see Template Extension. Verify in-game with /mmoclass list and /mmoclass select --id=<class>.
Export as Pack
The in-game Export as Pack tool (/mmopacks export) generates a correctly-formatted pack from your current server content — the recommended starting point, since it emits valid filenames, Name echoes, and Payload shapes for you.