---
title: Startup Phase Rules
hide_meta: true
---

# Startup Phase Rules

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:

```js
// Predicates
PmmoJS.registerPredicate(event => {
  event.registerActionPredicate(PmmoHelper.id('minecraft:stick'), ReqType.WEAPON,
    (player, stack) => player.experienceLevel >= 5
  )
})

// Direct data registration
PmmoHelper.registerXpAwardData(ObjectType.ITEM, 'minecraft:bread', EventType.CONSUME, {
  cooking: 2
}, true)

// Raw Forge events
ForgeEvents.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:

```js
// Runtime triggers
PmmoJS.trigger(EventType.BLOCK_BREAK, event => {
  if (event.hasPlayer()) {
    event.addXpAward('mining', 5)
  }
})

// Internal hooks
PmmoJS.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(...)` in `server_scripts/`** — on KubeJS 1.20.1, this is a startup API. It won't work in server scripts.
- **Putting `ProbeJSEvents.generateDoc(...)` in `startup_scripts/`** — 这是 server script API，用于自定义 ProbeJS 文档。它不能在 startup scripts 中运行。
- **Putting `PmmoJS.registerPerk(...)` in `server_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/`
