---
title: Runtime Events
hide_meta: true
---

# Runtime Events

Runtime events fire during gameplay. Keep these in `server_scripts/`.

## `PmmoJS.trigger`

This is the broadest hook in PmmoJS. It fires whenever PMMO's internal `EventTriggerRegistry` activates, which covers most of PMMO's gameplay events: breaking blocks, crafting items, dealing damage, jumping, swimming, taming, and more.

Think of it as "listen to PMMO's built-in event system from KubeJS."

```js
PmmoJS.trigger(EventType.BLOCK_BREAK, event => {
    const player = event.getPlayer()

    if (player && player.stages.has('peaceful_mining')) {
        event.addXpAward('mining', 25)
    }

    if (player && player.isCreative()) {
        event.setCancelled(true)
    }
})
```

### Trigger types covered on PMMO 1.7.40

- **Interaction:** `BLOCK_BREAK`, `BLOCK_PLACE`, `HIT_BLOCK`, `ACTIVATE_BLOCK`, `ACTIVATE_ITEM`, `CRAFT`, `BREW`, `CONSUME`
- **Combat:** `DEAL_DAMAGE`, `RECEIVE_DAMAGE`, `DEATH`, `SHIELD_BLOCK`
- **Entity:** `BREED`, `TAMING`, `ENTITY`, `GIVEN_AS_TRADE`, `RECEIVED_AS_TRADE`
- **Utility:** `ANVIL_REPAIR`, `ENCHANT`, `FISH`, `GROW`, `BREAK_SPEED`
- **Movement:** `JUMP`, `SPRINT_JUMP`, `CROUCH_JUMP`, `RIDING`, `SPRINTING`, `CROUCH`, `SUBMERGED`, `SWIMMING`, `DIVING`, `SURFACING`, `SWIM_SPRINTING`
- **Status:** `BREATH_CHANGE`, `HEALTH_CHANGE`, `HEALTH_INCREASE`, `HEALTH_DECREASE`, `EFFECT`

Some PMMO handlers (dimension travel, login, mount, piston, explosion, player death, sleep, potion brewing) do not go through the trigger registry. Use `PmmoJS.internal` for those.

### Key methods on the trigger event

- `getType()` and `getTypeId()` — which trigger type fired
- `getForgeEvent()` and `getForgeEventClassName()` — the underlying Forge event, if any
- `hasPlayer()`, `getPlayer()`, `getServerPlayer()` — the player involved
- `getContextBoolean(key)`, `getContextString(key)`, `getContextInt(key)`, `getContextLong(key)`, `getContextDouble(key)` — read context values
- `putContextBoolean(key, value)`, `putContextString(key, value)`, etc. — write context values
- `hasContextKey(key)`, `removeContextKey(key)`, `getContextKeys()` — manage context keys
- `addXpAward(skill, amount)` — add an XP award
- `setXpAwards(map)`, `getXpAwards()`, `clearXpAwards()` — manage all XP awards
- `setCancelled(true)` — tell PMMO to skip processing this trigger

## `PmmoJS.xp`

Fires when PMMO changes a player's XP.

```js
PmmoJS.xp(event => {
    const player = event.getEntity()
    const skill = event.getSkill()

    if (event.isLevelUp() && event.endLevel() % 10 === 0) {
        player.give(Item.of('minecraft:diamond'))
    }

    if (skill === 'mining') {
        event.cancel()
    }
})
```

## `PmmoJS.enchant`

Fires when a player enchants an item.

```js
PmmoJS.enchant(event => {
    const ench = event.getEnchantmentInstance()
    SkillHelper.addXP(event.getEntity(), 'magic', 10 * ench.level)
})
```

## `PmmoJS.furnace`

Fires from PMMO's furnace burn event.

```js
PmmoJS.furnace(event => {
    const input = event.getInput()
    if (input.id === 'minecraft:iron_ore') {
        // custom logic here
    }
})
```

## `PmmoJS.salvage`

Fires when a player salvages an item.

```js
PmmoJS.salvage(event => {
    const builder = event.getBuilder()
    builder.setSalvageMax(2)
    event.setOutputStack(Item.of('minecraft:iron_nugget', 2))
})
```

## Damage penalty hooks

Use these to scale PMMO's damage penalty instead of only canceling it.

```js
PmmoJS.itemstackDamagePenalty(event => {
    event.setDamage(event.getDamage() * 0.75)
})

PmmoJS.entityDamagePenalty(event => {
    event.setDamage(event.getDamage() * 0.5)
})
```

The first applies to item durability loss; the second applies to entity damage received.

## `PmmoHelper` in server scripts

`PmmoHelper` gives you direct access to PMMO's API without KubeJS overload ambiguity. This is useful for custom commands, Forge event listeners, and places where the PmmoJS event wrappers are not the right fit.

```js
ServerEvents.loaded(event => {
    const player = event.server.getPlayerList().getPlayers()[0]
    if (!player) return

    console.log(PmmoHelper.getSkillLevel(player, 'mining'))
    console.log(PmmoHelper.getItemRequirements(player.mainHandItem, ReqType.WEAR))
    console.log(PmmoHelper.getCurrentVeinCharge(player))
})
```

Key method groups:

- **Skill state:** `getSkillLevel`, `setSkillLevel`, `addSkillXp`, `getAllSkillLevels`
- **Data lookups:** `getItemXpAwards`, `getBlockRequirements`, `getConsolidatedModifiers`
- **Direct registration:** `registerRequirementData`, `registerXpAwardData`, `registerBonusData`, tooltip registrations, predicates
- **Discovery helpers:** `getTriggerTypeIds`, `getInternalTypeIds`
- **PMMO systems:** `awardXpToPlayer`, `awardXpToPartyInRange`, `getPartyMembers`, `applyVeinMining`, `triggerSalvage`

已有脚本如果还在用 `SkillHelper`，可以继续保留；新写的 server script 用 `PmmoHelper`。
