Skip to main content

KubeJS Examples

These scripts show a complete setup: a startup script registers the content items, and server scripts attach rules and react to events. See the API Reference for every method used here.

Registering Items and Recipes

StartupEvents.registry('item', event => {
event.create('spirit_manual').displayName('Nameless Cultivation Manual')
event.create('spirit_stone').displayName('Spirit Stone')
})

ServerEvents.recipes(event => {
event.shaped('example:spirit_manual', ['ABA', ' C ', 'ABA'], {
A: 'minecraft:paper',
B: 'minecraft:lapis_lazuli',
C: 'minecraft:book'
})
})

The item is registered by KubeJS, so the rest of the mod sees it as a normal item and can bind rules to its real item ID.

Reacting to Events

// kubejs/server_scripts/mxt_events.js
MxtEvents.abilityUse(event => {
if (event.isPre() && event.getAbility() === 'example:forbidden') event.cancel()
})

MxtEvents.resourceConsume(event => {
if (event.isPre()) event.setAmount('example:spirit_power', event.getAmounts()['example:spirit_power'] || 0)
})

MxtEvents.cultivationBreak(event => {
if (event.getPhase() === 'Pre') {
// event.getEvent() is the native CultivationBreakEvent.Pre.
event.getEvent().setCost('example:spirit_power', 20)
}
})

The matching data pack can bind example:spirit_manual to a technique and hook example:spirit_stone into item_aura or currency. That way the script only registers content, while the rules can still be hot-reloaded and synchronised.

Defining a Script Action

Register the callback under a namespaced ID in a server script:

MxtActions.entity('example:heal', (entity, params) => {
entity.heal(params.amount || 1)
})

Any matching data pack field can then use it through the pre-registered mxt:js type:

{
"type": "mxt:js",
"id": "example:heal",
"params": { "amount": 4 }
}

Running a Built-in Action from a Script

MxtActions.executeEntity(player, {
type: 'mxt:heal',
amount: 4
})

The definition object has the same shape as a single action inside a data pack, so any built-in action type works here.

Testing a Built-in Condition

const enoughQi = MxtConditions.testEntity(player, {
type: 'mxt:resource_compare',
resource: 'mxt:spirit_power',
comparison: '>=',
value: 10
})

Evaluating Number Providers

const levelScaled = MxtValues.evaluateNumber(player, {
type: 'mxt:expression',
expression: 'level * 2 + 1'
})
const actualAura = MxtValues.evaluateResource(player, 'mxt:spirit_power', {
type: 'mxt:actual_concentration'
})

Paying Several Resources Atomically

const result = MxtResources.consume(player, [
{ resource: 'mxt:spirit_power', amount: 10 },
{ resource: 'mxt:fire_aura', amount: 'level + 2' }
])

if (result.committed()) {
console.info(`Deducted: ${result.amounts()}`)
} else {
console.warn(`Insufficient resource: ${result.failedResource()}`)
}

When any one of the resources is insufficient, none of them is deducted. Note that a ResourceCost uses the resource field, while only the cost API may use the id shorthand:

// Consume a resource. Full form.
{ type: 'mxt:resource', resource: 'mxt:spirit_power', amount: 10 }

// Consume a resource. Compatible shorthand; only the cost API may use the id field.
{ id: 'mxt:spirit_power', amount: 10 }

// Consume items. items accepts an item ID, an item tag, or an ItemMatcher object.
{ type: 'mxt:item', items: ['minecraft:emerald', '#c:mystic_gems'], amount: 2 }

Casting an Ability

const result = MxtAbilities.use(player, 'example:fireball')
if (result.failure() !== null) console.warn(String(result.failure()))

Only an ability the entity already holds can be cast this way, and the call only takes effect on the server.