PaperTS

PaperTS是一个Paper Minecraft插件,它允许您使用TypeScript编写Minecraft服务器插件。

资源图片
# PaperTS PaperTS 是一个 Paper Minecraft 插件,它允许您使用 TypeScript 编写 Minecraft 服务器插件,通过 [Javet](https://github.com/caoccao/Javet) 在 Node.js JavaScript 引擎上运行。它为 TypeScript 模块提供运行时环境,让您可以使用 JavaScript/TypeScript 的强大功能和灵活性进行 Minecraft 服务器开发。**Node.JS 运行时在运行时下载**,插件从 [Javet 官方依赖](https://www.caoccao.com/Javet/tutorial/basic/installation.html) 安装它,您可以验证您的平台是否受支持。 ## 特性 - **TypeScript/JavaScript 插件支持**: 使用 TypeScript 或 JavaScript 编写 Minecraft 插件,并在您的 Paper 服务器上直接运行它们。 - **自动模块加载**: 扫描插件的数据文件夹中寻找模块(包含 `package.json` 的目录),自动初始化并启动它们。 - **Node.js 环境**: 使用 Javet 的 NodeRuntime 提供类似于 Node.js 的环境。 - **事件和命令注册**: 暴露 API,用于从 TypeScript 注册/取消注册 Bukkit 事件和命令。 - **热重载**: 模块可以发布和重新加载,而无需重启服务器。 ## 工作原理 1. 服务器启动时,PaperTS 扫描其数据文件夹,查找包含 `package.json` 文件的子目录。 2. 对于每个模块,它读取 `package.json` 中的 `main` 字段以找到入口脚本。 3. 入口脚本在 Node.js 运行时中执行,并可以使用 PaperTS API 与服务器进行交互。 4. 模块可以使用提供的全局 `PaperTS` 对象注册事件处理程序和命令。 ## 快速开始 1. **安装 PaperTS**: 将 PaperTS 插件 JAR 文件放置在服务器的 `plugins` 文件夹中。 2. **创建模块**: - 在 `plugins/PaperTS` 文件夹中,为您的模块创建一个新目录(例如 `my-plugin`)。 - 添加一个 `package.json` 文件,其中包含指向您的入口脚本的 `main` 字段(例如 `index.js`)。 - 编写您的 TypeScript/JavaScript 代码,如果需要,将其编译为 JavaScript。 3. **示例 `package.json`**: ```json { "name": "my-plugin", "main": "index.js" } ``` 4. **示例 `index.js`**: ```js class ServerModule { constructor() { console.log("我的插件已加载!"); } public handlePlayerJoin(event) { // 处理玩家加入事件 event.player.sendMessage(event.player.name, "欢迎来到服务器!"); } public helloCommand(sender, args) { sender.sendMessage("来自 PaperTS 的问候!"); } } const server = new ServerModule(); PaperTS.registerEvent( org.bukkit.event.player.PlayerJoinEvent, server.handlePlayerJoin.bind(server), ); PaperTS.registerCommand( "hello", "向玩家问候", "/hello", "", [], server.helloCommand.bind(server), ); ``` 5. 启动您的 Paper 服务器。PaperTS 将自动加载您的模块。您可以使用 `/paperts reload` 命令随时重新加载模块。 ### PaperTS 全局 API 以下全局 API 在您的 TypeScript/JavaScript 代码中可用: ```ts declare namespace PaperTS { export function registerEvent( eventClass: { new (...args: any[]): T }, listener: (event: T) => void, ): void; export function registerCommand( name: string, description: string, usageMessage: string, permission: string, aliases: string[], executor: (sender: CommandSender, args: string[]) => void, ): void; export function getPersistentContainerString( key: string, container: PersistentDataContainer ): string; export function hasKeyPersistentContainer( key: string, container: PersistentDataContainer ): boolean; export function setPersistentContainerString( key: string, value: string, container: PersistentDataContainer ): void; } ``` #### 注册事件 要注册事件,请使用 `PaperTS.registerEvent` 方法。您可以传递事件类和将在事件触发时执行的回调函数。 ```js export class ServerModule { public handlePlayerJoin(event) { console.log(`玩家 ${event.player.name} 加入了服务器!`); } } const server = new ServerModule(); PaperTS.registerEvent( org.bukkit.event.PlayerJoinEvent, server.handlePlayerJoin.bind(server), ); ``` #### 注册命令 要注册命令,请使用 `PaperTS.registerCommand` 方法。您可以指定命令名称、描述、用法消息、权限、别名以及将处理命令执行的执行器函数。 ```js class ServerModule { public command(sender, args) { console.log(`命令由 ${sender.displayName()} 执行,参数:${args.join(", ")}`); } } const server = new ServerModule(); PaperTS.registerCommand( "commandname", "命令描述", "/commandname ", "command.permission", ["alias1", "alias2"], server.command.bind(server), ); ``` #### 注意 使用 `bind` 是必要的,当将方法作为回调传递时,可以确保正确维护 (`this`) 上下文。 ### 使用 TypeScript 要使用 TypeScript,您可以在模块目录中设置一个 `tsconfig.json` 文件: ```json { "compilerOptions": { "incremental": true, "module": "commonjs", "esModuleInterop": true, "strict": true, "outDir": "./dist", "forceConsistentCasingInFileNames": true, "skipLibCheck": true, "typeRoots": [ "node_modules/paperts-java-ts-bind", "node_modules/@types" ] }, "include": [ "src/**/*" ] } ``` 在您的模块目录中安装必要的依赖项: ```sh npm install --save github:MetlHedd/java-ts-bind#1.20-R0.1-SNAPSHOT ``` 您可以替换版本,使用 `paperts-java-ts-bind` 软件包的另一个版本,如果您想使用其他版本,或者通过在此存储库中打开问题来请求另一个版本。 然后,您可以在 `src` 目录中编写您的 TypeScript 代码,并在 `dist` 目录中将其编译为 JavaScript。 您的 `package.json` 应该如下所示: ```json { "main": "dist/index.js", "scripts": { "watch": "tsc --project . --watch", "bundle": "esbuild src/index.ts --watch --bundle --outfile=dist/index.js --platform=node --target=node22 --external:org.* --external:com.* --external:net.* --external:java.*" }, "dependencies": { "esbuild": "^0.25.8", "paperts-java-ts-bind": "github:MetlHedd/java-ts-bind#1.20-R0.1-SNAPSHOT", "typescript": "^5.8.3", "@types/node": "^24.0.15" } } ``` 然后,您可以使用 `npm run bundle` 将您的 TypeScript 代码捆绑到一个可以由 PaperTS 运行的单个 JavaScript 文件中。 示例 `index.ts`: ```ts import { Event } from "org.bukkit.event"; import { PlayerJoinEvent } from "org.bukkit.event.player"; import { CommandSender } from "org.bukkit.command"; declare namespace PaperTS { export function registerEvent( eventClass: { new (...args: any[]): T }, listener: (event: T) => void, ): void; export function registerCommand( name: string, description: string, usageMessage: string, permission: string, aliases: string[], executor: (sender: CommandSender, args: string[]) => void, ): void; } export class ServerModule { constructor() { // 此构造函数在模块加载时调用 console.log("我的插件已加载!"); } public handlePlayerJoin(event: PlayerJoinEvent) { // 处理玩家加入事件 event.player.sendMessage(event.player.name, "欢迎来到服务器!"); } public helloCommand(sender: CommandSender, args: string[]) { sender.sendMessage("来自 PaperTS 的问候!"); } } const server = new ServerModule(); PaperTS.registerEvent( PlayerJoinEvent, server.handlePlayerJoin.bind(server), ); PaperTS.registerCommand( "hello", "向玩家问候", "/hello", "", [], server.helloCommand.bind(server), ); ``` ### 国际化 (i18n) PaperTS 通过 Node.js 运行时支持国际化 (i18n),从而能够使用一些 Node.js 模块实现更兼容的行为。要启用 i18n,请在插件的数据文件夹中创建一个名为 `node-icu` 的文件夹(通常为 `plugins/PaperTS/node-icu`),并将 ICU 数据文件放置在那里。您可以从 [Javet 存储库](https://github.com/caoccao/Javet) 的任何操作中下载 ICU 数据文件。插件将自动检测 `node-icu` 文件夹是否存在,并启用 i18n 支持。 ## 插件命令 您可以使用以下命令来管理您的 PaperTS 模块: - `/paperts reload`: 重新加载所有模块。 - `/paperts reload `: 重新加载一个特定的模块。 - `/paperts list`: 列出所有已加载的模块。 - `/paperts unload `: 卸载一个特定的模块。 - `/paperts load `: 加载一个特定的模块。 ## 开发 PaperTS 使用 [Javet](https://github.com/caoccao/Javet) 嵌入 V8 引擎和 Node.js 运行时。该插件管理引擎池、工作目录,并暴露一个 `Globals` API 来管理事件和命令。 ### 构建 使用 Gradle 构建: ```sh ./gradlew build ``` 输出 JAR 将在 `app/build/libs/` 中。 ## 贡献 欢迎贡献!请为错误修复、功能或文档改进打开问题或拉取请求。 ## 灵感 一些激发 PaperTS 的项目: - [Grakkit](https://github.com/grakkit/grakkit) - [Javet](https://github.com/caoccao/Javet) - [Custom Realms](https://github.com/customrealms) - [CraftJS](https://github.com/Dysfold/craftjs)