docs: areacontrol, event_register, README

This commit is contained in:
2025-11-11 16:44:56 +08:00
parent 11bd909a4f
commit b6a958af58
7 changed files with 576 additions and 168 deletions

View File

@@ -1,168 +0,0 @@
# AreaControl 脚本 MDocs
## 1. 概述
**AreaControl** 是一个为 Minecraft 服务器设计的强大区域管理工具,通过 KubeJS 实现。它允许管理员在游戏世界中定义一个特殊区域,并对进入该区域的玩家施加特定的规则,例如自动切换游戏模式、限制物品使用等。
该脚本的核心设计理念是 **高性能****易用性**。它采用事件驱动和多种优化技术,确保在不牺牲服务器性能的前提下,提供稳定可靠的功能。本文档将为您提供从安装、使用到二次开发的全方位指南。
---
## 2. 功能特性
- **自动模式切换**:玩家进入指定区域时,自动切换为**冒险**或**旁观**模式;离开时恢复为**生存**模式。
- **动态白名单**:所有功能仅对白名单内的玩家生效,管理员可通过命令随时增删玩家。
- **物品冷却系统**:可以为区域内的玩家设置统一的物品使用冷却时间。
- **实时启/禁用**:管理员可通过一条简单命令,在不重启服务器的情况下,全局启用或禁用所有功能。
- **二维平面检测**区域检测仅基于水平坐标X 和 Z 轴忽略玩家的高度Y 轴),适用于各种地形。
- **高性能设计**基于事件驱动无不必要的循环tick-polling确保对服务器的性能影响降至最低。
- **配置持久化**:所有配置(如区域中心、半径、白名单)都会自动保存,服务器重启后无需重新设置。
---
## 3. 用户指南
本节面向服务器管理员和普通用户,指导您如何安装和使用 AreaControl。
### 3.1. 安装
1. 确保您的 Minecraft 服务器已经正确安装了 KubeJS Mod。
2. 将编译后的 `areacontrol.js` 脚本文件放置在服务器的 `kubejs/server_scripts/` 目录下。
3. 重新启动服务器或在游戏内执行 `/kubejs reload server_scripts`
脚本加载后将自动初始化,默认在世界中心 `(0, 0)` 创建一个半径为 `50` 格的区域。
### 3.2. 管理命令
您可以在游戏内通过 `areacontrol` 系列命令来管理脚本。所有命令都需要管理员权限。
* `/areacontrol status`:查看脚本当前配置。
* `/areacontrol toggle`:全局启用或禁用功能。
* `/areacontrol setcenter`:将当前位置设为区域中心。
* `/areacontrol setradius <半径>`:设置区域半径。
* `/areacontrol whitelist <add|remove|list> [玩家名]`:管理白名单。
---
## 4. 开发者参考:技术与定制
本节面向希望理解其工作原理或进行二次开发的开发者。
### 4.1. 开发环境与构建
本项目使用 **TypeScript** 编写,以获得更强的类型安全和代码可维护性。
- **源码目录**:所有服务器端脚本的 TypeScript 源文件位于 `src/server_scripts/` 目录下。
- **编译**:在发布或测试前,需要将 TypeScript (`.ts`) 文件编译为 KubeJS 可识别的 JavaScript (`.js`) 文件。
- **单次编译**:执行 `npm run tsc``npx tsc --project tsconfig.server.json`
- **监视模式**:在开发过程中,建议使用监视模式,它会在文件发生变化时自动重新编译。执行 `npm run watch::server` 即可。
- **类型定义**:项目依赖于 KubeJS Probe 生成的类型定义,位于 `types/probe-types/` 目录,这为开发提供了完整的代码提示和类型检查。
### 4.2. 设计理念
#### 事件驱动架构
脚本不使用高开销的 `tick` 轮询,而是监听特定玩家事件来触发逻辑。
- `PlayerEvents.loggedIn`: 玩家登录时加入检查。
- `PlayerEvents.loggedOut`: 玩家登出时清理其缓存数据。
- `PlayerEvents.tick`: **降频使用**,每秒检查一次玩家位置。
- `ItemEvents.use`: 在玩家使用物品时触发冷却逻辑。
```typescript
// 示例:利用类型定义,精确捕获事件和玩家对象
ItemEvents.use((event: Internal.ItemUseEvent) => {
const { player } = event;
if (player && shouldApplyCooldown(player)) {
// ...
}
});
```
#### 分层与状态缓存
为避免不必要的操作,脚本采用分层检查和状态缓存。
1. **一级过滤**:检查脚本是否启用、玩家是否在白名单内。
2. **二级检查(降频)**:每秒检查一次玩家是否在区域内。
3. **三级处理(状态驱动)**:仅当玩家**跨越区域边界**时,才执行核心操作并更新缓存。
```typescript
// playerStates 缓存玩家的当前状态,并提供类型安全
const playerStates = new Map<string, { inArea: boolean }>();
function optimizedPlayerCheck(player: Internal.Player): void {
const currentState = playerStates.get(player.uuid) ?? { inArea: false };
const isInArea = isPlayerInArea(player);
if (currentState.inArea !== isInArea) {
handleGameModeChange(player, isInArea);
playerStates.set(player.uuid, { inArea: isInArea });
}
}
```
### 4.3. 核心算法
#### 快速边界检测
脚本通过**预计算**区域的边界框Bounding Box来实现高效的位置判断。
```typescript
// 1. 初始化时预计算边界
function updateBounds(center: Internal.Vec3i, radius: number): void {
bounds.minX = center.x - radius;
bounds.maxX = center.x + radius;
bounds.minZ = center.z - radius;
bounds.maxZ = center.z + radius;
}
// 2. 运行时进行高效比较
function isPlayerInArea(player: Internal.Player): boolean {
const pos = player.blockPosition();
return pos.x >= bounds.minX && pos.x <= bounds.maxX &&
pos.z >= bounds.minZ && pos.z <= bounds.maxZ;
}
```
#### 内存自动清理
通过监听 `PlayerEvents.loggedOut` 事件,自动从 `playerStates` 缓存中删除下线玩家的数据,防止内存泄漏。
### 4.4. 数据结构
我们使用 TypeScript 的 `interface` 来定义核心数据结构,确保类型安全。
#### 配置 (AreaControlConfig)
```typescript
interface AreaControlConfig {
enabled: boolean;
center: { x: number; y: number; z: number };
radius: number;
whitelist: string[];
mode: 'adventure' | 'spectator';
cooldownTime: number; // In ticks
}
```
#### 缓存 (PlayerState)
```typescript
interface PlayerState {
inArea: boolean;
}
// 最终的缓存结构
const playerStates: Map<string, PlayerState>; // Key: Player UUID
```
### 4.5. 定制化
#### 调整检查频率
默认检查频率是每秒一次(`20 ticks`)。您可以根据服务器需求调整此值。
```typescript
// 在 PlayerEvents.tick 监听器中调整
PlayerEvents.tick((event: Internal.PlayerTickEvent) => {
const player = event.player;
// 将 20 修改为您希望的检查间隔ticks
if (player.age % 20 === 0) {
optimizedPlayerCheck(player);
}
});
```
- **建议值**`10`(半秒一次,响应快),`40`(两秒一次,开销低)。不建议低于 `10`

149
docs/areacontrol_en.md Normal file
View File

@@ -0,0 +1,149 @@
# `areacontrol.js` Script Documentation
## 1. Overview
**AreaControl** is a powerful area management tool for Minecraft servers, implemented via KubeJS. It allows administrators to define a special zone in the game world and apply specific rules to players who enter it, such as automatically switching game modes or restricting item usage.
The core design philosophy of this script is **high performance** and **ease of use**. It employs an event-driven architecture and various optimization techniques to provide stable and reliable functionality without sacrificing server performance. This document will provide a comprehensive guide from installation and usage to technical implementation.
## 2. Features
- **Automatic Mode Switching**: Automatically switches players to **Adventure** or **Spectator** mode upon entering a specified area, and back to **Survival** mode upon leaving.
- **Flexible Whitelist**: Administrators can add players to a whitelist via commands, exempting them from game mode changes. OPs are exempt by default, but this is configurable.
- **Item Cooldown System**: Sets a uniform item usage cooldown for all players within the zone. This feature depends on the `event_register.js` script.
- **Real-time Toggling**: Administrators can globally enable or disable all features with a single command, without restarting the server.
- **High-Performance Design**:
- **Event-Driven**: Logic is triggered only on player login, logout, or movement, with no unnecessary polling.
- **Throttled Checks**: Player position checks are throttled (defaulting to once every 3 seconds) to reduce server load, and the frequency is configurable.
- **State Caching**: Core operations are executed only when a player crosses the area boundary, avoiding redundant calculations.
- **Configuration Persistence**: All settings (like the zone's center, radius, and whitelist) are saved automatically and persist through server restarts.
- **Rich Management Commands**: Provides a complete set of commands for real-time adjustment of all script parameters.
## 3. User Guide
This section is for server administrators, guiding you on how to install and use AreaControl.
### 3.1. Installation
1. Ensure your Minecraft server has the KubeJS Mod installed correctly.
2. Place the `areacontrol.js` script file in the server's `kubejs/server_scripts/` directory.
3. (Optional) If you need to enable the **Item Cooldown** feature, make sure `event_register.js` is also installed in the `kubejs/startup_scripts/` directory.
4. Restart the server or run `/kubejs reload server_scripts` in-game.
The script will initialize automatically upon loading.
### 3.2. Management Commands
You can manage the script in-game using the `/areacontrol` command series. All commands require administrator privileges (level 2 or higher).
- `/areacontrol status`
- **Function**: View all current configurations and the running status of the script.
- `/areacontrol toggle`
- **Function**: Globally enable or disable the script. When disabled, all players inside the zone will be returned to Survival mode.
- `/areacontrol toggleIncludingOPs`
- **Function**: Toggle whether to include administrators (OPs) in the game mode management.
- `/areacontrol toggleCooldown`
- **Function**: Enable or disable the item cooldown feature.
- `/areacontrol setcenter`
- **Function**: Set your current position as the center of the zone.
- `/areacontrol setradius <radius>`
- **Function**: Set the radius of the zone.
- **Example**: `/areacontrol setradius 100`
- `/areacontrol setmode <adventure|spectator>`
- **Function**: Set the game mode players will be switched to upon entering the zone.
- **Example**: `/areacontrol setmode spectator`
- `/areacontrol setcooldown <ticks>`
- **Function**: Set the item cooldown time in game ticks (20 ticks = 1 second).
- **Example**: `/areacontrol setcooldown 200` (sets a 10-second cooldown)
- `/areacontrol setcheckfrequency <ticks>`
- **Function**: Set the frequency for checking player positions, in game ticks. A lower value is more responsive but has a higher performance cost.
- **Example**: `/areacontrol setcheckfrequency 40` (checks every 2 seconds)
- `/areacontrol whitelist <add|remove|list> [playerName]`
- **Function**: Manage the whitelist. Whitelisted players are not affected by game mode changes.
- `add <playerName>`: Add a player to the whitelist.
- `remove <playerName>`: Remove a player from the whitelist.
- `list`: List all players on the whitelist.
- `/areacontrol reload`
- **Function**: Reload the configuration from storage.
- `/areacontrol help`
- **Function**: Display a list of all available commands in-game.
## 4. Technical Implementation
This section is for developers who want to understand how it works or perform secondary development.
### 4.1. Script and Environment
This project is written in **JavaScript** and uses JSDoc comments for type hinting to enhance code readability and maintainability. No compilation step is required for development.
- **Source File**: `kubejs/server_scripts/areacontrol.js`
- **Configuration File**: The script's configuration is stored via KubeJS's persistent data API, typically located at `saves/<world_name>/server_data/areacontrol_config.json`. Manual editing of this file is not recommended.
### 4.2. Core Design
#### Event-Driven Architecture
The script avoids high-cost `tick` polling and instead listens for specific player events to trigger logic.
- `PlayerEvents.loggedIn`: When a player logs in, their position is checked and their state is initialized.
- `PlayerEvents.loggedOut`: When a player logs out, their cached data is cleared to prevent memory leaks.
- `PlayerEvents.tick`: **Used with throttling**. By default, it checks the player's position once every 3 seconds (60 ticks), with an adjustable frequency.
```javascript
// Example: Throttled player position check
PlayerEvents.tick((event) => {
const { player } = event;
// Use player.age and configurable frequency for modulo operation
if (player.age % config.checkFrequency === 0) {
checkPlayerAreaStatus(player);
}
});
```
#### State Caching and Boundary Detection
To avoid unnecessary operations, the script uses state caching and fast boundary detection.
1. **Boundary Pre-calculation**: When `center` or `radius` changes, the script pre-calculates the area's `minX`, `maxX`, `minZ`, `maxZ` boundaries.
2. **Fast Detection**: When checking a player's position, it only needs to compare the player's X and Z coordinates with the pre-calculated boundaries, which is an efficient O(1) operation.
3. **State Caching**: A global object named `playerStates` caches whether each player is inside the area (as a boolean). The core logic, like switching game modes, is executed only when the player's current state differs from the cached state (i.e., the player has crossed the area boundary). The cache is then updated.
```javascript
// playerStates caches the current state of players
let playerStates = {}; // { [playerUuid]: boolean }
function checkPlayerAreaStatus(player) {
// ...
const isCurrentlyInArea = isPositionInArea(pos.x, pos.z);
const cachedState = playerStates[player.stringUuid];
// Only perform actions when the state changes
if (cachedState !== isCurrentlyInArea) {
if (isCurrentlyInArea) {
handlePlayerEnterArea(player);
} else if (cachedState === true) {
handlePlayerLeaveArea(player);
}
// Update the cache
playerStates[player.stringUuid] = isCurrentlyInArea;
}
}
```
### 4.3. Interaction with `event_register.js`
The item cooldown feature of `areacontrol.js` is an optional module that relies on the global event bus `eventBus` provided by `event_register.js`.
- **Check on Startup**: The script checks if `global['eventBus']` exists during initialization.
- **Graceful Degradation**: If `eventBus` is not defined, the `enableCooldown` setting is forcibly set to `false`, and all cooldown-related features (including commands) become unavailable.
- **Event Listening**: If `eventBus` exists, the script registers a listener for the `LivingEntityUseItemEvent$Finish` event. When a player in the area finishes using an item, this listener is triggered and adds a cooldown to the item based on the `cooldownSecs` configuration.
This design allows `areacontrol.js` to run standalone (without item cooldowns) or in conjunction with `event_register.js` to provide richer functionality, achieving decoupling between modules.

149
docs/areacontrol_zh.md Normal file
View File

@@ -0,0 +1,149 @@
# `areacontrol.js` 脚本说明
## 1. 概述
**AreaControl** 是一个为 Minecraft 服务器设计的强大的区域管理工具,通过 KubeJS 实现。它允许管理员在游戏世界中定义一个特殊区域,并对进入该区域的玩家施加特定的规则,例如自动切换游戏模式、限制物品使用等。
该脚本的核心设计理念是 **高性能****易用性**。它采用事件驱动和多种优化技术,确保在不牺牲服务器性能的前提下,提供稳定可靠的功能。本文档将为您提供从安装、使用到技术实现的全方位指南。
## 2. 功能特性
- **自动模式切换**:玩家进入指定区域时,自动切换为**冒险**或**旁观**模式;离开时恢复为**生存**模式。
- **灵活的白名单**管理员可以通过命令将玩家加入白名单使其不受游戏模式变更的影响。默认情况下OP 不受影响,但此项可配置。
- **物品冷却系统**:可以为区域内的玩家设置统一的物品使用冷却时间。此功能依赖 `event_register.js` 脚本。
- **实时启/禁用**:管理员可通过一条简单命令,在不重启服务器的情况下,全局启用或禁用所有功能。
- **高性能设计**
- **事件驱动**:仅在玩家登录、登出或移动时触发逻辑,无不必要的轮询。
- **降频检查**:玩家位置检查频率可调(默认为每 3 秒一次),减少服务器负担。
- **状态缓存**:只在玩家跨越区域边界时执行核心操作,避免重复计算。
- **配置持久化**:所有配置(如区域中心、半径、白名单)都会自动保存,服务器重启后依然不会丢失数据。
- **丰富的管理命令**:提供了一套完整的命令,用于实时调整脚本的所有参数。
## 3. 用户指南
本节面向服务器管理员,指导您如何安装和使用 AreaControl。
### 3.1. 安装
1. 确保您的 Minecraft 服务器已经正确安装了 KubeJS Mod。
2.`areacontrol.js` 脚本文件放置在服务器的 `kubejs/server_scripts/` 目录下。
3. (可选)如果需要启用**物品冷却**功能,请确保 `event_register.js` 也已安装在 `kubejs/startup_scripts/` 目录下。
4. 重新启动服务器或在游戏内执行 `/kubejs reload server_scripts`
脚本加载后将自动初始化。
### 3.2. 管理命令
您可以在游戏内通过 `/areacontrol` 系列命令来管理脚本。所有命令都需要管理员权限(等级 2 或更高)。
- `/areacontrol status`
- **功能**:查看脚本所有当前的配置和运行状态。
- `/areacontrol toggle`
- **功能**:全局启用或禁用脚本。禁用时,所有在区域内的玩家将恢复为生存模式。
- `/areacontrol toggleIncludingOPs`
- **功能**切换是否将管理员OP纳入游戏模式更改的管理范围。
- `/areacontrol toggleCooldown`
- **功能**:启用或禁用物品冷却功能。
- `/areacontrol setcenter`
- **功能**:将您当前的位置设置为区域的中心点。
- `/areacontrol setradius <半径>`
- **功能**:设置区域的半径。
- **示例**`/areacontrol setradius 100`
- `/areacontrol setmode <adventure|spectator>`
- **功能**:设置玩家进入区域后切换到的游戏模式。
- **示例**`/areacontrol setmode spectator`
- `/areacontrol setcooldown <刻数>`
- **功能**设置物品冷却时间单位为游戏刻ticks, 20 ticks = 1 秒)。
- **示例**`/areacontrol setcooldown 200` (设置为 10 秒)
- `/areacontrol setcheckfrequency <刻数>`
- **功能**:设置检查玩家位置的频率,单位为游戏刻。较低的值响应更快,但性能开销更高。
- **示例**`/areacontrol setcheckfrequency 40` (设置为每 2 秒检查一次)
- `/areacontrol whitelist <add|remove|list> [玩家名]`
- **功能**:管理白名单。白名单内的玩家将不受游戏模式更改的影响。
- `add <玩家名>`:添加玩家到白名单。
- `remove <玩家名>`:从白名单移除玩家。
- `list`:列出所有白名单内的玩家。
- `/areacontrol reload`
- **功能**:从存储中重新加载配置。
- `/areacontrol help`
- **功能**:在游戏内显示所有可用命令的列表。
## 4. 技术实现
本节面向希望理解其工作原理或进行二次开发的开发者。
### 4.1. 脚本与环境
本项目使用 **JavaScript** 编写,并利用 JSDoc 注释提供类型提示,以增强代码的可读性和可维护性。开发时无需编译步骤。
- **源码文件**`kubejs/server_scripts/areacontrol.js`
- **配置文件**:脚本的配置通过 KubeJS 的持久化数据 API 存储,通常位于 `saves/<世界名>/server_data/areacontrol_config.json`。不建议手动修改此文件。
### 4.2. 核心设计
#### 事件驱动架构
脚本不使用高开销的 `tick` 轮询,而是监听特定玩家事件来触发逻辑。
- `PlayerEvents.loggedIn`: 玩家登录时,检查其位置并初始化状态。
- `PlayerEvents.loggedOut`: 玩家登出时,清理其缓存数据以防内存泄漏。
- `PlayerEvents.tick`: **降频使用**,默认每 3 秒60 ticks检查一次玩家位置频率可调。
```javascript
// 示例:降频检查玩家位置
PlayerEvents.tick((event) => {
const { player } = event;
// 使用 player.age 和可配置的频率进行模运算
if (player.age % config.checkFrequency === 0) {
checkPlayerAreaStatus(player);
}
});
```
#### 状态缓存与边界检测
为避免不必要的操作,脚本采用状态缓存和快速边界检测。
1. **边界预计算**:当 `center``radius` 改变时,脚本会预先计算出区域的 `minX`, `maxX`, `minZ`, `maxZ` 边界。
2. **快速检测**:在检查玩家位置时,只需将玩家的 X 和 Z 坐标与预计算的边界进行比较,这是一个 O(1) 的高效操作。
3. **状态缓存**:一个名为 `playerStates` 的全局对象缓存着每个玩家是否在区域内的布尔值。只有当玩家的当前状态与缓存状态不一致时(即玩家穿越了区域边界),脚本才会执行游戏模式切换等核心逻辑,并更新缓存。
```javascript
// playerStates 缓存玩家的当前状态
let playerStates = {}; // { [playerUuid]: boolean }
function checkPlayerAreaStatus(player) {
// ...
const isCurrentlyInArea = isPositionInArea(pos.x, pos.z);
const cachedState = playerStates[player.stringUuid];
// 仅当状态发生变化时才执行操作
if (cachedState !== isCurrentlyInArea) {
if (isCurrentlyInArea) {
handlePlayerEnterArea(player);
} else if (cachedState === true) {
handlePlayerLeaveArea(player);
}
// 更新缓存
playerStates[player.stringUuid] = isCurrentlyInArea;
}
}
```
### 4.3. 与 `event_register.js` 的交互
`areacontrol.js` 的物品冷却功能是一个可选模块,它依赖于 `event_register.js` 提供的全局事件总线 `eventBus`
- **启动时检查**:脚本在初始化时会检查 `global['eventBus']` 是否存在。
- **功能降级**:如果 `eventBus` 未定义,`enableCooldown` 配置将被强制设为 `false`,并且与冷却相关的功能(包括命令)将不可用。
- **事件监听**:如果 `eventBus` 存在,脚本会注册 `LivingEntityUseItemEvent$Finish` 事件的监听器。当区域内的玩家完成物品使用时,此监听器会触发并根据 `cooldownSecs` 配置为该物品添加冷却。
这种设计使得 `areacontrol.js` 既可以独立运行(不带物品冷却),也可以与 `event_register.js` 配合使用以提供更丰富的功能,实现了模块间的解耦。

102
docs/event_register_en.md Normal file
View File

@@ -0,0 +1,102 @@
# `event_register.js` Script Documentation
## Overview
`event_register.js` provides a simple custom event bus system. It allows for decoupled event listening and firing between different KubeJS script files, leading to cleaner and more modular code organization. This script creates a global `eventBus` object that can be used to register and emit events in any server, client, or startup script.
## Features
- **Globally Available**: Exposes the event bus to the global scope via `global['eventBus']`, making it easy to call from any KubeJS script.
- **Simplified Event Handling**: Converts complex native events (like Forge events) into easier-to-manage custom events.
- **Code Decoupling**: Allows one script to fire an event while one or more other scripts can listen and react, reducing direct dependencies between scripts.
- **Easy to Extend**: You can easily add listeners for more native events and forward them through the `eventBus`.
## Usage Guide
The core of this script is the `eventBus` object, which has two main methods: `register` and `emit`.
### 1. Registering an Event Listener (`eventBus.register`)
Use this method to listen for a custom event. When the event is fired, the provided callback function will be executed.
- **Parameters**:
- `eventName` (string): The name of the event to listen for.
- `callback` (Function): The callback function to execute when the event is fired. It receives an `event` object as its parameter.
**Example**:
Let's say we want to perform an action when a player finishes using an item.
```javascript
// In one of your scripts (e.g., server_scripts/my_script.js)
// Listen for the "LivingEntityUseItemEvent$Finish" event
eventBus.register("LivingEntityUseItemEvent$Finish", event => {
const { entity, item, level } = event;
// Check if the entity is a player
if (entity.isPlayer()) {
// Print a message to the server log
console.log(`${entity.name.string} finished using ${item.id}`);
// Give the player an apple
entity.give('minecraft:apple');
}
});
```
### 2. Firing an Event (`eventBus.emit`)
Use this method to fire a custom event. All listeners registered for that event will be called.
- **Parameters**:
- `eventName` (string): The name of the event to fire.
- `event` (*): The event data object to pass to the callback functions.
**Built-in Implementation**:
The `event_register.js` script already listens for a native Forge event and forwards it through the `eventBus`.
```javascript
// Internal code in event_register.js
// Listen for the native Forge event for when an item is finished being used
ForgeEvents.onEvent(
"net.minecraftforge.event.entity.living.LivingEntityUseItemEvent$Finish",
(event) => {
// When the native event occurs, fire an event with the same name on the custom event bus
eventBus.emit("LivingEntityUseItemEvent$Finish", event);
},
);
```
This implementation means you don't have to listen for that complex Forge event name yourself. You just need to listen for `LivingEntityUseItemEvent$Finish` via `eventBus.register`, as shown in the first example.
### 3. Firing a New Custom Event
You can also use the `eventBus` to create and manage your own custom events for communication between your different script modules.
**Example**:
Suppose one script is responsible for detecting if a player enters a specific area and wants to notify another script to perform a follow-up action.
**Script A: `server_scripts/area_detector.js`**
```javascript
// (Pseudo-code) Assume we have a method to check the player's position
PlayerEvents.tick(event => {
const { player } = event;
if (player.x > 100 && player.z > 200 && player.level.dimension == 'minecraft:overworld') {
// The player has entered the "danger zone", fire a custom event
eventBus.emit('kubejs:player_entered_danger_zone', { player: player, zone: 'A1' });
}
});
```
**Script B: `server_scripts/zone_handler.js`**
```javascript
// Listen for the custom event fired by Script A
eventBus.register('kubejs:player_entered_danger_zone', event => {
const { player, zone } = event;
player.tell(`You have entered zone ${zone}, be careful!`);
player.potionEffects.add('minecraft:slowness', 600, 1); // Apply slowness effect
});
```
In this way, `area_detector.js` doesn't need to know about `zone_handler.js`. It is only responsible for sending a signal (the event) under certain conditions. Any other script can choose to listen for this signal and react, achieving modular functionality.

102
docs/event_register_zh.md Normal file
View File

@@ -0,0 +1,102 @@
# `event_register.js` 脚本说明
## 概述
`event_register.js` 提供了一个简单的自定义事件总线Event Bus系统。它允许在 KubeJS 的不同脚本文件之间解耦事件的监听和触发,使得代码组织更加清晰和模块化。该脚本创建了一个全局变量 `eventBus`,可用于在任何服务器、客户端或启动脚本中注册和触发事件。
## 特点
- **全局可用**: 通过 `global['eventBus']` 将事件总线暴露到全局,方便在任何 KubeJS 脚本中调用。
- **简化事件处理**: 将复杂的原生事件(如 Forge 事件)转换为更易于管理和使用的自定义事件。
- **代码解耦**: 允许一个脚本触发事件,而另一个或多个脚本监听并响应这些事件,降低了脚本之间的直接依赖。
- **易于扩展**: 可以轻松添加对更多原生事件的监听,并将它们通过 `eventBus` 进行转发。
## 使用说明
该脚本的核心是 `eventBus` 对象,它有两个主要方法:`register``emit`
### 1. 注册事件监听器 (`eventBus.register`)
使用此方法来监听一个自定义事件。当该事件被触发时,提供的回调函数将被执行。
- **参数**:
- `eventName` (string): 要监听的事件名称。
- `callback` (Function): 事件触发时要执行的回调函数,它会接收到一个 `event` 对象作为参数。
**示例**:
假设我们想在玩家完成使用物品时执行某些操作。
```javascript
// 在你的某个脚本中 (例如: server_scripts/my_script.js)
// 监听 "LivingEntityUseItemEvent$Finish" 事件
eventBus.register("LivingEntityUseItemEvent$Finish", event => {
const { entity, item, level } = event;
// 检查实体是否为玩家
if (entity.isPlayer()) {
// 在服务器日志中打印消息
console.log(`${entity.name.string} 使用完成了 ${item.id}`);
// 给予玩家一个苹果
entity.give('minecraft:apple');
}
});
```
### 2. 触发事件 (`eventBus.emit`)
使用此方法来触发一个自定义事件。所有注册了该事件的监听器都将被调用。
- **参数**:
- `eventName` (string): 要触发的事件名称。
- `event` (*): 要传递给回调函数的事件数据对象。
**脚本内置实现**:
`event_register.js` 脚本内部已经监听了一个原生的 Forge 事件,并在该事件发生时通过 `eventBus` 进行了转发。
```javascript
// event_register.js 内部代码
// 监听原生的 Forge 物品使用完成事件
ForgeEvents.onEvent(
"net.minecraftforge.event.entity.living.LivingEntityUseItemEvent$Finish",
(event) => {
// 当原生事件发生时,通过自定义事件总线触发同名事件
eventBus.emit("LivingEntityUseItemEvent$Finish", event);
},
);
```
这个实现意味着你无需自己去监听那个复杂的 Forge 事件名称。你只需要通过 `eventBus.register` 监听 `LivingEntityUseItemEvent$Finish` 即可,如第一个示例所示。
### 3. 触发一个全新的自定义事件
你也可以利用 `eventBus` 来创建和管理完全由你定义的事件,用于在你的不同脚本模块之间通信。
**示例**:
假设一个脚本负责检测玩家是否进入了特定区域,并希望通知另一个脚本来执行后续操作。
**脚本 A: `server_scripts/area_detector.js`**
```javascript
// (伪代码) 假设我们有一个方法来检测玩家位置
PlayerEvents.tick(event => {
const { player } = event;
if (player.x > 100 && player.z > 200 && player.level.dimension == 'minecraft:overworld') {
// 玩家进入了 "危险区域",触发一个自定义事件
eventBus.emit('kubejs:player_entered_danger_zone', { player: player, zone: 'A1' });
}
});
```
**脚本 B: `server_scripts/zone_handler.js`**
```javascript
// 监听由脚本 A 触发的自定义事件
eventBus.register('kubejs:player_entered_danger_zone', event => {
const { player, zone } = event;
player.tell(`你已进入区域 ${zone},请小心!`);
player.potionEffects.add('minecraft:slowness', 600, 1); // 给予缓慢效果
});
```
通过这种方式,`area_detector.js` 无需知道 `zone_handler.js` 的存在,它只负责在特定条件下发出一个信号(事件)。任何其他脚本都可以选择监听这个信号并做出响应,实现了功能的模块化。