# PmmoJS 概览

PmmoJS 是 [Project MMO](https://www.curseforge.com/minecraft/mc-mods/project-mmo) 在 Forge 1.20.1 上的 KubeJS 附属模组。

它将 PMMO 的 API 封装成干净的 KubeJS 事件和辅助类，让你能用 JavaScript 配置 PMMO 的每一个部分 —— 技能、需求、经验奖励、Perk、触发器等等 —— 不写任何 Java 代码。

如果你要从零设计整合包成长，先读 [PMMO 编写流程](./pmmo-workflow)。它会按顺序说明：定义技能、选择默认数据基线、注册对象数据、添加 NBT 规则、配置 Perk，最后用运行时 hook 处理例外。

## 三层控制能力

PmmoJS 的功能按三个层级组织，对应 KubeJS 的脚本类型：

### 启动层（`startup_scripts/`）

在游戏世界加载之前完成的注册：

- **自定义 Perk** —— 通过 `PmmoJS.registerPerk(...)` 定义新的 Perk 类型。每个 Perk 拥有完整的生命周期回调：条件检查、启动、持续运行、关闭、状态显示。
- **自定义谓词** —— 通过 `PmmoJS.registerPredicate(...)` 注册 PMMO 会评估的条件检查。
- **直接数据注册** —— 通过 `PmmoHelper` 直接将需求数据、经验奖励、加成和触发器监听器注册到 PMMO 的 API 中。

### 配置层（`server_scripts/`）

通过 KubeJS 事件编辑 PMMO 的配置文件：

| 事件 | 控制内容 |
|---|---|
| `PmmoJS.skillsConfig(...)` | 添加、替换或删除技能 |
| `PmmoJS.perksConfig(...)` | 编辑 PMMO 配置中的已有 Perk 条目 |
| `PmmoJS.serverConfig(...)` | 服务器级设置，如最大等级、矿脉挖掘、死亡惩罚 |
| `PmmoJS.autoValueConfig(...)` | 方块和物品的自动生成值 |
| `PmmoJS.antiCheeseConfig(...)` | AFK 检测和收益递减 |
| `PmmoJS.globalsConfig(...)` | 全局 NBT 路径和常量 |
| `PmmoJS.settings(...)` | 物品、方块、实体、生物群系和维度的需求与经验数据 |

### 运行时层（`server_scripts/`）

在实际游戏过程中触发的钩子：

| 事件 | 触发时机 |
|---|---|
| `PmmoJS.trigger(EventType, ...)` | PMMO 触发器事件（挖掘、合成、伤害、跳跃等） |
| `PmmoJS.internal(PMMOInternalType, ...)` | PMMO 处理器级钩子（登录、跨维度、爆炸、酿造） |
| `PmmoJS.xp(...)` | 玩家获得 PMMO 经验时 |
| `PmmoJS.enchant(...)` | 玩家附魔物品时 |
| `PmmoJS.furnace(...)` | 熔炉烧炼时 |
| `PmmoJS.salvage(...)` | 玩家回收物品时 |
| `PmmoJS.itemstackDamagePenalty(...)` | 调整物品耐久损耗 |
| `PmmoJS.entityDamagePenalty(...)` | 调整实体伤害 |

## 脚本绑定

PmmoJS 会为你的 KubeJS 脚本注册以下绑定，可用的绑定取决于你在哪个脚本类型中：

**启动脚本：** `PmmoHelper`、`TagBuilder`、`NbtPathBuilder`

**服务端脚本：** `PmmoHelper`、`SkillHelper`、`SKillHelper`、`CustomReqMap`、`TagBuilder`、`NbtPathBuilder`、`SalvageBuilder`

**客户端脚本：** `SkillHelper`、`SKillHelper`（仅限只读访问技能数据）

### PmmoHelper

`PmmoHelper` 是主要的工具类。它将 PMMO 的内部 API 封装为清晰的静态方法：

- **技能状态：** `getSkillLevel`、`setSkillLevel`、`addSkillXp`、`getAllSkillLevels`
- **数据查询：** `getItemXpAwards`、`getBlockRequirements`、`getConsolidatedModifiers`
- **直接注册：** `registerRequirementData`、`registerXpAwardData`、`registerBonusData`、`registerTriggerListener`
- **队伍系统：** `getPartyMembers`、`getPartyMembersInRange`、`inviteToParty`
- **矿脉挖掘：** `applyVeinMining`、`regenerateVeinCharge`、`getCurrentVeinCharge`
- **类型发现：** `getTriggerTypeIds`、`getInternalTypeIds`、`getEventTypeIds`、`getReqTypeIds`、`getObjectTypeIds`

### 类型枚举

PmmoJS 同时暴露 PMMO 的类型枚举，让你对每个值都有自动补全：

- `EventType` —— PMMO 事件类型名称（如 `BLOCK_BREAK`、`CRAFT`、`DEATH`）
- `PMMOInternalType` —— 内部钩子类型 ID（如 `DIMENSION_TRAVEL`、`LOGIN`）
- `ReqType` —— 需求类型名称（如 `WEAPON`、`TOOL`、`KILL`）
- `ObjectType` —— 对象类型名称（如 `ITEM`、`BLOCK`、`ENTITY`）
- `ModifierDataType` —— 修正数据类型（如 `BIOME`、`HELD`、`WORN`）
- `PMMOPerkSide` —— `SERVER`、`CLIENT` 或 `BOTH`

## 版本兼容

| 组件 | 版本 |
|---|---|
| Minecraft | 1.20.1 |
| Project MMO | 1.7.40 |
| KubeJS | 2001.6.5-build.16+ |
| ProbeJS（可选） | v6 或 v7（Legacy） |

## 何时用启动脚本 vs 服务端脚本

这是最容易混淆的地方。规则很简单：

- **启动脚本** 在世界加载前运行。用于必须在加载时存在的定义和注册。
- **服务端脚本** 在世界加载后运行。用于任何响应游戏事件或需要在重载周期中修改配置的逻辑。

把运行时逻辑放在启动脚本里会失败。把注册逻辑放在服务端脚本里可能可以运行，但这并不是正确的生命周期。
