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
function main(ctx) {
const forge = emaki.module("forge");
if (!forge.available()) {
return { skipped: true, message: "EmakiForge unavailable" };
}
// ...
return true;
}Probe methods
| Method | Returns | Description |
|---|---|---|
available() | boolean | Whether the module is available. |
ready() | boolean | Whether the module finished initialization. |
apiVersion() | string | EmakiForge API version. |
pluginName() | string | Plugin 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.
| Method | Returns | Description |
|---|---|---|
registerForgeRule(definition) | boolean | Register a forge rule. |
registerForgeRule(id, definition) | boolean | Overload: merge id into the definition, then register. |
unregisterForgeRule(id) | void | Unregister a rule by id. |
registeredForgeRules() | list | Return the list of registered rule ids. |
Rule definition fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | yes | none | Unique rule id (normalized); registration fails when blank. |
function | string | no | modifyForge | Rule callback function name; execute works as an equivalent key. |
priority | int | no | 0 | Priority; lower runs first, ties broken by id. |
recipeIds | string / list | no | empty (all recipes) | Recipe ids the rule applies to; recipes also works. |
timeoutMillis | long | no | engine default | Per-call script timeout, clamped by the global limit. |
Rule callback ctx fields
| Field | Type | Description |
|---|---|---|
ruleId | string | Current rule id. |
recipeId | string | Recipe id. |
recipeName | string | Recipe display name. |
playerUuid | string | Player UUID. |
playerName | string | Player name. |
originalSuccessRate | double | Original success rate. |
successRate | double | Current accumulated success rate. |
cancelled | boolean | Whether already cancelled. |
message | string | Current message. |
targetItem | map | Summary of the main input item: type / amount / displayName, optional lore / customModelData. |
requiredMaterials | list | Required material inputs, each an item summary with a slot. |
optionalMaterials | list | Optional material inputs, same fields as above. |
traces | list | Traces from previous rules, each with id / before / after / message. |
Rule callback return fields
| Return field | Type | Description |
|---|---|---|
successRate or chance | number | Set the success rate directly (takes priority, overrides bonus / multiplier). |
successBonus | number | Add to the current success rate (when no successRate). |
successMultiplier | number | Multiply the current success rate (applied after bonus). |
cancel | boolean | Whether to cancel the forge. |
message | string | Message 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.
| Method | Returns | Description |
|---|---|---|
onResult(definition) | boolean | Register a forge result hook. |
onResult(id, definition) | boolean | Overload: merge id into the definition, then register. |
unregisterResultHook(id) | void | Unregister a result hook by id. |
registeredResultHooks() | list | Return the list of registered result hook ids. |
Hook definition fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | yes | none | Unique hook id; registration fails when blank. |
function | string | no | onForgeResult | Callback function name; execute also works. |
recipeIds | string / list | no | empty (all recipes) | Recipe ids the hook applies to; recipes also works. |
timeoutMillis | long | no | engine default | Per-call script timeout. |
Hook callback event fields
| Field | Type | Description |
|---|---|---|
hookId | string | Hook id. |
playerUuid | string | Player UUID. |
playerName | string | Player name. |
recipeId | string | Recipe id. |
recipeName | string | Recipe display name. |
success | boolean | Whether the forge succeeded. |
errorKey | string | Failure error key. |
quality | string | Forge quality. |
multiplier | double | Multiplier. |
resultItem | map | Read-only result item summary { type, amount, displayName, lore?, customModelData? }; non-empty only when the forge succeeded, {} on failure. |
actionFailureReason | string | Action failure reason. |
replacements | map | Text 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:
| Placeholder | Description |
|---|---|
%success% | Whether the forge succeeded. |
%forge_recipe_id% | Forge recipe id. |
%forge_quality% | Forge quality. |
%forge_multiplier% | Multiplier. |
Example returning actions:
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:
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:
plugins/EmakiCoreLib/scripts/extensions/global/forge_success.js/corelib script reloadThe example file is released to
plugins/EmakiCoreLib/scripts/examples/by default and is not auto-enabled. Copy it intoextensions/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:
/ef debug module scriptTrace 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 returnsfalseor 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.