Developers
Script plugins
For servers and advanced setups: plugins that run inside BedrockAdvancements, with test functions and your own trigger types.
Adding a plugin
- Put your plugin's folder in
BedrockAdvancements_BP/scripts/plugins/. - In
scripts/plugins/index.js, import it and add it toPLUGINS:
import gems from "./gems/index.js";
export const PLUGINS = [
gems,
];
A plugin's index.js exports { id, register }:
import { BA } from "../../api/index.js";
function register() {
BA.plugin("gems", () => {
BA.tab({ id: "main", title: "Gem Collector", icon: "textures/items/emerald", background: "textures/blocks/emerald_block" });
BA.advancement({
id: "root",
tab: "main",
title: "Gem Collector",
description: "Pick up an emerald",
icon: "textures/items/emerald",
criteria: { emerald: { trigger: "inventory_changed", item: "emerald" } },
});
});
}
export default { id: "gems", register };
If a plugin throws while registering, the error is logged and the other plugins still load. scripts/plugins/example/ is a complete example.
What scripts add
- Test functions on many triggers, like
test(dead, player, source)onplayer_killed_entity, oritemTest(stack)oninventory_changed. - Reward functions:
rewards: { run: (player) => { … } }. - The
ticktrigger:{ trigger: "tick", test: (player) => player.isSwimming, interval: 20 }. - The
enabledfunction on a tab: hide it (and pause its progress) whenever it returns false. - Custom trigger types, below.
BA.advancements(defaults, list) defines several at once, each inheriting defaults (handy for { tab: "main" }).
Custom trigger types
BA.registerTrigger("gems:jumps", {
// Called once, the first time any loaded advancement uses this trigger.
start() {
BA.events.everyPlayer("gems:jumps", 2, (player) => {
if (!player.isJumping) return;
for (const ref of BA.triggers.pending(player, BA.triggers.refs("gems:jumps"))) {
BA.triggers.hit(player, ref); // counts towards `count` if the criterion has one
}
});
},
});
BA.triggers.refs(type): every criterion using the trigger;ref.defis its definition.BA.triggers.pending(player, refs): those the player still needs (skips completed ones and disabled tabs).BA.events.onAfter(name, fn)/onBefore(name, fn): shared world event subscriptions.BA.events.everyPlayer(name, ticks, fn): runsfn(player)for each online player everyticks, spread across ticks.BA.data(player).getState(key)/setState(key, value)/addState(key, n): saved per-player state for your trigger.
Triggers start lazily and check pending() first, so unused triggers cost nothing.