JavaScript Scripting
EmakiSkills registers a scripting module through the CoreLib scripting system. The module ID is skills. emaki.module("skills") returns a different object depending on context:
- In ordinary trigger scripts (
runjsaction,examples/, etc.) it returns the query facadeScriptSkillsModuleApi, used for probing and querying registered skill script actions. - In Skills-specific extension scripts (the
extensions/skills/directory, loaded throughregister()) it returns the registration API, used to register custom skill script actions.
This page covers only EmakiSkills-specific content. For the generic scripting mechanism see CoreLib JavaScript Scripting.
Always guard with
available()before calling any business method. EmakiSkills is a CoreLib softdepend.
Query facade (trigger script context)
In ordinary trigger scripts, emaki.module("skills") returns the query facade.
| Method | Returns | Description |
|---|---|---|
available() | boolean | Whether the module is available. |
hasScriptAction(actionId) | boolean | Whether the registry contains the skill script action id. |
registeredScriptActions() | list | Return the list of all registered skill script action ids. |
The query facade only has the methods above; there is no
ready()/apiVersion()/pluginName(). Use.size()on the returned list in JS.
Trigger scripts can read the skill context via emaki.context:
| Access | Key | Description |
|---|---|---|
emaki.context.placeholder("skills_skill_id") | skills_skill_id | Skill id (placeholder form). |
emaki.context.attribute("skill_id") | skill_id | Skill id (attribute form). |
Trigger example
EmakiSkills ships the trigger-style example script scripts/examples/skills_upgrade_success.js:
function main(ctx) {
const skills = emaki.module("skills");
const skillId = emaki.context.placeholder("skills_skill_id") || emaki.context.attribute("skill_id");
if (emaki.player.exists()) {
emaki.player.sendMessage("[EmakiJS] Skill upgrade success script: " + skillId + " skills=" + skills.available());
}
return {
success: true,
output: {
skill_id: String(skillId || ""),
skills_available: skills.available(),
registered_script_actions: skills.registeredScriptActions().size()
}
};
}Registration API (extension script context)
In extension scripts under the extensions/skills/ directory, CoreLib invokes the script's register() function and binds the registration API as emaki.module("skills").
| Method | Returns | Description |
|---|---|---|
registerAction(definition) | boolean | Register a custom skill script action. |
unregisterAction(actionId) | void | Unregister a skill script action by id. |
Action definition fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | yes | none | Action id (normalized); registration fails when blank. |
category | string | no | javascript | Action category. |
description | string | no | same as id | Description. |
parameters | list | no | empty | Parameter definitions, see below. |
executionMode | string | no | SYNC | Execution mode, SYNC or ASYNC_IO (case-insensitive, invalid falls back to SYNC). |
timeoutMillis | number | no | engine default | Per-call script timeout. |
execute | string | no | execute | Execution function name. |
validate | string | no | empty (no validation) | Validation function name. |
Each parameters element:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | yes | none | Parameter name (normalized); skipped when blank. |
type | string | no | STRING | Parameter type enum (case-insensitive, invalid falls back to STRING). |
required | bool / string | no | false | Whether required. |
defaultValue | string | no | empty | Default value, used only for optional parameters. |
description | string | no | empty | Description. |
Execute and validate functions
execute(ctx, args): execution function;ctxis the skill script context API (below),argsis the parameter Map.validate(args): validation function; receives only the parameter Map.
Execution mode ASYNC_IO runs on an async thread; SYNC runs synchronously on the calling thread. The return value maps to a skill action result: {skipped:true} skips, success returns output / return / message, and {success:false} fails.
Skill script context API (ctx)
| Method | Returns | Description |
|---|---|---|
skillId() | string | Current skill id. |
triggerId() | string | Trigger id. |
variable(key) | string | Read a variable. |
setVariable(key, value) | void | Set a variable. |
variables() | map | All variables. |
caster() | entity | Caster entity wrapper. |
target() | entity | Target entity wrapper. |
hasTarget() | boolean | Whether there is a target. |
setTarget(entity) | void | Set the target. |
targetLocation() | map | Target location, keys world / x / y / z / yaw / pitch. |
runAction(actionId, arguments) | boolean | Run a CoreLib action. |
runActionLine(line) | boolean | Run a single action line. |
castMythic(mythicSkillId) | boolean | Cast a MythicMobs skill. |
castMythic(mythicSkillId, parameters) | boolean | Cast a MythicMobs skill with parameters. |
applyDamage(target, damageTypeId, baseDamage) | boolean | Apply damage through EmakiAttribute. |
applyDamage(target, damageTypeId, baseDamage, damageContext) | boolean | Apply damage with a damage context. |
ctx.state is the cross-call shared state accessor: get(key), set(key, value), has(key), remove(key).
Registration example
EmakiSkills ships the extension-style example script scripts/examples/js_lightning_strike.js:
function register() {
const skills = emaki.module("skills");
skills.registerAction({
id: "js_lightning_strike",
category: "javascript",
description: "Strike the current skill target and optionally deal damage through EmakiAttribute",
executionMode: "SYNC",
timeoutMillis: 1000,
parameters: [
{ name: "damage", type: "DOUBLE", required: false, defaultValue: "10", description: "Base damage to apply" },
{ name: "damage_type", type: "STRING", required: false, defaultValue: "lightning", description: "Emaki attribute damage type id" }
],
validate: "validateLightning",
execute: "executeLightning"
});
}
function validateLightning(args) {
const damage = Number(read(args, "damage", "10"));
if (!Number.isFinite(damage) || damage <= 0) {
return { success: false, message: "Damage must be a positive number" };
}
return true;
}
function executeLightning(ctx, args) {
const caster = ctx.caster();
const target = ctx.target();
if (!target.exists()) {
return { skipped: true, message: "No target selected" };
}
const damage = Number(read(args, "damage", "10"));
const damageType = String(read(args, "damage_type", "lightning"));
let applied = false;
const attribute = emaki.module("attribute");
if (attribute.available()) {
applied = attribute.applyDamage(caster, target, damageType, damage, {
source: "js_lightning_strike",
skill_id: ctx.skillId(),
trigger_id: ctx.triggerId()
});
}
if (!applied) {
target.damage(damage);
}
return { success: true, message: "JavaScript lightning skill executed" };
}
function read(object, key, fallback) {
if (object == null) {
return fallback;
}
if (typeof object.get === "function") {
const value = object.get(key);
return value == null ? fallback : value;
}
const value = object[key];
return value == null ? fallback : value;
}Enabling extension scripts
Skills extension scripts load from extensions/skills/ under the CoreLib script root:
plugins/EmakiCoreLib/scripts/extensions/skills/js_lightning_strike.js/corelib script reloadThe example file is released to
plugins/EmakiCoreLib/scripts/examples/by default and is not auto-enabled. Copy it intoextensions/skills/and reload to enable it.
Built-in skill script actions
EmakiSkills ships a set of built-in Java skill script actions that skill configs can call directly:
| Action id | Category | Key parameters |
|---|---|---|
message | feedback | text (required); target (default caster). |
sound | feedback | sound (required); volume=1; pitch=1; at=caster. |
particle | feedback | particle (required); at=target; count=1; speed=0. |
ray | target | range=16; width=1; save=target (key saved into state). |
damage | combat | amount (required); target=target; damage_type=generic; element=empty. |
aoe_damage | combat | amount (required); radius=5; center=target; shape=sphere; filter=hostile; max_targets=20; exclude_caster=true. |
projectile | combat | speed=1.5; gravity=0.05; lifetime=60; hit_radius=0.5; pierce=0; homing=false; particle=FLAME; damage=0; direction=look. |
ignite | combat | ticks (required); target=target. |
heal | combat | amount (required); target=caster. |
mythic | bridge | skill (required, Mythic skill id). |
Target resolution:
caster/self/playeris the caster;lookis roughly 3 blocks ahead of the line of sight; any other string is first looked up in state shared values, otherwise the target entity is used.
Notes
- Registration methods require the CoreLib scripting system to be enabled; otherwise registration returns
falseor is silently skipped. applyDamageis invoked through EmakiAttribute by reflection; it returns false when EmakiAttribute is missing, and the target must be a living entity.- When CoreLib is missing the module degrades gracefully.
- On reload, extension scripts first unregister previously registered actions, then re-run
register(), avoiding hot-reload leftovers.