PmmoJS follows KubeJS script lifecycles. Each API belongs to the folder that matches when the code runs.
The rule
For Forge 1.20.1 with KubeJS:
| Script folder | Purpose |
|---|---|
startup_scripts/ | Registration and startup-only Forge hooks |
server_scripts/ | PMMO 运行逻辑和可选的自定义 ProbeJS 文档 |
client_scripts/ | Read-only skill display helpers and client-side UI |
Practical guide
startup_scripts/
Use for anything that defines data before the game world loads:
// PredicatesPmmoJS.registerPredicate(event => {event.registerActionPredicate(PmmoHelper.id('minecraft:stick'), ReqType.WEAPON,(player, stack) => player.experienceLevel >= 5)})// Direct data registrationPmmoHelper.registerXpAwardData(ObjectType.ITEM, 'minecraft:bread', EventType.CONSUME, {cooking: 2}, true)// Raw Forge eventsForgeEvents.onEvent('net.minecraftforge.event.entity.player.PlayerEvent$PlayerLoggedInEvent', event => {console.info(`[PmmoJS] ${event.getEntity().getScoreboardName()} logged in`)})
server_scripts/
Use for gameplay reactions, config editing, and optional custom documentation generation:
// Runtime triggersPmmoJS.trigger(EventType.BLOCK_BREAK, event => {if (event.hasPlayer()) {event.addXpAward('mining', 5)}})// Internal hooksPmmoJS.internal(PMMOInternalType.POTION_BREW, event => {if (!event.getContextBoolean('alreadyTracked')) {event.addXpAward('alchemy', 10)}})// 自定义 ProbeJS 文档生成ProbeJSEvents.generateDoc(event => {event.addSnippet('pmmojs.trigger.type', PmmoHelper.getTriggerTypeIds(), 'PmmoJS trigger ids')})
PmmoJS 内置的 ProbeJS 类型和代码片段会自动注册。ProbeJSEvents.generateDoc(...) 只用于整合包自己的额外文档或片段。
client_scripts/
Limited to read-only operations. SkillHelper and ClientSkillHelper are available for skill display lookups. PmmoHelper is not exposed on the client.
Common mistakes
- Putting
ForgeEvents.onEvent(...)inserver_scripts/— on KubeJS 1.20.1, this is a startup API. It won't work in server scripts. - Putting
ProbeJSEvents.generateDoc(...)instartup_scripts/— 这是 server script API,用于自定义 ProbeJS 文档。它不能在 startup scripts 中运行。 - Putting
PmmoJS.registerPerk(...)inserver_scripts/— this needs to run at registration time, not during gameplay. Move it to startup.
Reload behavior
- Startup scripts only run once during mod initialization. They are not hot-reloadable.
- Server scripts run on every server reload. This is where you iterate on gameplay logic.
- Config events in server scripts are applied through the reload path, so they stay compatible with PMMO's own config reloads.
Decision flowchart
Ask yourself what the code does:
- Defines data or structures at load time? →
startup_scripts/ - Reacts to gameplay or edits config? →
server_scripts/ - Only reads skill data for UI display? →
client_scripts/ - 添加自定义 ProbeJS 文档? →
server_scripts/