---
title: 运行时事件
hide_meta: true
---

# 运行时事件

运行时事件在游戏过程中触发。放在 `server_scripts/` 中。

## `PmmoJS.trigger`

这是 PmmoJS 中覆盖面最广的钩子。每当 PMMO 内部的 `EventTriggerRegistry` 激活时触发，覆盖了 PMMO 的大部分游戏事件：破坏方块、合成物品、造成伤害、跳跃、游泳、驯服等等。

可以把它理解为"从 KubeJS 监听 PMMO 的内置事件系统"。

```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)
    }
})
```

### PMMO 1.7.40 覆盖的触发器类型

- **交互：** `BLOCK_BREAK`、`BLOCK_PLACE`、`HIT_BLOCK`、`ACTIVATE_BLOCK`、`ACTIVATE_ITEM`、`CRAFT`、`BREW`、`CONSUME`
- **战斗：** `DEAL_DAMAGE`、`RECEIVE_DAMAGE`、`DEATH`、`SHIELD_BLOCK`
- **实体：** `BREED`、`TAMING`、`ENTITY`、`GIVEN_AS_TRADE`、`RECEIVED_AS_TRADE`
- **工具：** `ANVIL_REPAIR`、`ENCHANT`、`FISH`、`GROW`、`BREAK_SPEED`
- **移动：** `JUMP`、`SPRINT_JUMP`、`CROUCH_JUMP`、`RIDING`、`SPRINTING`、`CROUCH`、`SUBMERGED`、`SWIMMING`、`DIVING`、`SURFACING`、`SWIM_SPRINTING`
- **状态：** `BREATH_CHANGE`、`HEALTH_CHANGE`、`HEALTH_INCREASE`、`HEALTH_DECREASE`、`EFFECT`

部分 PMMO 处理器（跨维度、登录、骑乘、活塞、爆炸、玩家死亡、睡觉、药水酿造）不经过触发器注册表，请使用 `PmmoJS.internal`。

### 触发器事件的关键方法

- `getType()` 和 `getTypeId()` —— 触发的是哪种触发器类型
- `getForgeEvent()` 和 `getForgeEventClassName()` —— 底层的 Forge 事件（如果有的话）
- `hasPlayer()`、`getPlayer()`、`getServerPlayer()` —— 涉及的玩家
- `getContextBoolean(key)`、`getContextString(key)`、`getContextInt(key)`、`getContextLong(key)`、`getContextDouble(key)` —— 读取上下文值
- `putContextBoolean(key, value)`、`putContextString(key, value)` 等 —— 写入上下文值
- `hasContextKey(key)`、`removeContextKey(key)`、`getContextKeys()` —— 管理上下文键
- `addXpAward(skill, amount)` —— 添加 XP 奖励
- `setXpAwards(map)`、`getXpAwards()`、`clearXpAwards()` —— 管理所有 XP 奖励
- `setCancelled(true)` —— 告诉 PMMO 跳过处理此触发器

## `PmmoJS.xp`

当 PMMO 改变玩家的 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`

当玩家附魔物品时触发。

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

## `PmmoJS.furnace`

由 PMMO 的熔炉烧炼事件触发。

```js
PmmoJS.furnace(event => {
    const input = event.getInput()
    if (input.id === 'minecraft:iron_ore') {
        // 自定义逻辑
    }
})
```

## `PmmoJS.salvage`

当玩家回收物品时触发。

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

## 伤害惩罚钩子

使用这些钩子来缩放 PMMO 的伤害惩罚，而不是仅仅取消它。

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

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

第一个适用于物品耐久损耗；第二个适用于收到的实体伤害。

## 服务端脚本中的 `PmmoHelper`

`PmmoHelper` 让你直接访问 PMMO 的 API，避免 KubeJS 重载歧义。这对于自定义命令、Forge 事件监听器以及 PmmoJS 事件封装不太适合的场景很有用。

```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))
})
```

关键方法组：

- **技能状态：** `getSkillLevel`、`setSkillLevel`、`addSkillXp`、`getAllSkillLevels`
- **数据查询：** `getItemXpAwards`、`getBlockRequirements`、`getConsolidatedModifiers`
- **直接注册：** `registerRequirementData`、`registerXpAwardData`、`registerBonusData`、工具提示注册、谓词
- **发现辅助：** `getTriggerTypeIds`、`getInternalTypeIds`
- **PMMO 系统：** `awardXpToPlayer`、`awardXpToPartyInRange`、`getPartyMembers`、`applyVeinMining`、`triggerSalvage`

`SkillHelper` 仍然可用于旧脚本，但 `PmmoHelper` 是推荐的前进方向。
