Skip to main content

KubeJS API Reference

The MiXianTu KubeJS bridge provides a separate object per domain; it does not provide a Mxt root object carrying every method. All APIs that change game state must be called from kubejs/server_scripts/, and they enter the mod's existing server transactions and event flow.

The identifiers below — id, resource, ability, curse, zone and so on — are all namespaced strings, for example mxt:spirit_power or example:fireball. Passing an invalid identifier, or JSON that cannot be decoded by the matching codec, throws a script error directly, so that data problems can be located.

Overview

GlobalResponsibility
MxtActionsRegister mxt:js action callbacks, or run a built-in action.
MxtConditionsRegister mxt:js condition callbacks, or test a built-in condition.
MxtValuesRegister or evaluate number providers and resource value providers.
MxtCostsCheck or pay a single complete Cost.
MxtResourcesPay several resource costs atomically.
MxtAbilitiesCast an ability the entity already holds.
MxtCultivationAdd cultivation progress and attempt a realm breakthrough.
MxtCursesApply or explicitly remove a curse.
MxtAuraQuery, add and remove server-side aura areas.
MxtSoulsReclaim the transferable soul of an entity.
MxtEventsEvery MiXianTu server lifecycle event.

Entity, LivingEntity, Player, Level, BlockPos, ItemStack and DamageSource are all vanilla Java objects exposed by KubeJS. A JsonObject/JsonElement parameter accepts a plain JavaScript object or array.

Common Data Rules

Number Provider

Every parameter that is a number provider, such as amount or value, accepts the following forms:

10 // constant
'level * 2 + 1' // formula
{ type: 'mxt:uniform', min: 1, max: 3 } // built-in typed object

The formula context is created automatically by the called API from the entity or the level. The result computed by a script callback or a provider must be a finite number; NaN, Infinity, an exception or a callback that is not registered is logged and treated as 0.

mxt:js Callback Definitions

Actions, conditions, number providers and resource value providers all have a pre-registered mxt:js type. First register the callback in a server script:

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

Then use it in any matching data pack field:

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

An id is unique within the same callback category. KubeJS clears every callback before reloading server scripts and then re-runs the scripts, which register them again; do not put a registration in a client script that only runs once. When no callback is found, an action does not run, a condition returns false, a value returns 0, and a warning is logged.

MxtActions

Registering a Script Action

MethodCallback parametersPurpose
entity(id, callback)(entity: Entity, params: object)Registers an entity action.
biEntity(id, callback)(actor: Entity, target: Entity, params: object)Registers a bi-entity action.
block(id, callback)(level: Level, pos: BlockPos, params: object)Registers a block position action.
item(id, callback)(holder: Entity, stack: ItemStack, params: object)Registers an item action.

All four callbacks correspond to type: "mxt:js" in a data pack. An exception thrown by a callback is caught and written to the error log; the current action is aborted, but the server does not crash.

Running Any Built-in Action Directly

MethodParametersReturn valueDescription
executeEntity(entity, definition)Entity, entity action JSONvoidDecodes and runs it through EntityAction.CODEC.
executeBiEntity(actor, target, definition)Two Entity, bi-entity action JSONvoidUses actor as the formula context subject.
executeBlock(level, pos, definition)Level, BlockPos, block action JSONvoidUses the level as the formula context.
executeItem(holder, stack, definition)Entity, ItemStack, item action JSONvoidUses the holder as the formula context subject.

definition is an action object whose format is exactly the same as a single action inside a data pack, and its type goes through the existing built-in registry dispatch:

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

MxtConditions

Registering a Script Condition

MethodCallback parametersReturn value
entity(id, callback)(entity, params)boolean
biEntity(id, callback)(actor, target, params)boolean
block(id, callback)(level, pos, params)boolean
item(id, callback)(holder, stack, params)boolean
damage(id, callback)(source: DamageSource, amount: number, params)boolean

They correspond to the mxt:js built-in types of the Entity, BiEntity, Block, Item and Damage conditions respectively. Returning true means the condition is met; an unregistered condition and a callback that throws are both treated as false.

Testing Any Built-in Condition Directly

MethodParametersReturn valueDescription
testEntity(entity, definition)Entity, entity condition JSONbooleanDecodes EntityCondition.CODEC.
testBiEntity(actor, target, definition)Two Entity, bi-entity condition JSONbooleanThe formula context comes from actor.
testBlock(level, pos, definition)Level, BlockPos, block condition JSONbooleanThe formula context comes from the level.
testItem(holder, stack, definition)Entity, ItemStack, item condition JSONbooleanThe formula context comes from the holder.
testDamage(level, source, amount, definition)Level, DamageSource, damage amount, damage condition JSONbooleanUses the formula context of the direct source entity when there is one, otherwise an empty context.
const enoughQi = MxtConditions.testEntity(player, {
type: 'mxt:resource_compare',
resource: 'mxt:spirit_power',
comparison: '>=',
value: 10
})

MxtValues

Registering a Script Provider

MethodCallback parametersReturn valuePurpose
number(id, callback)(context: FormulaContext, params: object)Finite numbermxt:js number provider.
resourceValue(id, callback)(holder: ResourceHolderAttachment, resource: Holder<Resource>, context: FormulaContext, params: object)Finite numbermxt:js resource value provider.

FormulaContext exposes:

MethodDescription
context.value(name)Gets an explicit context variable or a registered formula variable.
context.contains(name)Whether the variable is available.
context.player()Returns the current player, or null when there is none.
context.variables()Returns the current explicit variable map.
context.random()Returns the authoritative random source used by this evaluation.

In resourceValue, holder is the resource attachment and resource is the resource holder; they are normally used read-only, for example holder.get(resource). Do not use this callback to write state.

Evaluation

MethodParametersReturn valueDescription
evaluateNumber(entity, definition)Entity, number provider objectnumberEvaluates any registered provider. A non-finite result returns 0.
evaluateResource(entity, resource, definition)LivingEntity, resource ID, resource value provider JSONnumberEvaluates the value of the given resource. An entity-aware provider reads the environment/actual aura at the current position.
const levelScaled = MxtValues.evaluateNumber(player, {
type: 'mxt:expression',
expression: 'level * 2 + 1'
})
const actualAura = MxtValues.evaluateResource(player, 'mxt:spirit_power', {
type: 'mxt:actual_concentration'
})

MxtCosts and MxtResources

MxtCosts

MethodParametersReturn valueDescription
check(player, definition)Player, one Cost JSONbooleanOnly checks; does not change the inventory or resources.
consume(player, definition)Player, one Cost JSONbooleanChecks first and then pays; when it cannot be paid nothing is changed.

Full cost registry dispatch is supported. The current built-in types:

// 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 }

A single Cost is the safe entry point; for several resources use MxtResources.consume below, which has atomic transaction semantics. Do not treat several MxtCosts.consume calls as one atomic payment.

MxtResources

MethodParametersReturn valueDescription
consume(entity, costs)Entity, ResourceCost[]ResourceTransactions.ResultPays a group of resources atomically; when any one of them is insufficient, none of the group is deducted.

Each element of costs follows the ResourceCost format, and its field name is resource, not id:

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()}`)
}

The accessors of the returned record are committed(), failedResource() and amounts(). On the client, with an invalid formula, or when the resources are not satisfied, committed() is false.

Runtime Domain APIs

MxtAbilities

MethodParametersReturn value
use(entity, ability)Entity, ability IDAbilityService.UseResult

It can only cast an ability the entity already holds, and it only takes effect on the server. The result record: committed() means it completed immediately, casting() means the cast has started, failure() is the failure enum, failedResource() is the ID of the insufficient resource, and amounts() are the resources actually paid.

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

MxtCultivation

MethodParametersReturn valueDescription
add(entity, resource, amount)LivingEntity, resource ID, finite non-negative numberbooleanAdds to the cultivation progress of that resource. On the client, with an unknown resource, a negative number or a non-finite number it returns false.
tryBreakthrough(entity, resource)LivingEntity, resource IDCultivationService.BreakthroughResultAttempts a breakthrough along the realm chain of that resource.

The accessors of the breakthrough record are advanced(), failure(), failedResource() and costs(). It fires the normal cultivationBreak flow, breakthrough actions, particles, tribulations and associated abilities.

MxtCurses

MethodParametersReturn valueDescription
apply(entity, curse, stacks, source)Entity, curse ID, positive integer stack count, non-empty source stringCurseService.ApplyResultGoes through the complete conditions and merging logic.
remove(entity, curse)Entity, curse IDbooleanRemoves it with the EXPLICIT reason; fires the removal event.

ApplyResult exposes applied(), cancelled(), failure() and instance(). For source it is recommended to write a stable source such as example:quest_reward, so that data and events can be traced.

MxtAura

MethodParametersReturn valueDescription
get(level, pos)Level, BlockPosAuraResultReads the fully resolved multi-resource aura at that position. Read-only, and the client can query its locally available state.
addBox(level, zone, minX, minY, minZ, maxX, maxY, maxZ, priority)Server Level, a loaded aura zone ID, two block coordinates, integer prioritystringAdds a persistent cuboid area and returns the generated area ID.
remove(level, area)Server Level, the area ID returned by addBoxbooleanRemoves the matching persistent area.

addBox only accepts a ServerLevel, and zone must be a loaded aura_zone data pack ID; otherwise it throws an exception. The commonly used read-only methods of AuraResult are aura(), concentration(), maximum(), regenPerTick(), cultivationSpeed(), source(), sourceKind() and suppressCultivate().

MxtSouls

MethodParametersReturn valueDescription
reclaim(entity)EntitybooleanUses the authoritative soul reclaim flow. It only applies to transferable souls, and it fires the reclaim pre/post events of soul.

MxtEvents

All events are registered in the server event group. Subscribe like this:

MxtEvents.abilityUse(event => {
if (event.isPre() && event.getAbility() === 'example:forbidden') {
event.cancel()
}
})

event.cancel() stops the current KubeJS listener chain immediately. It only cancels the MiXianTu transaction when the underlying event is a cancellable NeoForge event; calling it in a non-cancellable phase only stops the script listeners and does not undo game behaviour that has already happened.

Dedicated Event Wrappers

EventPhasesAvailable methodsWhat can be changed
abilityUsePre, PostgetEntity(), getAbility(), isPre(), getPaidCosts()Pre can be cancelled. getPaidCosts() returns an empty map in Pre.
curseApplyPre, PostgetCurse(), isPre(), getStacks(), setStacks(n), getSource(), setSource(text)Only Pre can cancel and modify the stack count/source; the stack count must be greater than 0. Calling a setter on Post throws an exception.
resourceConsumePre, PostisPre(), getAmounts(), setAmount(resource, amount)Only Pre can cancel and modify a single resource amount; the amount must be finite and greater than 0.
auraZoneenter, leave, tick, overridegetKind(), getSource(), getConcentration(), isCultivationSuppressed(), getOverrideZone()Only override can be cancelled. getOverrideZone() returns an empty string when it is not an override.

The keys of a resource map are already converted to string IDs. For example:

MxtEvents.resourceConsume(event => {
if (!event.isPre()) return
const amounts = event.getAmounts()
if (amounts['mxt:spirit_power'] > 0) {
event.setAmount('mxt:spirit_power', 5)
}
})

Generic Lifecycle Events

The remaining events use the generic wrapper, with these methods:

MethodReturn value / effect
getType()The KubeJS event name, for example cultivationBreak.
getPhase()The actual Java phase class name, for example Pre, StrikePre, StartPost.
isCancellable()Whether the current phase can be cancelled.
getEvent()The native MiXianTu event instance, whose Java accessors are listed in the table below.
cancel()The standard KubeJS cancel method; it only cancels the underlying transaction when isCancellable() is true.

In the table below, native stands for const native = event.getEvent(). Return values such as Identifier, Holder and Attachment are Java objects; use String(value) when you need a text ID.

KubeJS eventPhase class namesMain native accessors / semantics
abilityTriggeredPre, PostgetEntity(), getAbility(), signalType(), context(); Pre can cancel the triggered ability. The native event's ability() returns Holder<Ability>; use HolderHelper.id(...) or the KubeJS wrapper's getAbility() when you need the ID.
curseRemovePre, Postcurse() (Holder<Curse>), state(), reason(), gameTime(), holder(); Pre can cancel the removal. reason is EXPLICIT, EXPIRED, CLEANSED, REPLACED, CONTENT_ACTION or ADMIN.
cultivationBreakPre, Posttarget() (Holder<RealmStage>), threshold(), context(), spirit(), resources(); Pre additionally has originalCosts(), costs() and setCost(resource, amount) and can cancel; Post has paidCosts().
techniqueLearnPre, Posttechnique() (Holder<CultivationTechnique>), spirit(); Pre can cancel.
alchemyCraftPre, Postrecipe() (RecipeHolder<AlchemyRecipe>); Pre.inputs() is the list of input IDs and can cancel; Post.spoiled() and Post.outputs() are the result state.
artifactRefinePre, Poststack(), owner(); Pre can cancel.
forgingStart, Started, StrikePre, StrikePost, CompletePre, CompletePost, CancelEvery phase can read player() (ServerPlayer) and pos() (BlockPos, the position of the table). Per phase: Start.blueprint(); Started/StrikePost/Cancel.session(); StrikePre.method() (Holder<ForgingMethod>), resources(), context(), costs(), setCosts(costs); CompletePre.blueprint(), session(); CompletePost.blueprint(), session(), result(). Start, StrikePre, CompletePre and Cancel can be cancelled.
formationActivate, Deactivate, Ticklevel(), controller(), instance() (the formation ID comes from instance().formation()); Activate and Tick can be cancelled.
lifespanEndPre, Postentity(), spirit(); Pre can cancel the end, and after cancelling the lifespan is set to unlimited.
realmInstanceEnterPre, EnterPost, Exitlevel(), definition() (Holder<RealmInstance>), member(); only EnterPre can be cancelled.
sectJoinPre, JoinPost, LeavePre, LeavePost, PromotePre, PromotePostsect(), data(); every *Pre can be cancelled.
soulTransferPre, TransferPost, ReclaimPre, ReclaimPostentity(), soul(); every *Pre can be cancelled.
spiritContractPre, Postcontract(), contractType(), requester(), action(); contractType() is an Optional<Holder<ContractType>>, action() is BIND, BREAK, RECALL or RELEASE; Pre can be cancelled.
tribulationStartPre, StartPost, PhasePre, PhasePost, Completetribulation() (Holder<Tribulation>), phase(), data(); StartPre and PhasePre can be cancelled.

Two Extra Conventions for forging

The session is read-only. session() returns a ForgingSessionView, which can read value(), steps(), optimalSteps(), history() (an immutable list) and canComplete(), but cannot modify the session — the native ForgingSession is a mutable object and is no longer handed to listeners, so a call such as event.getEvent().session().strike(...) does not exist. The table itself is not handed to listeners either, only its position pos(); to read a slot, use player.level().getBlockEntity(pos).

A listener must not throw, and a throw does not break the operation. The four decision events (Start, StrikePre, CompletePre, Cancel) are dispatched in the middle of the transaction, so when a listener throws, the server turns it into a rejection on the spot: the log records LISTENER_ERROR (distinct from CANCELLED when a script calls cancel() deliberately), the operation does not happen, materials are not consumed, and the session stays as it was. The three notification events (Started, StrikePost, CompletePost) are dispatched after the operation has already taken effect, so a throw is only logged and ignored.

For example, adjusting the breakthrough cost:

MxtEvents.cultivationBreak(event => {
if (event.getPhase() !== 'Pre') return
const native = event.getEvent()
native.setCost('mxt:spirit_power', 20)
})

Return Values and Errors

Java records returned by the service APIs always use Java accessors, for example result.committed(), rather than assuming that JavaScript fields exist. A failure usually does not throw: check the return values such as failure(), committed(), advanced() and applied(). An exception is only thrown when an API parameter is invalid, an identifier is invalid, JSON cannot be decoded by the matching codec, or a mutable setter is called on the wrong event phase.

Custom Trigger Signals

MxtKubeJsApi.publishTrigger(entity, signal, values) publishes a custom trigger signal from a server script:

ParameterTypeDescription
entityEntityThe subject of the signal, which is also the dispatch target for subscribers; a client entity is rejected.
signalIdentifierA namespaced signal ID, for example example:pill_taken.
valuesMap<String,Object>Key/value pairs written into the TriggerContext extension fields; may be null.

Trigger subscriptions are not saved to the world. A script that has to wait for an event across restarts should save a stable ID/phase state itself and call its registration logic again after the entity joins the world or the data pack is reloaded.

See KubeJS Examples for complete combinations.