Repository navigation
KubeJS Atlas Builder
English | 中文
Use the builder inside SkillAtlasEvents.definitions. Scripts work on a staged copy of the base atlas (config/skill_atlas/atlas.json). The result is fully validated before it becomes the effective atlas.
SkillAtlasEvents.definitions(event => {
event.createNode('pack_harvest_health')
.name('Farmer Constitution')
.category('farming')
.icon('minecraft:golden_carrot')
.position(0, 0)
.level(1, rank => {
rank.cost({ type: 'skill_points', amount: 1 })
rank.attributeReward('minecraft:generic.max_health', 2, 'add')
})
})| Method | Purpose |
|---|---|
createNode(id) / createCategory(id) / createPool(id)
|
Create and return a builder |
modifyNode(id, callback) / modifyCategory(id, callback) / modifyPool(id, callback)
|
Edit an existing object |
removeNode(id) / removeCategory(id) / removePool(id)
|
Remove an object |
hasNode(id) / getNodeIds() / getSnapshot()
|
Inspect the staged atlas |
Builders close when the event callback ends. Writing through a builder you kept for later throws an error.
| Method | Meaning |
|---|---|
category(id) |
Category of the node |
name(text) / description(text)
|
Name and tooltip text |
icon(itemIdOrIconObject) |
'minecraft:diamond' or e.g. {type:'texture', id:'minecraft:textures/item/diamond.png'}
|
position(x, y) |
Canvas position |
hidden(boolean) |
Hide until the prerequisites are met |
requireAll(boolean) |
true: all prerequisites; false: any prerequisite |
requires(id) |
Requires at least level 1 of id
|
requiresLevelGreaterThan(id, level) |
Requires a level strictly greater than level
|
clearPrerequisites() |
Remove all prerequisites |
choiceGroup(groupId) |
Put the node into a choice group; '' removes it |
condition(typeId, data) / clearConditions()
|
Custom conditions for every learnable level |
level(n, callback) |
Create or edit level n (starting at 1) |
clearLevels() |
Remove all levels, including their custom declarations |
json(patch) |
Merge raw node JSON fields |
requiresLevelGreaterThan('haste', 2) means at least level 3.
Levels start at 1 and must be contiguous. Each level's rewards apply only while that level is the current one. They do not stack with lower levels, so if level 2 should give +2 in total, write amount = 2 on level 2.
Nodes that share the same choice group ID are mutually exclusive. Once a player learns any node in the group, the other nodes in that group are locked with the state Excluded. They become learnable again when the learned node is reset to level 0.
SkillAtlasEvents.definitions(event => {
event.createNode('warrior_path').category('combat').choiceGroup('class').level(1, r => r.cost({ type: 'skill_points', amount: 1 }))
event.createNode('mage_path').category('combat').choiceGroup('class').level(1, r => r.cost({ type: 'skill_points', amount: 1 }))
})- Group IDs follow the node ID rule: lowercase, no colon, at most 64 characters.
- Groups are atlas-wide. Nodes in different categories can share a group.
- A node that is already learned is never locked by its group. If two nodes were learned before the group was added, both stay learned and can still be upgraded.
- The check runs on the server. Blocked attempts fail with code
choice_excluded. - Map editors can set the same field in the in-game node editor (Choice group) or in JSON as
"choice_group".
| Method | Meaning |
|---|---|
cost({type, amount}) |
type is 'skill_points' or 'experience' (actual experience points) |
item(itemId, count[, nbtOrComponents]) |
Required delivery item |
clearItems() |
Remove delivery items |
attributeReward(attribute, amount, operation) |
Attribute modifier reward |
effectReward(...) / immunityReward(...) / commandReward(...)
|
Native reward types |
reward(json) |
Any native reward JSON, or {type:'pack:type', data:{...}} for a custom reward |
clearRewards() |
Remove native rewards only |
condition(typeId, data) / clearConditions()
|
Custom conditions for this level |
customReward(typeId, data) / clearCustomRewards()
|
Custom rewards for this level |
json(patch) |
Merge raw level JSON fields |
The field holding delivery item data is still called nbt. On 1.20.1 it is a full item NBT condition. On 1.21.1 and 26.1.2 it is Skill Atlas's component patch format. Old NBT strings cannot be reused unchanged on newer versions.
| Method | Meaning |
|---|---|
name(text) / icon(...)
|
Display |
pool(poolId) |
Point pool; '' means no pool, so costs fall back to actual experience |
background(textureId, tiled) |
Canvas background |
json(patch) |
Raw JSON fields |
| Method | Meaning |
|---|---|
name(text) / description(text) / color(rgb) / initial(points)
|
Display and initial points |
acquisition(method, count, points, limit) |
Native rule: kill, mine, harvest, craft, smelt, fish, movement, advancement, playtime
|
targets(array) |
Targets of a native rule, e.g. ['#minecraft:crops']
|
customAcquisition(typeId, data, count, points, limit) |
Bind to a registered acquisition type |
json(patch) |
Raw JSON fields |
Custom pools do not accept native targets. Switching back to a native acquisition, or setting method through json, removes the custom binding.
json merges top-level fields and replaces arrays as a whole. It cannot change the object's ID. The result still goes through the full native parser, so every native field works: shape, size, aliases, prerequisite lines, background images and so on. Ranges and totals are the same as for the base atlas. Nothing is relaxed for scripts.
KubeJS (English)
- Getting Started
- Events
- Server API
- Atlas Builder
- Custom Types and Costs
- Client API
- Reload and Editor
- Examples
KubeJS(中文)