Skip to content

JavaScript Scripting

EmakiForge registers its own scripting module through the CoreLib scripting system. The module ID is forge. Inside a script you obtain the module facade with emaki.module("forge") to register forge success-rate rules and forge result hooks.

This page covers only the EmakiForge-specific script methods, registration fields, context and examples. For the generic scripting mechanism (runjs action, emaki.player, emaki.logger, security configuration, threading model, etc.) see CoreLib JavaScript Scripting.

Always guard with available() before calling any business method. EmakiForge is a CoreLib softdepend; the module is unavailable when the plugin is not installed or not ready.

Obtaining the module

js
function main(ctx) {
  const forge = emaki.module("forge");
  if (!forge.available()) {
    return { skipped: true, message: "EmakiForge unavailable" };
  }
  // ...
  return true;
}

Probe methods

MethodReturnsDescription
available()booleanWhether the module is available.
ready()booleanWhether the module finished initialization.
apiVersion()stringEmakiForge API version.
pluginName()stringPlugin name.

Forge success-rate rules

Forge rules run during forge resolution. They can read the context and modify the success rate or cancel the forge.

MethodReturnsDescription
registerForgeRule(definition)booleanRegister a forge rule.
registerForgeRule(id, definition)booleanOverload: merge id into the definition, then register.
unregisterForgeRule(id)voidUnregister a rule by id.
registeredForgeRules()listReturn the list of registered rule ids.

Rule definition fields

FieldTypeRequiredDefaultDescription
idstringyesnoneUnique rule id (normalized); registration fails when blank.
functionstringnomodifyForgeRule callback function name; execute works as an equivalent key.
priorityintno0Priority; lower runs first, ties broken by id.
recipeIdsstring / listnoempty (all recipes)Recipe ids the rule applies to; recipes also works.
timeoutMillislongnoengine defaultPer-call script timeout, clamped by the global limit.

Rule callback ctx fields

FieldTypeDescription
ruleIdstringCurrent rule id.
recipeIdstringRecipe id.
recipeNamestringRecipe display name.
playerUuidstringPlayer UUID.
playerNamestringPlayer name.
originalSuccessRatedoubleOriginal success rate.
successRatedoubleCurrent accumulated success rate.
cancelledbooleanWhether already cancelled.
messagestringCurrent message.
targetItemmapSummary of the main input item: type / amount / displayName, optional lore / customModelData.
requiredMaterialslistRequired material inputs, each an item summary with a slot.
optionalMaterialslistOptional material inputs, same fields as above.
traceslistTraces from previous rules, each with id / before / after / message.

Rule callback return fields

Return fieldTypeDescription
successRate or chancenumberSet the success rate directly (takes priority, overrides bonus / multiplier).
successBonusnumberAdd to the current success rate (when no successRate).
successMultipliernumberMultiply the current success rate (applied after bonus).
cancelbooleanWhether to cancel the forge.
messagestringMessage written to the trace.

The final success rate is clamped to 0~100. Rules run serially in ascending priority order and stop on cancellation. A non-object return or an execution failure keeps the original rate and records a trace.

Forge result hooks

Result hooks fire after a forge completes, for side effects such as rewards, broadcasts and logging.

MethodReturnsDescription
onResult(definition)booleanRegister a forge result hook.
onResult(id, definition)booleanOverload: merge id into the definition, then register.
unregisterResultHook(id)voidUnregister a result hook by id.
registeredResultHooks()listReturn the list of registered result hook ids.

Hook definition fields

FieldTypeRequiredDefaultDescription
idstringyesnoneUnique hook id; registration fails when blank.
functionstringnoonForgeResultCallback function name; execute also works.
recipeIdsstring / listnoempty (all recipes)Recipe ids the hook applies to; recipes also works.
timeoutMillislongnoengine defaultPer-call script timeout.

Hook callback event fields

FieldTypeDescription
hookIdstringHook id.
playerUuidstringPlayer UUID.
playerNamestringPlayer name.
recipeIdstringRecipe id.
recipeNamestringRecipe display name.
successbooleanWhether the forge succeeded.
errorKeystringFailure error key.
qualitystringForge quality.
multiplierdoubleMultiplier.
resultItemmapRead-only result item summary { type, amount, displayName, lore?, customModelData? }; non-empty only when the forge succeeded, {} on failure.
actionFailureReasonstringAction failure reason.
replacementsmapText replacement map.

Result hooks are for side effects. The hook callback may return { actions: [...] }, where actions is an array of action-line strings that the plugin runs in order through the CoreLib ActionExecutor. The action-line syntax matches the actions used in recipes, e.g. "sendmessage text=\"<green>...\"", "playsound sound=minecraft:... volume=1 pitch=1". A failure only logs a warning to the console and does not affect the completed forge result.

Placeholders available in action lines:

PlaceholderDescription
%success%Whether the forge succeeded.
%forge_recipe_id%Forge recipe id.
%forge_quality%Forge quality.
%forge_multiplier%Multiplier.

Example returning actions:

js
function onForgeResult(event) {
  if (event.success) {
    return {
      actions: [
        "sendmessage text=\"<green>Forge succeeded, quality %forge_quality%\"",
        "playsound sound=minecraft:block.anvil.use volume=1 pitch=1"
      ]
    };
  }
  return {};
}

Full example

Extension scripts that register rules and result hooks use the register() entry point. EmakiForge ships the example script scripts/examples/forge_success.js:

js
function register() {
  const forge = emaki.module("forge");

  forge.registerForgeRule({
    id: "example_moon_bonus",
    priority: 10,
    function: "modifyForge"
  });

  forge.onResult({
    id: "example_result_notice",
    function: "onForgeResult"
  });
}

function modifyForge(ctx) {
  return {
    successBonus: 3,
    message: "Example: +3% forge success rate"
  };
}

function onForgeResult(event) {
  emaki.logger.info("Forge result hook: recipe=" + event.recipeId + ", success=" + event.success + ", quality=" + event.quality);
}

Enabling extension scripts

Registration scripts are loaded through the register() entry point. Put the script into CoreLib's global extension directory and reload:

text
plugins/EmakiCoreLib/scripts/extensions/global/forge_success.js
text
/corelib script reload

The example file is released to plugins/EmakiCoreLib/scripts/examples/ by default and is not auto-enabled. Copy it into extensions/global/ and reload to enable it.

Script debugging

When you enable the debug submodule named script, EmakiForge writes the per-rule execution trace to the server console every time its JS rules run, which helps server administrators debug script rules.

Enable command:

text
/ef debug module script

Trace fields: rule id, before (value before execution), after (value after execution) and message. This output goes to the server console for server administrators to debug; it is not shown to players.

Notes

  • Every registration method requires the CoreLib scripting system to be enabled (script.enabled: true); otherwise registration returns false or is silently skipped.
  • When CoreLib is missing the module degrades gracefully: rules and hooks have no effect but raise no error.
  • Rules run in ascending priority order (lower first), which is the opposite of EmakiAttribute damage hooks (descending). Keep this in mind when mixing them.