diff --git a/Box3JS-NeoForge-1.21.1/docs/.vitepress/config.mjs b/Box3JS-NeoForge-1.21.1/docs/.vitepress/config.mjs index 849e398..36f3c78 100644 --- a/Box3JS-NeoForge-1.21.1/docs/.vitepress/config.mjs +++ b/Box3JS-NeoForge-1.21.1/docs/.vitepress/config.mjs @@ -1,219 +1,237 @@ -import { defineConfig } from 'vitepress' +import { defineConfig } from "vitepress"; const cnNav = [ - { text: '首页', link: '/' }, - { text: '指南', link: '/guide/README' }, - { text: '教程', link: '/tutorial/README' }, - { text: 'API', link: '/api/README' }, -] + { text: "首页", link: "/" }, + { text: "指南", link: "/guide/README" }, + { text: "教程", link: "/tutorial/README" }, + { text: "API", link: "/api/README" }, +]; const enNav = [ - { text: 'Home', link: '/en/' }, - { text: 'Guide', link: '/en/guide/README' }, - { text: 'Tutorials', link: '/en/tutorial/README' }, - { text: 'API', link: '/en/api/README' }, -] + { text: "Home", link: "/en/" }, + { text: "Guide", link: "/en/guide/README" }, + { text: "Tutorials", link: "/en/tutorial/README" }, + { text: "API", link: "/en/api/README" }, +]; const cnSidebar = [ { - text: '快速开始', + text: "快速开始", collapsed: false, items: [ - { text: '文档索引', link: '/overview' }, - { text: '总览', link: '/guide/README' }, - { text: '快速开始', link: '/guide/getting-started' }, - { text: '常用配方', link: '/guide/recipes' }, - { text: '常见问题', link: '/guide/faq' }, - { text: '运行原理', link: '/guide/architecture' }, - { text: 'JS vs Java', link: '/guide/js-vs-java' }, - { text: '关于 Box3JS', link: '/guide/about-box3js' }, + { text: "文档索引", link: "/overview" }, + { text: "总览", link: "/guide/README" }, + { text: "快速开始", link: "/guide/getting-started" }, + { text: "常用配方", link: "/guide/recipes" }, + { text: "常见问题", link: "/guide/faq" }, + { text: "运行原理", link: "/guide/architecture" }, + { text: "JS vs Java", link: "/guide/js-vs-java" }, + { text: "关于 Box3JS", link: "/guide/about-box3js" }, ], }, { - text: '教程', + text: "教程", collapsed: false, items: [ - { text: '总览', link: '/tutorial/README' }, - { text: '01 — 基础入门', link: '/tutorial/01-basics' }, - { text: '02 — 玩家与物品', link: '/tutorial/02-player-items' }, - { text: '03 — 事件与实体', link: '/tutorial/03-events-entities' }, - { text: '04 — 进阶系统', link: '/tutorial/04-advanced-systems' }, - { text: '05 — 实战案例', link: '/tutorial/05-examples' }, - { text: '06 — 客户端脚本', link: '/tutorial/06-client-scripting' }, + { text: "总览", link: "/tutorial/README" }, + { text: "01 — 基础入门", link: "/tutorial/01-basics" }, + { text: "02 — 玩家与物品", link: "/tutorial/02-player-items" }, + { text: "03 — 事件与实体", link: "/tutorial/03-events-entities" }, + { text: "04 — 进阶系统", link: "/tutorial/04-advanced-systems" }, + { text: "05 — 实战案例", link: "/tutorial/05-examples" }, + { text: "06 — 客户端脚本", link: "/tutorial/06-client-scripting" }, ], }, { - text: 'API 参考', + text: "API 参考", collapsed: false, items: [ - { text: '总览', link: '/api/README' }, + { text: "总览", link: "/api/README" }, { - text: '服务端 API', + text: "服务端 API", collapsed: false, items: [ - { text: 'Server', link: '/api/server' }, - { text: 'World', link: '/api/world' }, - { text: 'Entity', link: '/api/entity' }, - { text: 'Player', link: '/api/player' }, - { text: 'Voxels', link: '/api/voxels' }, - { text: 'Registries', link: '/api/registries' }, + { text: "Server", link: "/api/server" }, + { text: "World", link: "/api/world" }, + { text: "Entity", link: "/api/entity" }, + { text: "Player", link: "/api/player" }, + { text: "Voxels", link: "/api/voxels" }, + { text: "Registries", link: "/api/registries" }, ], }, { - text: '客户端 API', + text: "客户端 API", collapsed: false, items: [ - { text: 'Client', link: '/api/client' }, + { text: "Client", link: "/api/client" }, + { text: "Audio", link: "/api/audio" }, + { text: "Input", link: "/api/input" }, + { text: "UI", link: "/api/ui" }, + { text: "Chat", link: "/api/chat" }, + { text: "GUI", link: "/api/gui" }, ], }, { - text: '共用 API', + text: "共用 API", collapsed: false, items: [ - { text: 'Storage', link: '/api/storage' }, - { text: 'Database', link: '/api/database' }, - { text: 'HTTP', link: '/api/http' }, - { text: 'Math', link: '/api/math' }, + { text: "Storage", link: "/api/storage" }, + { text: "Database", link: "/api/database" }, + { text: "HTTP", link: "/api/http" }, + { text: "Math", link: "/api/math" }, + { text: "RemoteChannel", link: "/api/remote-channel" }, ], }, { - text: '命令参考', + text: "命令参考", collapsed: false, - items: [ - { text: '/box3script', link: '/api/commands' }, - ], + items: [{ text: "/box3script", link: "/api/commands" }], }, ], }, -] +]; const enSidebar = [ { - text: 'Get Started', + text: "Get Started", collapsed: false, items: [ - { text: 'Overview', link: '/en/guide/README' }, - { text: 'Getting Started', link: '/en/guide/getting-started' }, - { text: 'Recipes', link: '/en/guide/recipes' }, - { text: 'FAQ', link: '/en/guide/faq' }, - { text: 'Architecture', link: '/en/guide/architecture' }, - { text: 'JS vs Java', link: '/en/guide/js-vs-java' }, - { text: 'About Box3JS', link: '/en/guide/about-box3js' }, + { text: "Overview", link: "/en/guide/README" }, + { text: "Getting Started", link: "/en/guide/getting-started" }, + { text: "Recipes", link: "/en/guide/recipes" }, + { text: "FAQ", link: "/en/guide/faq" }, + { text: "Architecture", link: "/en/guide/architecture" }, + { text: "JS vs Java", link: "/en/guide/js-vs-java" }, + { text: "About Box3JS", link: "/en/guide/about-box3js" }, ], }, { - text: 'Tutorials', + text: "Tutorials", collapsed: false, items: [ - { text: 'Overview', link: '/en/tutorial/README' }, - { text: '01 — Basics', link: '/en/tutorial/01-basics' }, - { text: '02 — Player & Items', link: '/en/tutorial/02-player-items' }, - { text: '03 — Events & Entities', link: '/en/tutorial/03-events-entities' }, - { text: '04 — Advanced Systems', link: '/en/tutorial/04-advanced-systems' }, - { text: '05 — Examples', link: '/en/tutorial/05-examples' }, - { text: '06 — Client Scripting', link: '/en/tutorial/06-client-scripting' }, + { text: "Overview", link: "/en/tutorial/README" }, + { text: "01 — Basics", link: "/en/tutorial/01-basics" }, + { text: "02 — Player & Items", link: "/en/tutorial/02-player-items" }, + { + text: "03 — Events & Entities", + link: "/en/tutorial/03-events-entities", + }, + { + text: "04 — Advanced Systems", + link: "/en/tutorial/04-advanced-systems", + }, + { text: "05 — Examples", link: "/en/tutorial/05-examples" }, + { + text: "06 — Client Scripting", + link: "/en/tutorial/06-client-scripting", + }, ], }, { - text: 'API Reference', + text: "API Reference", collapsed: false, items: [ - { text: 'Overview', link: '/en/api/README' }, + { text: "Overview", link: "/en/api/README" }, { - text: 'Server-side API', + text: "Server-side API", collapsed: false, items: [ - { text: 'Server', link: '/en/api/server' }, - { text: 'World', link: '/en/api/world' }, - { text: 'Entity', link: '/en/api/entity' }, - { text: 'Player', link: '/en/api/player' }, - { text: 'Voxels', link: '/en/api/voxels' }, - { text: 'Registries', link: '/en/api/registries' }, + { text: "Server", link: "/en/api/server" }, + { text: "World", link: "/en/api/world" }, + { text: "Entity", link: "/en/api/entity" }, + { text: "Player", link: "/en/api/player" }, + { text: "Voxels", link: "/en/api/voxels" }, + { text: "Registries", link: "/en/api/registries" }, ], }, { - text: 'Client-side API', + text: "Client-side API", collapsed: false, items: [ - { text: 'Client', link: '/en/api/client' }, + { text: "Client", link: "/en/api/client" }, + { text: "Audio", link: "/en/api/audio" }, + { text: "Input", link: "/en/api/input" }, + { text: "UI", link: "/en/api/ui" }, + { text: "Chat", link: "/en/api/chat" }, + { text: "GUI", link: "/en/api/gui" }, ], }, { - text: 'Shared API', + text: "Shared API", collapsed: false, items: [ - { text: 'Storage', link: '/en/api/storage' }, - { text: 'Database', link: '/en/api/database' }, - { text: 'HTTP', link: '/en/api/http' }, - { text: 'Math', link: '/en/api/math' }, + { text: "Storage", link: "/en/api/storage" }, + { text: "Database", link: "/en/api/database" }, + { text: "HTTP", link: "/en/api/http" }, + { text: "Math", link: "/en/api/math" }, + { text: "RemoteChannel", link: "/en/api/remote-channel" }, ], }, { - text: 'CLI Reference', + text: "CLI Reference", collapsed: false, - items: [ - { text: '/box3script', link: '/en/api/commands' }, - ], + items: [{ text: "/box3script", link: "/en/api/commands" }], }, ], }, -] +]; export default defineConfig({ - title: 'Box3JS', - description: 'Minecraft NeoForge 1.21.1 的 JavaScript/TypeScript 脚本引擎', + title: "Box3JS", + description: "Minecraft 的 JavaScript/TypeScript 脚本引擎", lastUpdated: true, cleanUrls: true, ignoreDeadLinks: true, - - head: [ - ['link', { rel: 'icon', href: '/favicon.ico' }], - ], - + base: "/box3js-mc/", + head: [["link", { rel: "icon", href: "/favicon.ico" }]], locales: { root: { - label: '简体中文', - lang: 'zh-CN', - title: 'Box3JS', - description: '基于 Mozilla Rhino 引擎,为 Minecraft NeoForge 1.21.1 提供 JS/TS 双端脚本能力 — 神奇代码岛同款编程体验', + label: "简体中文", + lang: "zh-CN", + title: "Box3JS", + description: + "基于 Mozilla Rhino 引擎,为 Minecraft 提供 JS/TS 双端脚本能力 — 神奇代码岛同款编程体验", themeConfig: { nav: cnNav, sidebar: cnSidebar, editLink: { - pattern: 'https://github.com/box3lab/Box3JS/edit/main/Box3JS-NeoForge-1.21.1/docs/:path', + pattern: + "https://github.com/box3lab/Box3-MCMod/tree/main/Box3JS-NeoForge-1.21.1/docs/:path", }, lastUpdated: { - text: '最后更新', + text: "最后更新", }, docFooter: { - prev: '上一页', - next: '下一页', + prev: "上一页", + next: "下一页", }, footer: { - message: '基于 MIT 许可证发布', + message: "基于 MIT 许可证发布", }, }, }, en: { - label: 'English', - lang: 'en-US', - title: 'Box3JS', - description: 'JavaScript/TypeScript dual-side scripting engine for Minecraft NeoForge 1.21.1 — same programming experience as Box3', + label: "English", + lang: "en-US", + title: "Box3JS", + description: + "JavaScript/TypeScript dual-side scripting engine for Minecraft — same programming experience as Box3", themeConfig: { nav: enNav, sidebar: enSidebar, editLink: { - pattern: 'https://github.com/box3lab/Box3JS/edit/main/Box3JS-NeoForge-1.21.1/docs/en/:path', + pattern: + "https://github.com/box3lab/Box3-MCMod/tree/main/Box3JS-NeoForge-1.21.1/docs/en/:path", }, lastUpdated: { - text: 'Last updated', + text: "Last updated", }, docFooter: { - prev: 'Previous page', - next: 'Next page', + prev: "Previous page", + next: "Next page", }, footer: { - message: 'Released under the MIT License.', + message: "Released under the MIT License.", }, }, }, @@ -223,11 +241,14 @@ export default defineConfig({ logo: false, socialLinks: [ - { icon: 'github', link: 'https://github.com/box3lab/Box3JS' }, + { + icon: "github", + link: "https://github.com/box3lab/Box3-MCMod", + }, ], search: { - provider: 'local', + provider: "local", }, }, -}) +}); diff --git a/Box3JS-NeoForge-1.21.1/docs/api/README.md b/Box3JS-NeoForge-1.21.1/docs/api/README.md index ae9b6a4..adad2ef 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/README.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/README.md @@ -273,13 +273,13 @@ Box3JS API 按运行环境分为服务端、客户端和双端共享三类。服 | `storage` | 双端 | 数据持久化,见 [storage.md](storage.md) | | `db` | 双端 | SQLite 数据库,见 [database.md](database.md) | | `http` | 双端 | HTTP 请求,见 [http.md](http.md) | -| `audio` | 客户端 | 客户端音效、音乐、音量控制,见 [client.md](client.md) | -| `client` | 客户端 | 客户端生命周期,见 [client.md](client.md) | -| `input` | 客户端 | 客户端键盘输入,见 [client.md](client.md) | -| `ui` | 客户端 | 客户端屏幕 UI,见 [client.md](client.md) | -| `chat` | 客户端 | 客户端聊天收发,见 [client.md](client.md) | -| `gui` | 客户端 | 自定义容器 GUI,见 [client.md](client.md) | -| `remoteChannel` | 双端 | 服务端↔客户端事件通信,见 [server.md](server.md) / [client.md](client.md) | +| `audio` | 客户端 | 客户端音效、音乐、音量控制,见 [audio.md](audio.md) | +| `client` | 客户端 | 客户端生命周期,见 [client.md](client.md) | +| `input` | 客户端 | 客户端键盘输入,见 [input.md](input.md) | +| `ui` | 客户端 | 客户端屏幕 UI,见 [ui.md](ui.md) | +| `chat` | 客户端 | 客户端聊天收发,见 [chat.md](chat.md) | +| `gui` | 客户端 | 自定义容器 GUI,见 [gui.md](gui.md) | +| `remoteChannel` | 双端 | 服务端↔客户端事件通信,见 [remote-channel.md](remote-channel.md) | | `registries` | 服务端 | 自定义方块/物品/音效(编译模式),见 [registries.md](registries.md) | | `console` | 双端 | 控制台日志输出(`log`/`warn`/`error`/`debug`) | | `GameVector3` | 双端 | 三维向量,见 [math.md](math.md) | @@ -319,7 +319,13 @@ Box3JS API 按运行环境分为服务端、客户端和双端共享三类。服 | [storage.md](storage.md) | 数据持久化存储 | | [database.md](database.md) | SQLite 数据库 | | [http.md](http.md) | HTTP 网络请求 | -| [client.md](client.md) | 客户端 API:生命周期、键盘输入、屏幕 UI、聊天、GUI、remoteChannel、客户端本地存储 | +| [client.md](client.md) | 客户端生命周期:onTick、getFPS、getPlayer、getLookingAt、getServerInfo、雾效 | +| [audio.md](audio.md) | 客户端音效/音乐播放与音量控制 | +| [input.md](input.md) | 客户端键盘输入检测与鼠标事件 | +| [ui.md](ui.md) | 客户端屏幕 UI:标题、动作栏、自定义绘制文字 | +| [chat.md](chat.md) | 客户端聊天消息收发与命令发送 | +| [gui.md](gui.md) | 自定义容器 GUI 界面 | +| [remote-channel.md](remote-channel.md) | 客户端↔服务端双向事件通信 | | [registries.md](registries.md) | 自定义方块/物品/音效(blocks.json、items.json、sounds.json、creativeTabs.json) | | [math.md](math.md) | GameVector3、GameBounds3、GameRGBColor、GameRGBAColor、GameQuaternion | | [commands.md](commands.md) | `/box3script` 命令参考 | diff --git a/Box3JS-NeoForge-1.21.1/docs/api/audio.md b/Box3JS-NeoForge-1.21.1/docs/api/audio.md new file mode 100644 index 0000000..c0a77cc --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/audio.md @@ -0,0 +1,75 @@ +# audio — 音频 API + +客户端音频播放与音量控制。 + +## audio.playSound(path, volume, pitch) + +播放音效(SoundSource.PLAYERS 类别)。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `path` | string | (必需) | 声音 ID,如 `"minecraft:block.note_block.pling"` | +| `volume` | number | `1.0` | 音量 (0–1) | +| `pitch` | number | `1.0` | 音高 (0.5–2) | + +```js +audio.playSound("minecraft:block.note_block.pling", 1.0, 1.0); +audio.playSound("minecraft:entity.experience_orb.pickup", 0.5, 1.5); +``` + +## audio.playMusic(path, volume, pitch) + +播放音乐(SoundSource.MUSIC 类别)。参数同 `playSound`。 + +```js +audio.playMusic("minecraft:music.creative", 0.5, 1.0); +``` + +## audio.stopAll() + +停止所有正在播放的声音和音乐。 + +```js +audio.stopAll(); +``` + +## audio.getVolume(category) + +获取指定音频类别的音量。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `category` | string | 类别名称,见下方列表 | + +```js +var musicVol = audio.getVolume("music"); // 0.0–1.0 +``` + +## audio.setVolume(category, value) + +设置指定音频类别的音量。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `category` | string | 类别名称 | +| `value` | number | 音量值 (0–1) | + +```js +audio.setVolume("music", 0.5); +audio.setVolume("player", 0.8); +``` + +## 音频类别 + +| 类别 | 说明 | +|------|------| +| `master` | 主音量 | +| `music` | 音乐 | +| `record` | 唱片/音符盒 | +| `weather` | 天气(雨) | +| `block` | 方块 | +| `hostile` | 敌对生物 | +| `neutral` | 中立生物 | +| `player` | 玩家 | +| `ambient` | 环境 | +| `voice` | 语音 | diff --git a/Box3JS-NeoForge-1.21.1/docs/api/chat.md b/Box3JS-NeoForge-1.21.1/docs/api/chat.md new file mode 100644 index 0000000..937d284 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/chat.md @@ -0,0 +1,41 @@ +# chat — 聊天 API + +客户端聊天消息收发与命令发送。 + +## chat.sendMessage(text) + +向服务端发送聊天消息。 + +```js +chat.sendMessage("大家好!"); +``` + +## chat.sendCommand(cmd) + +向服务端发送命令(等同于在聊天框输入 `/` 前缀的命令)。 + +```js +chat.sendCommand("spawn"); +chat.sendCommand("home"); +``` + +## chat.onMessage(handler) + +注册接收聊天消息的处理器。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 + +回调参数:`(message: string, sender: string, isSystem: boolean) => boolean | void` + +返回 `false` 可阻止消息显示在聊天栏。 + +```js +var token = chat.onMessage((message, sender, isSystem) => { + console.log(`[chat] ${sender}: ${message}`); + + if (message.includes("filtered_word")) { + return false; // 阻止该消息显示 + } +}); + +// 取消监听 +token.cancel(); +``` diff --git a/Box3JS-NeoForge-1.21.1/docs/api/client.md b/Box3JS-NeoForge-1.21.1/docs/api/client.md index 56c528a..7287168 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/client.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/client.md @@ -1,24 +1,24 @@ # client — 客户端 API -客户端脚本运行在玩家本地 Minecraft 客户端上,入口文件是 `src/client/app.ts`,构建产物是 `dist/client.js`。客户端 API 只负责本地 UI、输入、音频、聊天辅助、本地存储、本地 HTTP/SQLite 以及接收/发送跨端事件。 - -客户端脚本通过以下全局对象访问 API: - -| 对象 | 类型 | 用途 | -|------|------|------| -| `audio` | `GameAudio` | 音效、音乐播放与音量控制 | -| `client` | `GameClient` | 生命周期回调 | -| `input` | `GameInput` | 键盘输入检测 | -| `ui` | `GameUI` | 屏幕文字显示(ActionBar、标题) | -| `chat` | `GameChat` | 收发聊天消息、发送命令 | -| `storage` | `GameStorage` | 客户端本地持久化存储 | -| `db` | `GameDatabase` | 客户端本地 SQLite 数据库 | -| `http` | `GameHttpAPI` | HTTP 请求(同步/异步) | -| `gui` | `GameGUI` | 自定义容器 GUI 界面 | -| `remoteChannel` | `RemoteChannel` | 客户端 ↔ 服务端事件通信 | +客户端脚本运行在玩家本地 Minecraft 客户端上,入口文件是 `src/client/app.ts`,构建产物是 `dist/client.js`。 + +## 客户端全局对象 + +| 对象 | 类型 | 用途 | 文档 | +|------|------|------|------| +| `client` | `GameClient` | 生命周期回调、玩家信息、雾效 | 本页 | +| `audio` | `GameAudio` | 音效、音乐播放与音量控制 | [audio.md](audio.md) | +| `input` | `GameInput` | 键盘输入检测、鼠标事件 | [input.md](input.md) | +| `ui` | `GameUI` | 屏幕文字显示(ActionBar、标题、自定义绘制) | [ui.md](ui.md) | +| `chat` | `GameChat` | 收发聊天消息、发送命令 | [chat.md](chat.md) | +| `gui` | `GameGUI` | 自定义容器 GUI 界面 | [gui.md](gui.md) | +| `remoteChannel` | `RemoteChannel` | 客户端 ↔ 服务端事件通信 | [remote-channel.md](remote-channel.md) | +| `storage` | `GameStorage` | 客户端本地持久化存储 | [storage.md](storage.md) | +| `db` | `GameDatabase` | 客户端本地 SQLite 数据库 | [database.md](database.md) | +| `http` | `GameHttpAPI` | HTTP 请求(同步/异步) | [http.md](http.md) | ::: info 前置条件 -客户端必须安装 Box3JS mod,服务端必须启用该项目的客户端脚本并通过网络自动下发。客户端脚本放在 `src/client/` 目录下,服务端脚本放在 `src/server/` 目录下。客户端类型入口是 `types/client/index.d.ts`,不会包含服务端 `world` / `voxels` API。 +客户端必须安装 Box3JS mod,服务端必须启用该项目的客户端脚本并通过网络自动下发。客户端类型入口是 `types/client/index.d.ts`,不会包含服务端 `world` / `voxels` API。 ::: 客户端脚本不能直接修改服务端世界。需要改变方块、玩家、实体或计分板时,应发送事件给服务端: @@ -27,80 +27,6 @@ remoteChannel.sendServerEvent({ type: "requestTeleport" }); ``` -## audio — 音频播放 - -### audio.playSound(path, volume, pitch) - -播放音效(SoundSource.PLAYERS 类别)。 - -| 参数 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| `path` | string | (必需) | 声音 ID,如 `"minecraft:block.note_block.pling"` | -| `volume` | number | `1.0` | 音量 (0–1) | -| `pitch` | number | `1.0` | 音高 (0.5–2) | - -```js -audio.playSound("minecraft:block.note_block.pling", 1.0, 1.0); -audio.playSound("minecraft:entity.experience_orb.pickup", 0.5, 1.5); -``` - -### audio.playMusic(path, volume, pitch) - -播放音乐(SoundSource.MUSIC 类别)。参数同 `playSound`。 - -```js -audio.playMusic("minecraft:music.creative", 0.5, 1.0); -``` - -### audio.stopAll() - -停止所有正在播放的声音和音乐。 - -```js -audio.stopAll(); -``` - -### audio.getVolume(category) - -获取指定音频类别的音量。 - -| 参数 | 类型 | 说明 | -|------|------|------| -| `category` | string | 类别名称,见下方列表 | - -```js -var musicVol = audio.getVolume("music"); // 0.0–1.0 -``` - -### audio.setVolume(category, value) - -设置指定音频类别的音量。 - -| 参数 | 类型 | 说明 | -|------|------|------| -| `category` | string | 类别名称 | -| `value` | number | 音量值 (0–1) | - -```js -audio.setVolume("music", 0.5); -audio.setVolume("player", 0.8); -``` - -### 音频类别 - -| 类别 | 说明 | -|------|------| -| `master` | 主音量 | -| `music` | 音乐 | -| `record` | 唱片/音符盒 | -| `weather` | 天气(雨) | -| `block` | 方块 | -| `hostile` | 敌对生物 | -| `neutral` | 中立生物 | -| `player` | 玩家 | -| `ambient` | 环境 | -| `voice` | 语音 | - ## client — 生命周期 ### client.onTick(callback) @@ -167,7 +93,7 @@ if (!info.isLocal) { } ``` -### 雾效控制 (Fog Control) +## 雾效控制 (Fog Control) Box3JS 客户端可以覆盖 Minecraft 的雾颜色和距离,实现类似 Box3 `world.fogColor` / `world.maxFog` 的效果。 @@ -231,311 +157,6 @@ client.setFogEndDistance(50); client.resetFog(); ``` -## input — 键盘输入 - -### input.isKeyDown(key) - -检查指定按键当前是否被按下。 - -| 参数 | 类型 | 说明 | -|------|------|------| -| `key` | string | 按键名称(小写),见下方按键列表 | - -```js -if (input.isKeyDown("space")) { - // 空格键正在被按住 -} -``` - -### input.onKeyPress(key, callback) - -注册按键按下回调(按下瞬间触发一次)。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 - -```js -var token = input.onKeyPress("f", () => { - chat.sendCommand("fly"); -}); - -// 取消监听 -token.cancel(); -``` - -### input.getMouseX() - -获取当前鼠标 X 坐标(屏幕像素)。 - -```js -var mx = input.getMouseX(); -``` - -### input.getMouseY() - -获取当前鼠标 Y 坐标(屏幕像素)。 - -```js -var my = input.getMouseY(); -``` - -### input.onMouseClick(callback) - -注册鼠标按键回调。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 - -回调参数:`(button: number, action: number, x: number, y: number) => void` - -| 参数 | 说明 | -|------|------| -| `button` | 0=左键, 1=右键, 2=中键 | -| `action` | 0=释放, 1=按下, 2=重复 | -| `x` | 鼠标 X 坐标(屏幕像素) | -| `y` | 鼠标 Y 坐标(屏幕像素) | - -```js -var token = input.onMouseClick((button, action, x, y) => { - if (action === 1) { // 按下 - console.log(`Clicked button ${button} at (${x}, ${y})`); - } -}); - -// 取消监听 -token.cancel(); -``` - -### 支持的按键名称 - -| 类别 | 按键 | -|------|------| -| 字母 | `a`–`z` | -| 数字 | `0`–`9` | -| 功能键 | `f1`–`f12` | -| 方向键 | `up`, `down`, `left`, `right` | -| 特殊键 | `space`, `enter`, `escape`, `tab`, `backspace`, `delete` | -| 修饰键 | `shift`, `left_shift`, `right_shift`, `ctrl`, `left_ctrl`, `right_ctrl`, `alt`, `left_alt`, `right_alt` | - -## ui — 屏幕 UI - -### ui.showOverlay(text) - -在动作栏(快捷栏上方)显示文字。支持颜色代码(`§a`、`§b` 等)。 - -```js -ui.showOverlay("§a欢迎来到服务器!"); -``` - -### ui.showTitle(title, subtitle, fadeIn?, stay?, fadeOut?) - -显示屏幕中央大标题。 - -| 参数 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| `title` | string | (必需) | 主标题 | -| `subtitle` | string | (必需) | 副标题 | -| `fadeIn` | number | `10` | 淡入 tick 数 | -| `stay` | number | `70` | 停留 tick 数 | -| `fadeOut` | number | `20` | 淡出 tick 数 | - -```js -ui.showTitle("Boss 来袭!", "准备战斗", 10, 70, 20); -ui.showTitle("§c游戏结束", "§7再接再厉"); -``` - -### ui.showActionBar(text) - -在动作栏显示文字(与 `showOverlay` 相同)。 - -```js -ui.showActionBar("§e按 F 键使用技能"); -``` - -### ui.getScreenSize() - -获取当前游戏窗口和 GUI 缩放尺寸。 - -```js -var size = ui.getScreenSize(); -console.log(size.width, size.height); // 窗口像素 -console.log(size.scaledWidth, size.scaledHeight); // GUI 缩放坐标 -``` - -### ui.drawText(id, x, y, text, color?) - -在屏幕上绘制自定义文字(每帧持续绘制,直到调用 `removeDrawText` 移除)。 - -| 参数 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| `id` | number | (必需) | 文字 ID,用于后续移除或更新 | -| `x` | number | (必需) | X 坐标(GUI 缩放坐标系) | -| `y` | number | (必需) | Y 坐标(GUI 缩放坐标系) | -| `text` | string | (必需) | 要显示的文字 | -| `color` | GameRGBColor | `白色` | 文字颜色 | - -返回文字 ID(与传入的 `id` 相同)。重复调用相同 ID 会覆盖之前的内容。 - -```js -var textId = ui.drawText(1, 10, 10, "Hello, Box3JS!"); -// 更新位置或内容 -ui.drawText(1, 10, 30, "Updated text", new GameRGBColor(1, 0, 0)); // 红色 -``` - -### ui.removeDrawText(id) - -移除指定 ID 的绘制文字。 - -```js -ui.removeDrawText(1); -``` - -### ui.clearDrawTexts() - -清除所有通过 `drawText()` 绘制的文字。 - -```js -ui.clearDrawTexts(); -``` - -## chat — 聊天消息与命令 - -### chat.sendMessage(text) - -向服务端发送聊天消息。 - -```js -chat.sendMessage("大家好!"); -``` - -### chat.sendCommand(cmd) - -向服务端发送命令(等同于在聊天框输入 `/` 前缀的命令)。 - -```js -chat.sendCommand("spawn"); -chat.sendCommand("home"); -``` - -### chat.onMessage(handler) - -注册接收聊天消息的处理器。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 - -回调参数:`(message: string, sender: string, isSystem: boolean) => boolean | void` - -返回 `false` 可阻止消息显示在聊天栏。 - -```js -var token = chat.onMessage((message, sender, isSystem) => { - console.log(`[chat] ${sender}: ${message}`); - - if (message.includes("filtered_word")) { - return false; // 阻止该消息显示 - } -}); - -// 取消监听 -token.cancel(); -``` - -## gui — 自定义 GUI - -### gui.openGUI(config) - -打开一个脚本控制的自定义容器 GUI(类似箱子界面),返回控制器对象。 -客户端会自动向服务端请求创建容器,并返回 `GuiController` 用于操作界面和监听事件。 - -| 参数 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| `config.title` | string | `"Container"` | 标题 | -| `config.rows` | number | `3` | 行数 (1–6) | -| `config.slots` | object | `{}` | 初始物品,格式 `{ [槽位]: "物品ID" }` | - -```js -var ctrl = gui.openGUI({ - title: "§6商店", - rows: 3, - slots: { 0: "minecraft:diamond", 4: "minecraft:emerald" }, -}); - -// 设置物品 -ctrl.setItem(1, "minecraft:gold_ingot", 5); - -// 获取物品 -var item = ctrl.getItem(0); -console.log(item.id, item.count); // minecraft:diamond, 1 - -// 监听槽位点击 -var clickToken = ctrl.onSlotClick((slot) => { - console.log("Clicked slot:", slot); -}); - -// 监听关闭 -var closeToken = ctrl.onClose(() => { - console.log("GUI closed"); -}); - -// 关闭 GUI -ctrl.close(); -``` - -### GuiController 方法 - -| 方法 | 说明 | -|------|------| -| `setItem(slot, itemId, count?)` | 设置指定槽位的物品 | -| `getItem(slot)` | 获取指定槽位的物品,返回 `{ id, count }` | -| `onSlotClick(callback)` | 注册槽位点击回调,返回 `GameEventHandlerToken`,`callback(slot: number)` | -| `onClose(callback)` | 注册关闭回调,返回 `GameEventHandlerToken`,`callback()` | -| `close()` | 关闭 GUI | - -## remoteChannel — 客户端 ↔ 服务端通信 - -客户端通过 `remoteChannel` 与服务端进行双向事件通信。事件数据通过 JSON 序列化传输。 - -### remoteChannel.sendServerEvent(event) - -向服务端发送事件。`event` 为任意 JSON 可序列化的值。 - -```js -remoteChannel.sendServerEvent({ - type: "clientReady", - timestamp: Date.now(), -}); -``` - -### remoteChannel.onClientEvent(handler) - -注册来自服务端的远程事件处理器。返回 `GameEventHandlerToken`。 - -回调参数:`(event: { tick: number, args: T }) => void` - -```js -remoteChannel.onClientEvent((event) => { - const { tick, args } = event; - - switch (args.type) { - case "ping": - console.log(`[client] Ping: ${args.message}`); - remoteChannel.sendServerEvent({ type: "pong" }); - break; - case "notify": - ui.showOverlay(`§b${args.message}`); - break; - } -}); -``` - -::: info -服务端对应 API 为 `remoteChannel.sendClientEvent()` / `broadcastClientEvent()` / `onServerEvent()`。详见 `server.d.ts` 中的类型声明。 -::: - -## storage — 客户端存储 - -客户端也有独立的 `storage`,数据保存在客户端本地 `.minecraft/config/box3/data/<项目名>/` 目录下。API 与服务端 `storage` 完全一致: - -```js -var store = storage.getDataStorage("settings"); -store.set("volume", 0.8); -var volume = store.get("volume"); // 0.8 -``` - -详细 API 参考 [storage.md](storage.md)。 - ## 客户端完整示例 ```js diff --git a/Box3JS-NeoForge-1.21.1/docs/api/entity.md b/Box3JS-NeoForge-1.21.1/docs/api/entity.md index 1ce6169..9e43314 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/entity.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/entity.md @@ -45,20 +45,21 @@ entity.position.set(0, 100, 0); 只读 `GameVector3`。**LiveVec3**:读取时自动同步当前速度,`.set(x,y,z)` 直接设置速度向量。 ```js -entity.velocity.set(0, 1, 0); // 向上弹射 -entity.velocity.set(2, 0, 2); // 水平方向速度 +entity.velocity.set(0, 1, 0); // 向上弹射 +entity.velocity.set(2, 0, 2); // 水平方向速度 ``` ### entity.bounds 只读 `GameVector3`。实体的包围盒**半尺寸** (half-extents): + - `x` = 宽度 / 2 - `y` = 高度 / 2 - `z` = 宽度 / 2 ### entity.onGround -⬆ MC 扩展 | 只读。实体是否站在方块上。 +只读。实体是否站在方块上。 ```js if (entity.onGround) { @@ -68,7 +69,7 @@ if (entity.onGround) { ### entity.eyePosition -⬆ MC 扩展 | 只读 `GameVector3`。实体视线高度位置(射线检测起点)。 +只读 `GameVector3`。实体视线高度位置(射线检测起点)。 ```js var eye = entity.eyePosition; @@ -99,13 +100,13 @@ zombie.hp = 100; 治疗实体 `amount` 点生命值(不超过 maxHp)。 ```js -zombie.hurt(10); // 造成 10 点伤害 -zombie.heal(5); // 治疗 5 点 +zombie.hurt(10); // 造成 10 点伤害 +zombie.heal(5); // 治疗 5 点 ``` ### entity.invulnerable -⬆ MC 扩展 | 获取/设置实体是否无敌(不受伤害)。 +获取/设置实体是否无敌(不受伤害)。 ```js entity.invulnerable = true; @@ -125,7 +126,7 @@ console.log(entity.invulnerable); 获取/设置实体是否参与碰撞。默认 `true`。设为 `false` 时对 LivingEntity 禁用物理 (setNoPhysics)。 ```js -entity.collides = false; // 无碰撞幽灵 +entity.collides = false; // 无碰撞幽灵 ``` ### entity.fixed @@ -133,7 +134,7 @@ entity.collides = false; // 无碰撞幽灵 获取/设置实体是否固定。默认 `false`。设为 `true` 时禁用重力并每 tick 清零移动速度。 ```js -entity.fixed = true; // 固定装饰物,不受重力不掉落 +entity.fixed = true; // 固定装饰物,不受重力不掉落 ``` ### entity.gravity @@ -141,7 +142,7 @@ entity.fixed = true; // 固定装饰物,不受重力不掉落 获取/设置实体是否受重力影响。默认 `true`。设为 `false` 时禁用重力 (setNoGravity)。 ```js -entity.gravity = false; // 无重力漂浮 +entity.gravity = false; // 无重力漂浮 ``` ### entity.friction @@ -164,7 +165,7 @@ var ball = world.createEntity({ gravity: true, collides: true, restitution: 0.8, - mass: 0.5 + mass: 0.5, }); ``` @@ -175,13 +176,13 @@ var ball = world.createEntity({ 控制实体是否不可见(隐身)。 ```js -entity.meshInvisible = true; // 隐身 +entity.meshInvisible = true; // 隐身 console.log(entity.meshInvisible); ``` ### entity.glowing -⬆ MC 扩展 | 获取/设置发光效果(类似光灵箭轮廓高亮)。 +获取/设置发光效果(类似光灵箭轮廓高亮)。 ```js entity.glowing = true; @@ -190,42 +191,42 @@ console.log(entity.glowing); ### entity.setGlowColor(color) -⬆ MC 扩展 | 设置发光轮廓颜色。通过队伍颜色实现,映射 RGB 到最接近的 `ChatFormatting`(16 色)。 +设置发光轮廓颜色。通过队伍颜色实现,映射 RGB 到最接近的 `ChatFormatting`(16 色)。 ```js entity.glowing = true; -entity.setGlowColor(new GameRGBColor(1, 0, 0)); // 红色发光 -entity.setGlowColor(new GameRGBColor(0, 0, 1)); // 蓝色发光 +entity.setGlowColor(new GameRGBColor(1, 0, 0)); // 红色发光 +entity.setGlowColor(new GameRGBColor(0, 0, 1)); // 蓝色发光 ``` ### entity.setText(text) -⬆ MC 扩展 | 设置文字展示实体的文本内容(仅 `minecraft:text_display` 实体有效)。 +设置文字展示实体的文本内容(仅 `minecraft:text_display` 实体有效)。 ### entity.setTextColor(color) -⬆ MC 扩展 | 设置文字展示实体的文本颜色。 +设置文字展示实体的文本颜色。 ### entity.setTextBackgroundColor(color) -⬆ MC 扩展 | 设置文字展示实体的背景颜色,`GameRGBAColor` 可用于半透明背景。 +设置文字展示实体的背景颜色,`GameRGBAColor` 可用于半透明背景。 ```js // 创建文字展示实体 var textEntity = world.createEntity("minecraft:text_display", pos); textEntity.setText("Hello, World!"); -textEntity.setTextColor(new GameRGBColor(1, 1, 1)); // 白色文字 +textEntity.setTextColor(new GameRGBColor(1, 1, 1)); // 白色文字 textEntity.setTextBackgroundColor(new GameRGBAColor(0, 0, 0, 0.5)); // 半透明黑色背景 ``` ### entity.nameTag -⬆ MC 扩展 | 获取/设置实体的自定义名称(头上显示的名字,支持颜色代码)。空字符串 = 无名称。 +获取/设置实体的自定义名称(头上显示的名字,支持颜色代码)。空字符串 = 无名称。 ```js entity.nameTag = "§cBoss 怪物"; -console.log(entity.nameTag); // 属性方式读取 -entity.setNameTag("§e守卫"); // 方法方式设置 +console.log(entity.nameTag); // 属性方式读取 +entity.setNameTag("§e守卫"); // 方法方式设置 ``` ## 标签系统 @@ -270,38 +271,38 @@ var bosses = world.querySelectorAll(".boss"); ### entity.setFire(ticks) -⬆ MC 扩展 | 点燃实体指定 tick 数。20 ticks = 1 秒。 +点燃实体指定 tick 数。20 ticks = 1 秒。 ### entity.clearFire() -⬆ MC 扩展 | 扑灭实体火焰。 +扑灭实体火焰。 ```js -entity.setFire(100); // 点燃 5 秒 -entity.clearFire(); // 立即扑灭 +entity.setFire(100); // 点燃 5 秒 +entity.clearFire(); // 立即扑灭 ``` ## AI 与导航 ### entity.setAI(enabled) -⬆ MC 扩展 | 启用/禁用实体 AI(仅 Mob 有效)。禁用后实体不会移动或攻击。 +启用/禁用实体 AI(仅 Mob 有效)。禁用后实体不会移动或攻击。 ```js -entity.setAI(false); // 冻结实体 +entity.setAI(false); // 冻结实体 ``` ### entity.setTarget(target) -⬆ MC 扩展 | 设置怪物的攻击目标(仅 Mob 有效)。怪物会自动寻路并攻击该目标。 +设置怪物的攻击目标(仅 Mob 有效)。怪物会自动寻路并攻击该目标。 ### entity.getTarget() -⬆ MC 扩展 | 获取当前攻击目标,返回 `GameEntity` 或 `null`。 +获取当前攻击目标,返回 `GameEntity` 或 `null`。 ### entity.clearTarget() -⬆ MC 扩展 | 清除攻击目标,停止追击。 +清除攻击目标,停止追击。 ```js var boss = world.spawnEntity("minecraft:skeleton", new GameVector3(0, 100, 0)); @@ -313,7 +314,7 @@ boss.clearTarget(); ### entity.navigateTo(x, y, z, speed) -⬆ MC 扩展 | 让实体寻路到目标坐标(仅 PathfinderMob 有效)。返回 `true` 表示路径计算成功。 +让实体寻路到目标坐标(仅 PathfinderMob 有效)。返回 `true` 表示路径计算成功。 ### entity.navigateTo(pos, speed) @@ -326,7 +327,7 @@ entity.navigateTo(target.position, 1.0); ### entity.lookAt(x, y, z) -⬆ MC 扩展 | 实体面朝目标坐标。 +实体面朝目标坐标。 ### entity.lookAt(pos) @@ -350,9 +351,9 @@ entity.lookAt(target.position); 添加效果并可选择隐藏粒子。 ```js -entity.addEffect("minecraft:speed", 600, 2); // 速度 III,30 秒 -entity.addEffect("minecraft:strength", 99999, 1, true); // 永久力量 II,无粒子 -entity.addEffect("minecraft:glowing", 200, 0); // 发光 10 秒 +entity.addEffect("minecraft:speed", 600, 2); // 速度 III,30 秒 +entity.addEffect("minecraft:strength", 99999, 1, true); // 永久力量 II,无粒子 +entity.addEffect("minecraft:glowing", 200, 0); // 发光 10 秒 // 常用效果: // minecraft:speed, minecraft:slowness, minecraft:strength @@ -369,14 +370,14 @@ entity.addEffect("minecraft:glowing", 200, 0); // 发光 10 秒 给生物穿戴装备。**slot 值:** -| slot | 说明 | -|------|------| -| `"mainhand"` | 主手 | -| `"offhand"` | 副手 | +| slot | 说明 | +| ------------------------------ | ---- | +| `"mainhand"` | 主手 | +| `"offhand"` | 副手 | | `"head"`, `"helmet"`, `"helm"` | 头盔 | -| `"chest"`, `"chestplate"` | 胸甲 | -| `"legs"`, `"leggings"` | 护腿 | -| `"feet"`, `"boots"` | 靴子 | +| `"chest"`, `"chestplate"` | 胸甲 | +| `"legs"`, `"leggings"` | 护腿 | +| `"feet"`, `"boots"` | 靴子 | ```js entity.setEquipment("mainhand", "minecraft:diamond_sword"); @@ -390,8 +391,8 @@ entity.setEquipment("feet", "minecraft:leather_boots"); 设置装备槽物品的掉落概率,范围 0.0–1.0。`slot` 设为 `"all"` 可一次性设置所有槽位(包括主副手和四个护甲槽)。 ```js -entity.setDropChance("mainhand", 0.5); // 50% 概率掉落主手物品 -entity.setDropChance("all", 0); // 不掉落任何装备 +entity.setDropChance("mainhand", 0.5); // 50% 概率掉落主手物品 +entity.setDropChance("all", 0); // 不掉落任何装备 ``` ## 属性 @@ -430,23 +431,23 @@ entity.setAttribute("minecraft:generic.armor", 10); 设置销毁回调。`handler` 接收一个参数 `(entity)`。 ```js -entity.setOnDestroy(function(e) { +entity.setOnDestroy(function (e) { console.log("实体 " + e.id + " 被销毁"); }); ``` ### entity.setPersistent(v) -⬆ MC 扩展 | 设为 `true` 时生物不会因远离玩家而自然消失(仅 Mob 有效)。仅写方法,无 getter。 +设为 `true` 时生物不会因远离玩家而自然消失(仅 Mob 有效)。仅写方法,无 getter。 ```js var boss = world.spawnEntity( "minecraft:wither_skeleton", new GameVector3(0, 100, 0), ); -boss.setPersistent(true); // 不会自然消失 +boss.setPersistent(true); // 不会自然消失 boss.setNameTag("§c§l凋零守卫"); -boss.setOnDestroy(function(e) { +boss.setOnDestroy(function (e) { world.say("Boss 被击败了!"); }); ``` diff --git a/Box3JS-NeoForge-1.21.1/docs/api/gui.md b/Box3JS-NeoForge-1.21.1/docs/api/gui.md new file mode 100644 index 0000000..97f6498 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/gui.md @@ -0,0 +1,52 @@ +# gui — 自定义 GUI + +客户端自定义容器界面,类似箱子界面,由脚本完全控制。 + +## gui.openGUI(config) + +打开一个脚本控制的自定义容器 GUI,返回 `GuiController` 对象。 +客户端会自动向服务端请求创建容器。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `config.title` | string | `"Container"` | 标题 | +| `config.rows` | number | `3` | 行数 (1–6) | +| `config.slots` | object | `{}` | 初始物品,格式 `{ [槽位]: "物品ID" }` | + +```js +var ctrl = gui.openGUI({ + title: "§6商店", + rows: 3, + slots: { 0: "minecraft:diamond", 4: "minecraft:emerald" }, +}); + +// 设置物品 +ctrl.setItem(1, "minecraft:gold_ingot", 5); + +// 获取物品 +var item = ctrl.getItem(0); +console.log(item.id, item.count); // minecraft:diamond, 1 + +// 监听槽位点击 +var clickToken = ctrl.onSlotClick((slot) => { + console.log("Clicked slot:", slot); +}); + +// 监听关闭 +var closeToken = ctrl.onClose(() => { + console.log("GUI closed"); +}); + +// 关闭 GUI +ctrl.close(); +``` + +## GuiController 方法 + +| 方法 | 说明 | +|------|------| +| `setItem(slot, itemId, count?)` | 设置指定槽位的物品 | +| `getItem(slot)` | 获取指定槽位的物品,返回 `{ id, count }` | +| `onSlotClick(callback)` | 注册槽位点击回调,返回 `GameEventHandlerToken`,`callback(slot: number)` | +| `onClose(callback)` | 注册关闭回调,返回 `GameEventHandlerToken`,`callback()` | +| `close()` | 关闭 GUI | diff --git a/Box3JS-NeoForge-1.21.1/docs/api/input.md b/Box3JS-NeoForge-1.21.1/docs/api/input.md new file mode 100644 index 0000000..fc31504 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/input.md @@ -0,0 +1,81 @@ +# input — 输入 API + +客户端键盘与鼠标输入检测。 + +## input.isKeyDown(key) + +检查指定按键当前是否被按下。 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `key` | string | 按键名称(小写),见下方按键列表 | + +```js +if (input.isKeyDown("space")) { + // 空格键正在被按住 +} +``` + +## input.onKeyPress(key, callback) + +注册按键按下回调(按下瞬间触发一次)。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 + +```js +var token = input.onKeyPress("f", () => { + chat.sendCommand("fly"); +}); + +// 取消监听 +token.cancel(); +``` + +## input.getMouseX() + +获取当前鼠标 X 坐标(屏幕像素)。 + +```js +var mx = input.getMouseX(); +``` + +## input.getMouseY() + +获取当前鼠标 Y 坐标(屏幕像素)。 + +```js +var my = input.getMouseY(); +``` + +## input.onMouseClick(callback) + +注册鼠标按键回调。返回 `GameEventHandlerToken`,调用 `.cancel()` 取消。 + +回调参数:`(button: number, action: number, x: number, y: number) => void` + +| 参数 | 说明 | +|------|------| +| `button` | 0=左键, 1=右键, 2=中键 | +| `action` | 0=释放, 1=按下, 2=重复 | +| `x` | 鼠标 X 坐标(屏幕像素) | +| `y` | 鼠标 Y 坐标(屏幕像素) | + +```js +var token = input.onMouseClick((button, action, x, y) => { + if (action === 1) { // 按下 + console.log(`Clicked button ${button} at (${x}, ${y})`); + } +}); + +// 取消监听 +token.cancel(); +``` + +## 支持的按键名称 + +| 类别 | 按键 | +|------|------| +| 字母 | `a`–`z` | +| 数字 | `0`–`9` | +| 功能键 | `f1`–`f12` | +| 方向键 | `up`, `down`, `left`, `right` | +| 特殊键 | `space`, `enter`, `escape`, `tab`, `backspace`, `delete` | +| 修饰键 | `shift`, `left_shift`, `right_shift`, `ctrl`, `left_ctrl`, `right_ctrl`, `alt`, `left_alt`, `right_alt` | diff --git a/Box3JS-NeoForge-1.21.1/docs/api/player.md b/Box3JS-NeoForge-1.21.1/docs/api/player.md index d9bc281..fdf11f6 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/player.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/player.md @@ -3,8 +3,8 @@ `player` 通过 `entity.player` 获取,拥有 `entity` 的全部属性并额外提供背包、经验、飞行、消息、传送等玩家专属功能。 ```js -world.onPlayerJoin(function(entity, tick) { - var p = entity.player; // p 即为 player 对象 +world.onPlayerJoin(function (entity, tick) { + var p = entity.player; // p 即为 player 对象 p.directMessage("欢迎回来, " + p.name + "!"); }); ``` @@ -23,19 +23,19 @@ world.onPlayerJoin(function(entity, tick) { 获取/设置玩家管理员权限等级 (0–4)。 -| 等级 | 说明 | -|------|------| -| 0 | 普通玩家 | -| 1 | 可绕过出生点保护 | -| 2 | 可使用大部分命令 | -| 3 | 可管理玩家 | -| 4 | 最高权限 (等同于 `/op`) | +| 等级 | 说明 | +| ---- | ----------------------- | +| 0 | 普通玩家 | +| 1 | 可绕过出生点保护 | +| 2 | 可使用大部分命令 | +| 3 | 可管理玩家 | +| 4 | 最高权限 (等同于 `/op`) | ```js if (player.opLevel >= 2) { // 需要权限等级 2 的操作 } -player.opLevel = 3; // 属性方式设置为 3 级 +player.opLevel = 3; // 属性方式设置为 3 级 ``` 另有 `player.getOpLevel()` 方法返回权限等级数字。 @@ -51,7 +51,7 @@ player.opLevel = 3; // 属性方式设置为 3 级 只读。玩家模型缩放比例(MC 原生 scale,非 Box3 scale)。 ```js -player.invisible = true; // 隐形 +player.invisible = true; // 隐形 console.log("玩家缩放: " + player.scale); ``` @@ -73,8 +73,6 @@ console.log("玩家缩放: " + player.scale); 只读。玩家当前是否站在方块上。 - - ### player.walkSpeed 步行速度,对应 `MOVEMENT_SPEED` 属性基值。默认值约 0.1。 @@ -92,8 +90,8 @@ console.log("玩家缩放: " + player.scale); 获取/设置是否允许跳跃。默认 `true`。设为 `false` 时保存当前跳跃力并将 `JUMP_STRENGTH` 设为 0;设回 `true` 时恢复。 ```js -player.enableJump = false; // 禁止跳跃 -player.enableJump = true; // 恢复跳跃 +player.enableJump = false; // 禁止跳跃 +player.enableJump = true; // 恢复跳跃 ``` ### player.crouchSpeed @@ -105,38 +103,38 @@ player.enableJump = true; // 恢复跳跃 获取/设置游泳速度。底层映射到 `WATER_MOVEMENT_EFFICIENCY` 属性。 ```js -player.swimSpeed = 0.5; // 游泳更快 +player.swimSpeed = 0.5; // 游泳更快 ``` ### player.moveState 只读。当前移动状态字符串: -| 值 | 说明 | -|------|------| +| 值 | 说明 | +| ---------- | -------- | | `"FLYING"` | 正在飞行 | -| `"SWIM"` | 在水中 | -| `"JUMP"` | 向上跳跃 | -| `"FALL"` | 下落中 | +| `"SWIM"` | 在水中 | +| `"JUMP"` | 向上跳跃 | +| `"FALL"` | 下落中 | | `"GROUND"` | 在地面上 | ### player.walkState 只读。当前行走状态字符串: -| 值 | 说明 | -|------|------| +| 值 | 说明 | +| ---------- | ------ | | `"CROUCH"` | 潜行中 | -| `"RUN"` | 奔跑中 | -| `"WALK"` | 行走中 | -| `"NONE"` | 静止 | +| `"RUN"` | 奔跑中 | +| `"WALK"` | 行走中 | +| `"NONE"` | 静止 | ```js -player.walkSpeed = 0.2; // 加速 -player.jumpPower = 0.6; // 跳更高 -player.swimSpeed = 0.3; // 游泳速度 +player.walkSpeed = 0.2; // 加速 +player.jumpPower = 0.6; // 跳更高 +player.swimSpeed = 0.3; // 游泳速度 -world.onTick(function() { +world.onTick(function () { if (player.walkState === "RUN") { // 玩家在奔跑 } @@ -179,16 +177,16 @@ player.disableFly = true; ### player.collision -⬆ MC 扩展 | 获取/设置团队内碰撞。设为 `false` 可防止多人推搡。底层修改玩家所在队伍的 `CollisionRule`(ALWAYS / NEVER)。 +获取/设置团队内碰撞。设为 `false` 可防止多人推搡。底层修改玩家所在队伍的 `CollisionRule`(ALWAYS / NEVER)。 ```js -player.collision = false; // 禁用碰撞 +player.collision = false; // 禁用碰撞 console.log(player.collision); ``` ## 生命值 -⬆ MC 扩展 | 获取/设置玩家血量。`ServerPlayer` 本身是 `LivingEntity`,直接操作健康值。 +获取/设置玩家血量。`ServerPlayer` 本身是 `LivingEntity`,直接操作健康值。 ### player.hp @@ -204,8 +202,8 @@ console.log(player.collision); ```js // 设置职业血量 -player.maxHp = 40; // 战士 40 HP -player.hp = 40; // 满血 +player.maxHp = 40; // 战士 40 HP +player.hp = 40; // 满血 // 设置后若当前血量超过新最大值会自动截断 player.maxHp = 20; @@ -223,17 +221,15 @@ if (player.dead) { 获取/设置游戏模式。get 返回名称字符串,set 接受字符串或数字。 ```js -player.gameMode = "creative"; // 创造模式 -player.gameMode = "survival"; // 生存模式 -player.gameMode = "adventure"; // 冒险模式 -player.gameMode = "spectator"; // 旁观模式 +player.gameMode = "creative"; // 创造模式 +player.gameMode = "survival"; // 生存模式 +player.gameMode = "adventure"; // 冒险模式 +player.gameMode = "spectator"; // 旁观模式 // 或数字: 0=生存, 1=创造, 2=冒险, 3=旁观 ``` ## 相机 - - ### player.cameraMode 获取/设置相机模式:`"FPS"`(第一人称)或 `"FOLLOW"`(跟随实体)。设为 `"FPS"` 时自动清除跟随目标。 @@ -256,7 +252,7 @@ player.gameMode = "spectator"; // 旁观模式 ### player.lookAt(x, y, z) -⬆ MC 扩展 | 让玩家看向指定坐标。 +让玩家看向指定坐标。 ### player.lookAt(pos) @@ -301,7 +297,7 @@ console.log(player.spawnPoint); ### player.dimension -⬆ MC 扩展 | 获取/设置玩家所在维度。set 可跨维度传送。 +获取/设置玩家所在维度。set 可跨维度传送。 ```js player.teleport(new GameVector3(0, 100, 0)); @@ -334,11 +330,11 @@ player.kick("你已被移出游戏"); ### player.directMessage(msg, color) -⬆ MC 扩展 | 发送带颜色的聊天消息。 +发送带颜色的聊天消息。 ```js -player.directMessage("操作成功!", new GameRGBColor(0, 1, 0)); // 绿色 -player.directMessage("警告!", new GameRGBColor(1, 0.5, 0)); // 橙色 +player.directMessage("操作成功!", new GameRGBColor(0, 1, 0)); // 绿色 +player.directMessage("警告!", new GameRGBColor(1, 0.5, 0)); // 橙色 ``` ### player.actionBar(msg) @@ -351,7 +347,7 @@ player.directMessage("警告!", new GameRGBColor(1, 0.5, 0)); // 橙色 ### player.title(title, subtitle, fadeIn, stay, fadeOut) -⬆ MC 扩展 | 完全参数的标题。`fadeIn`/`stay`/`fadeOut` 单位均为 tick (20 tick = 1秒)。 +完全参数的标题。`fadeIn`/`stay`/`fadeOut` 单位均为 tick (20 tick = 1秒)。 ### player.dialog(config) @@ -381,7 +377,7 @@ player.link("https://example.com"); // 对话树 player.directMessage("输入你的选择: A 或 B"); -player.onChat(function(entity, msg, tick) { +player.onChat(function (entity, msg, tick) { if (msg === "A") { player.directMessage("你选择了 A"); } @@ -392,23 +388,23 @@ player.onChat(function(entity, msg, tick) { ### player.xp -⬆ MC 扩展 | 获取/设置经验等级。 +获取/设置经验等级。 ### player.addExperienceLevels(levels) -⬆ MC 扩展 | 增加 `levels` 级经验。 +增加 `levels` 级经验。 ### player.food -⬆ MC 扩展 | 获取/设置饱食度(0–20)。 +获取/设置饱食度(0–20)。 ### player.saturation -⬆ MC 扩展 | 获取/设置饱和度(0–20,浮点数)。 +获取/设置饱和度(0–20,浮点数)。 ```js -player.xp = 10; // 设置 10 级 -player.addExperienceLevels(3); // 加 3 级 +player.xp = 10; // 设置 10 级 +player.addExperienceLevels(3); // 加 3 级 player.food = 20; player.saturation = 10; ``` @@ -465,7 +461,7 @@ player.giveNamedItem("minecraft:diamond_sword", 1, "§c§l烈焰之刃", [ ```js var held = player.getHeldItem(); -console.log(held.id, held.count); // "minecraft:diamond_sword" 1 +console.log(held.id, held.count); // "minecraft:diamond_sword" 1 ``` ### player.clearInventory() @@ -478,30 +474,30 @@ player.clearInventory(); ## 自定义容器 GUI -⬆ MC 扩展 | 为玩家打开脚本控制的容器 GUI(类似箱子界面),可自定义格子内容、点击行为和关闭回调。 +为玩家打开脚本控制的容器 GUI(类似箱子界面),可自定义格子内容、点击行为和关闭回调。 ### player.openGUI(config?) 打开一个容器 GUI 并返回 `GUIController` 控制器对象。 -| 参数 | 类型 | 默认值 | 说明 | -|------|------|--------|------| -| `title` | `string` | `"Container"` | 容器标题 | -| `rows` | `number` | `3` | 行数 (1–6),每行 9 格 | -| `slots` | `{ [slot: number]: string }` | `{}` | 预填充物品,key 为格子索引,value 为物品 ID | +| 参数 | 类型 | 默认值 | 说明 | +| ------- | ---------------------------- | ------------- | ------------------------------------------- | +| `title` | `string` | `"Container"` | 容器标题 | +| `rows` | `number` | `3` | 行数 (1–6),每行 9 格 | +| `slots` | `{ [slot: number]: string }` | `{}` | 预填充物品,key 为格子索引,value 为物品 ID | **返回值 `GUIController` 方法:** -| 方法 | 说明 | -|------|------| -| `setItem(slot, itemId, count?)` | 在指定格子放置物品 | -| `getItem(slot)` | 获取格子物品,返回 `{ id, count }` | -| `onSlotClick(callback)` | 注册点击回调,`return false` 可取消点击 | -| `onClose(callback)` | 注册关闭回调(ESC 或 `close()` 触发) | -| `close()` | 关闭容器 | +| 方法 | 说明 | +| ------------------------------- | --------------------------------------- | +| `setItem(slot, itemId, count?)` | 在指定格子放置物品 | +| `getItem(slot)` | 获取格子物品,返回 `{ id, count }` | +| `onSlotClick(callback)` | 注册点击回调,`return false` 可取消点击 | +| `onClose(callback)` | 注册关闭回调(ESC 或 `close()` 触发) | +| `close()` | 关闭容器 | ```js -world.onChat(function(entity, msg, tick) { +world.onChat(function (entity, msg, tick) { if (msg === "!shop") { var gui = entity.player.openGUI({ title: "§6§l商店", @@ -515,12 +511,12 @@ world.onChat(function(entity, msg, tick) { gui.setItem(1, "minecraft:netherite_ingot", 5); - gui.onSlotClick(function(slot, player) { + gui.onSlotClick(function (slot, player) { console.log("点击格子: " + slot); - if (slot === 0) return false; // 禁止拿走钻石 + if (slot === 0) return false; // 禁止拿走钻石 }); - gui.onClose(function(player) { + gui.onClose(function (player) { player.directMessage("商店已关闭"); }); } @@ -536,19 +532,19 @@ world.onChat(function(entity, msg, tick) { ### player.addEffect(effectId, duration, amplifier) -⬆ MC 扩展 | 添加药水效果。`duration` 为 tick,`amplifier` 从 0 开始。 +添加药水效果。`duration` 为 tick,`amplifier` 从 0 开始。 ### player.addEffect(effectId, duration, amplifier, hideParticles) -⬆ MC 扩展 | 添加效果并可选择隐藏粒子。 +添加效果并可选择隐藏粒子。 ### player.clearEffects() -⬆ MC 扩展 | 移除所有药水效果。 +移除所有药水效果。 ```js player.addEffect("minecraft:speed", 600, 2); -player.addEffect("minecraft:jump_boost", 99999, 1, true); // 永久,无粒子 +player.addEffect("minecraft:jump_boost", 99999, 1, true); // 永久,无粒子 player.clearEffects(); ``` @@ -556,11 +552,11 @@ player.clearEffects(); ### player.playSound(path, volume, pitch) -⬆ MC 扩展 | 向该玩家单独播放音效。`path` 为命名空间 ID(如 `"minecraft:block.note_block.pling"`),`volume` 0–1,`pitch` 0.5–2。 +向该玩家单独播放音效。`path` 为命名空间 ID(如 `"minecraft:block.note_block.pling"`),`volume` 0–1,`pitch` 0.5–2。 ### player.runCommand(cmd) -⬆ MC 扩展 | 以该玩家身份执行 Minecraft 命令。 +以该玩家身份执行 Minecraft 命令。 ```js player.playSound("minecraft:block.note_block.pling", 0.8, 1.5); @@ -571,11 +567,11 @@ player.runCommand("say hello"); ### player.grantAdvancement(advancementId) -⬆ MC 扩展 | 为该玩家授予成就/进度。 +为该玩家授予成就/进度。 ### player.revokeAdvancement(advancementId) -⬆ MC 扩展 | 撤销该玩家的成就/进度。 +撤销该玩家的成就/进度。 ```js player.grantAdvancement("minecraft:story/mine_stone"); @@ -587,7 +583,7 @@ player.revokeAdvancement("minecraft:story/mine_stone"); ### player.setPlayerListName(name) -⬆ MC 扩展 | 修改该玩家在 Tab 列表中显示的名字(支持颜色代码)。 +修改该玩家在 Tab 列表中显示的名字(支持颜色代码)。 ```js player.setPlayerListName("§e[CP3] §f" + player.name); diff --git a/Box3JS-NeoForge-1.21.1/docs/api/remote-channel.md b/Box3JS-NeoForge-1.21.1/docs/api/remote-channel.md new file mode 100644 index 0000000..56a0dfc --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/remote-channel.md @@ -0,0 +1,40 @@ +# remoteChannel — 跨端通信 + +客户端通过 `remoteChannel` 与服务端进行双向事件通信。事件数据通过 JSON 序列化传输。 + +## remoteChannel.sendServerEvent(event) + +向服务端发送事件。`event` 为任意 JSON 可序列化的值。 + +```js +remoteChannel.sendServerEvent({ + type: "clientReady", + timestamp: Date.now(), +}); +``` + +## remoteChannel.onClientEvent(handler) + +注册来自服务端的远程事件处理器。返回 `GameEventHandlerToken`。 + +回调参数:`(event: { tick: number, args: T }) => void` + +```js +remoteChannel.onClientEvent((event) => { + const { tick, args } = event; + + switch (args.type) { + case "ping": + console.log(`[client] Ping: ${args.message}`); + remoteChannel.sendServerEvent({ type: "pong" }); + break; + case "notify": + ui.showOverlay(`§b${args.message}`); + break; + } +}); +``` + +::: info +服务端对应 API 为 `remoteChannel.sendClientEvent()` / `broadcastClientEvent()` / `onServerEvent()`。详见类型声明中的 `server.d.ts`。 +::: diff --git a/Box3JS-NeoForge-1.21.1/docs/api/ui.md b/Box3JS-NeoForge-1.21.1/docs/api/ui.md new file mode 100644 index 0000000..b6b3ea1 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/api/ui.md @@ -0,0 +1,82 @@ +# ui — 界面 API + +客户端屏幕 UI 显示,包括标题、动作栏、自定义绘制文字。 + +## ui.showOverlay(text) + +在动作栏(快捷栏上方)显示文字。支持颜色代码(`§a`、`§b` 等)。 + +```js +ui.showOverlay("§a欢迎来到服务器!"); +``` + +## ui.showTitle(title, subtitle, fadeIn?, stay?, fadeOut?) + +显示屏幕中央大标题。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `title` | string | (必需) | 主标题 | +| `subtitle` | string | (必需) | 副标题 | +| `fadeIn` | number | `10` | 淡入 tick 数 | +| `stay` | number | `70` | 停留 tick 数 | +| `fadeOut` | number | `20` | 淡出 tick 数 | + +```js +ui.showTitle("Boss 来袭!", "准备战斗", 10, 70, 20); +ui.showTitle("§c游戏结束", "§7再接再厉"); +``` + +## ui.showActionBar(text) + +在动作栏显示文字(与 `showOverlay` 相同)。 + +```js +ui.showActionBar("§e按 F 键使用技能"); +``` + +## ui.getScreenSize() + +获取当前游戏窗口和 GUI 缩放尺寸。 + +```js +var size = ui.getScreenSize(); +console.log(size.width, size.height); // 窗口像素 +console.log(size.scaledWidth, size.scaledHeight); // GUI 缩放坐标 +``` + +## ui.drawText(id, x, y, text, color?) + +在屏幕上绘制自定义文字(每帧持续绘制,直到调用 `removeDrawText` 移除)。 + +| 参数 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| `id` | number | (必需) | 文字 ID,用于后续移除或更新 | +| `x` | number | (必需) | X 坐标(GUI 缩放坐标系) | +| `y` | number | (必需) | Y 坐标(GUI 缩放坐标系) | +| `text` | string | (必需) | 要显示的文字 | +| `color` | GameRGBColor | `白色` | 文字颜色 | + +返回文字 ID(与传入的 `id` 相同)。重复调用相同 ID 会覆盖之前的内容。 + +```js +var textId = ui.drawText(1, 10, 10, "Hello, Box3JS!"); +// 更新位置或内容 +ui.drawText(1, 10, 30, "Updated text", new GameRGBColor(1, 0, 0)); // 红色 +``` + +## ui.removeDrawText(id) + +移除指定 ID 的绘制文字。 + +```js +ui.removeDrawText(1); +``` + +## ui.clearDrawTexts() + +清除所有通过 `drawText()` 绘制的文字。 + +```js +ui.clearDrawTexts(); +``` diff --git a/Box3JS-NeoForge-1.21.1/docs/api/voxels.md b/Box3JS-NeoForge-1.21.1/docs/api/voxels.md index 6c4a5f2..0310e84 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/voxels.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/voxels.md @@ -70,7 +70,7 @@ voxels.setVoxel(new GameVector3(0, 100, 0), "minecraft:oak_stairs", 2); ### voxels.fillVoxel(x1, y1, z1, x2, y2, z2, voxel) -⬆ MC 扩展 | 在矩形区域内填充方块。坐标两端点会被自动排序(无需保证 x1≤x2)。 +在矩形区域内填充方块。坐标两端点会被自动排序(无需保证 x1≤x2)。 ### voxels.fillVoxel(pos1, pos2, voxel) @@ -140,7 +140,7 @@ var name = voxels.getVoxelName(new GameVector3(0, 100, 0)); ### voxels.countVoxel(x1, y1, z1, x2, y2, z2, voxel) -⬆ MC 扩展 | 统计区域内匹配方块的个数。`voxel` 可以是字符串或数字 ID。 +统计区域内匹配方块的个数。`voxel` 可以是字符串或数字 ID。 ### voxels.countVoxel(pos1, pos2, voxel) @@ -168,7 +168,7 @@ var count = voxels.countVoxel( ### voxels.setSpawner(x, y, z, entityType) -⬆ MC 扩展 | 设置坐标处刷怪笼的刷出类型。只有该坐标是 `minecraft:spawner` 时才有效。 +设置坐标处刷怪笼的刷出类型。只有该坐标是 `minecraft:spawner` 时才有效。 ### voxels.setSpawner(pos, entityType) diff --git a/Box3JS-NeoForge-1.21.1/docs/api/world.md b/Box3JS-NeoForge-1.21.1/docs/api/world.md index a668a2d..935d548 100644 --- a/Box3JS-NeoForge-1.21.1/docs/api/world.md +++ b/Box3JS-NeoForge-1.21.1/docs/api/world.md @@ -43,7 +43,7 @@ console.log(world.rainDensity); // 0.0 ~ 1.0 ### world.thunderDensity -⬆ MC 扩展 | 获取/设置雷暴强度,范围 0.0–1.0。 +获取/设置雷暴强度,范围 0.0–1.0。 ```js world.thunderDensity = 0.5; @@ -51,7 +51,7 @@ world.thunderDensity = 0.5; ### world.clearWeather() -⬆ MC 扩展 | 同时清除雨和雷暴。 +同时清除雨和雷暴。 ```js world.clearWeather(); @@ -118,11 +118,11 @@ world.setWorldSpawn(new GameVector3(0, 70, 0)); ### world.getGameRule(name) -⬆ MC 扩展 | 获取游戏规则布尔值。 +获取游戏规则布尔值。 ### world.setGameRule(name, value) -⬆ MC 扩展 | 设置游戏规则。`value` 为布尔值。 +设置游戏规则。`value` 为布尔值。 **支持的规则:** @@ -252,38 +252,38 @@ var token = world.onTick(function (info) { }); ``` -| 事件 | 类型 | 回调签名 | 触发时机 | -| ---------------------------- | ------- | ------------------------------------------------------ | ------------------------------------- | -| `world.onTick(fn)` | | `(info)` → `{tick, prevTick, elapsedTimeMS, skip}` | 每 tick | -| `world.onPlayerJoin(fn)` | | `(entity, tick)` | 玩家登录 | -| `world.onPlayerLeave(fn)` | | `(entity, tick)` | 玩家退出 | -| `world.onChat(fn)` | | `(entity, message, tick) => boolean \| void` | 玩家发送聊天消息;返回 `false` 可取消 | -| `world.onVoxelDestroy(fn)` | | `(entity, x, y, z, voxel, tick)` | 玩家破坏方块 | -| `world.onBlockPlace(fn)` | ⬆ MC | `(entity, x, y, z, voxel, voxelId, tick)` | 玩家放置方块 | -| `world.onBlockActivate(fn)` | ⬆ MC | `(entity, x, y, z, voxel, tick)` | 玩家右键方块 | -| `world.onInteract(fn)` | | `(entity, target, tick)` | 玩家右键实体 | -| `world.onVoxelContact(fn)` | | `(entity, voxelId, x, y, z, contactType, force, tick)` | 实体接触方块 | -| `world.onEntityContact(fn)` | | `(entity, other, tick)` | 两个实体接触 | -| `world.onEntitySeparate(fn)` | | `(entity, other, tick)` | 两个实体分离 | -| `world.onFluidEnter(fn)` | | `(entity, fluid, x, y, z, tick)` | 实体进入液体 | -| `world.onFluidLeave(fn)` | | `(entity, fluid, x, y, z, tick)` | 实体离开液体 | -| `world.onEntityDeath(fn)` | ⬆ MC | `(entity, killer, tick)` | 实体死亡;`killer` 可能为 null | -| `world.onEntityDamage(fn)` | ⬆ MC | `(entity, amount, source, attacker, tick)` | 实体受伤(Pre 阶段) | -| `world.onPlayerRespawn(fn)` | ⬆ MC | `(entity, tick)` | 玩家重生 | -| `world.onButtonPressed(fn)` | ⬆ MC | `(entity, button, tick)` | 玩家按下按钮 | -| `world.onMessage(fn)` | ⬆ MC | `(from, data)` | 收到 `world.sendMessage()` 消息 | +| 事件 | 类型 | 回调签名 | 触发时机 | +| ---------------------------- | ---- | ------------------------------------------------------ | ------------------------------------- | +| `world.onTick(fn)` | | `(info)` → `{tick, prevTick, elapsedTimeMS, skip}` | 每 tick | +| `world.onPlayerJoin(fn)` | | `(entity, tick)` | 玩家登录 | +| `world.onPlayerLeave(fn)` | | `(entity, tick)` | 玩家退出 | +| `world.onChat(fn)` | | `(entity, message, tick) => boolean \| void` | 玩家发送聊天消息;返回 `false` 可取消 | +| `world.onVoxelDestroy(fn)` | | `(entity, x, y, z, voxel, tick)` | 玩家破坏方块 | +| `world.onBlockPlace(fn)` | ⬆ MC | `(entity, x, y, z, voxel, voxelId, tick)` | 玩家放置方块 | +| `world.onBlockActivate(fn)` | ⬆ MC | `(entity, x, y, z, voxel, tick)` | 玩家右键方块 | +| `world.onInteract(fn)` | | `(entity, target, tick)` | 玩家右键实体 | +| `world.onVoxelContact(fn)` | | `(entity, voxelId, x, y, z, contactType, force, tick)` | 实体接触方块 | +| `world.onEntityContact(fn)` | | `(entity, other, tick)` | 两个实体接触 | +| `world.onEntitySeparate(fn)` | | `(entity, other, tick)` | 两个实体分离 | +| `world.onFluidEnter(fn)` | | `(entity, fluid, x, y, z, tick)` | 实体进入液体 | +| `world.onFluidLeave(fn)` | | `(entity, fluid, x, y, z, tick)` | 实体离开液体 | +| `world.onEntityDeath(fn)` | ⬆ MC | `(entity, killer, tick)` | 实体死亡;`killer` 可能为 null | +| `world.onEntityDamage(fn)` | ⬆ MC | `(entity, amount, source, attacker, tick)` | 实体受伤(Pre 阶段) | +| `world.onPlayerRespawn(fn)` | ⬆ MC | `(entity, tick)` | 玩家重生 | +| `world.onButtonPressed(fn)` | ⬆ MC | `(entity, button, tick)` | 玩家按下按钮 | +| `world.onMessage(fn)` | ⬆ MC | `(from, data)` | 收到 `world.sendMessage()` 消息 | ### GameButtonType `world.onButtonPressed` 回调的 `button` 参数为以下字符串常量之一: -| 常量 | 说明 | -| ---------- | ---------- | -| `"WALK"` | 行走(长按) | -| `"RUN"` | 奔跑(长按) | -| `"CROUCH"` | 潜行(长按) | -| `"JUMP"` | 跳跃 | -| `"FLY"` | 飞行(长按) | +| 常量 | 说明 | +| ----------- | ----------------- | +| `"WALK"` | 行走(长按) | +| `"RUN"` | 奔跑(长按) | +| `"CROUCH"` | 潜行(长按) | +| `"JUMP"` | 跳跃 | +| `"FLY"` | 飞行(长按) | | `"ACTION0"` | 屏幕按钮0(轻点) | | `"ACTION1"` | 屏幕按钮1(轻点) | @@ -594,14 +594,20 @@ world.launchFirework(new GameVector3(0, 100, 0), "red", "star"); ### world.launchFirework(x, y, z, colors, shape) -⬆ MC 扩展 | 使用 `GameRGBColor[]` 数组指定烟花颜色,支持任意 RGB 色彩。 +使用 `GameRGBColor[]` 数组指定烟花颜色,支持任意 RGB 色彩。 ### world.launchFirework(pos, colors, shape) ⬆ GameVector3 + `GameRGBColor[]` 重载。 ```js -world.launchFirework(0, 100, 0, [new GameRGBColor(1, 0, 0), new GameRGBColor(1, 0.5, 0)], "large_ball"); +world.launchFirework( + 0, + 100, + 0, + [new GameRGBColor(1, 0, 0), new GameRGBColor(1, 0.5, 0)], + "large_ball", +); ``` ### world.spawnParticle(type, x, y, z, count, dx, dy, dz, speed) @@ -614,7 +620,7 @@ world.launchFirework(0, 100, 0, [new GameRGBColor(1, 0, 0), new GameRGBColor(1, ### world.spawnParticle(x, y, z, color, count, dx, dy, dz, speed) -⬆ MC 扩展 | 生成彩色粒子(类型为 `dust`),使用 `GameRGBColor` 指定颜色。 +生成彩色粒子(类型为 `dust`),使用 `GameRGBColor` 指定颜色。 ### world.spawnParticle(pos, color, count, dx, dy, dz, speed) @@ -622,10 +628,28 @@ world.launchFirework(0, 100, 0, [new GameRGBColor(1, 0, 0), new GameRGBColor(1, ```js // 生成红色粒子 -world.spawnParticle(0, 100, 0, new GameRGBColor(1, 0, 0), 20, 0.5, 0.5, 0.5, 0.1); +world.spawnParticle( + 0, + 100, + 0, + new GameRGBColor(1, 0, 0), + 20, + 0.5, + 0.5, + 0.5, + 0.1, +); // 生成青色粒子 -world.spawnParticle(entity.position, new GameRGBColor(0, 1, 1), 10, 0.2, 0.2, 0.2, 0); +world.spawnParticle( + entity.position, + new GameRGBColor(0, 1, 1), + 10, + 0.2, + 0.2, + 0.2, + 0, +); ``` ### world.spawnParticleCircle(x, y, z, radius, type, count) @@ -765,7 +789,7 @@ if (result.hit) { ### world.entitiesInRadius(x, y, z, radius) -⬆ MC 扩展 | 返回球体范围内所有实体。`entitiesInArea` 的便捷封装。 +返回球体范围内所有实体。`entitiesInArea` 的便捷封装。 ### world.entitiesInRadius(pos, radius) @@ -782,7 +806,7 @@ for (var i = 0; i < nearby.length; i++) { ### world.getBiome(x, y, z) -⬆ MC 扩展 | 返回生物群系的命名空间 ID 字符串。 +返回生物群系的命名空间 ID 字符串。 ### world.getBiome(pos) @@ -798,11 +822,11 @@ var biome = world.getBiome(entity.position); ### world.sendMessage(target, data) -⬆ MC 扩展 | 发送消息给其他脚本项目。`target` 为 `"*"`(广播)或项目名。接收方用 `world.onMessage()` 监听。 +发送消息给其他脚本项目。`target` 为 `"*"`(广播)或项目名。接收方用 `world.onMessage()` 监听。 ### world.runCommand(cmd) -⬆ MC 扩展 | 以服务器控制台身份执行命令。 +以服务器控制台身份执行命令。 ```js world.runCommand("time set day"); @@ -813,7 +837,7 @@ world.runCommand("weather clear"); ### world.placeStructure(x, y, z, structureId) -⬆ MC 扩展 | 在指定位置放置数据包中的结构模板 (NBT)。 +在指定位置放置数据包中的结构模板 (NBT)。 ### world.placeStructure(pos, structureId) @@ -831,7 +855,7 @@ world.placeStructure(pos, "box3js:arena"); ### world.grantAdvancement(playerName, advancementId) -⬆ MC 扩展 | 为指定玩家授予成就/进度。 +为指定玩家授予成就/进度。 ```js world.grantAdvancement("Steve", "minecraft:story/mine_stone"); @@ -841,7 +865,7 @@ world.grantAdvancement("Steve", "minecraft:story/mine_stone"); ### world.listRecipes(filter) -⬆ MC 扩展 | 按关键字搜索配方 ID 列表。 +按关键字搜索配方 ID 列表。 ```js var recipes = world.listRecipes("diamond"); @@ -850,7 +874,7 @@ console.log(recipes); // ["minecraft:diamond_sword", "minecraft:diamond_block", ### world.removeRecipe(recipeId) -⬆ MC 扩展 | 将指定配方加入黑名单并立即生效。返回是否成功。 +将指定配方加入黑名单并立即生效。返回是否成功。 ```js world.removeRecipe("minecraft:iron_pickaxe"); @@ -858,7 +882,7 @@ world.removeRecipe("minecraft:iron_pickaxe"); ### world.clearRecipes() -⬆ MC 扩展 | 清除配方黑名单,恢复所有原始配方。 +清除配方黑名单,恢复所有原始配方。 ```js world.clearRecipes(); diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/README.md b/Box3JS-NeoForge-1.21.1/docs/en/api/README.md index cbcb548..987192e 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/README.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/README.md @@ -276,13 +276,13 @@ Server-side only. `registries` is `undefined` in client scripts. Only available | `storage` | Both | Data persistence, see [storage.md](storage.md) | | `db` | Both | SQLite database, see [database.md](database.md) | | `http` | Both | HTTP requests, see [http.md](http.md) | -| `audio` | Client | Client sound, music, volume control, see [client.md](client.md) | +| `audio` | Client | Client sound, music, volume control, see [audio.md](audio.md) | | `client` | Client | Client lifecycle, see [client.md](client.md) | -| `input` | Client | Client keyboard input, see [client.md](client.md) | -| `ui` | Client | Client screen UI, see [client.md](client.md) | -| `chat` | Client | Client chat send/receive, see [client.md](client.md) | -| `gui` | Client | Custom container GUI, see [client.md](client.md) | -| `remoteChannel` | Both | Server↔client event channel, see [server.md](server.md) / [client.md](client.md) | +| `input` | Client | Client keyboard input, see [input.md](input.md) | +| `ui` | Client | Client screen UI, see [ui.md](ui.md) | +| `chat` | Client | Client chat send/receive, see [chat.md](chat.md) | +| `gui` | Client | Custom container GUI, see [gui.md](gui.md) | +| `remoteChannel` | Both | Server↔client event channel, see [remote-channel.md](remote-channel.md) | | `registries` | Server | Custom blocks, items & sounds (compiled mode), see [registries.md](registries.md) | | `console` | Both | Console logging (`log`/`warn`/`error`/`debug`) | | `GameVector3` | Both | 3D vector, see [math.md](math.md) | @@ -322,7 +322,13 @@ Each API document should follow this structure. Use the same style when adding f | [storage.md](storage.md) | Persistent data storage | | [database.md](database.md) | SQLite database API | | [http.md](http.md) | HTTP request API | -| [client.md](client.md) | Client API: lifecycle, keyboard, screen UI, chat, GUI, remoteChannel, client-side storage | +| [client.md](client.md) | Client lifecycle: onTick, getFPS, getPlayer, getLookingAt, getServerInfo, fog control | +| [audio.md](audio.md) | Client audio playback and volume control | +| [input.md](input.md) | Client keyboard input detection and mouse events | +| [ui.md](ui.md) | Client screen UI: titles, action bar, custom drawn text | +| [chat.md](chat.md) | Client chat message sending/receiving and commands | +| [gui.md](gui.md) | Custom container GUI interface | +| [remote-channel.md](remote-channel.md) | Client↔server bidirectional event communication | | [registries.md](registries.md) | Custom blocks, items & sounds (blocks.json, items.json, sounds.json, creativeTabs.json) | | [math.md](math.md) | GameVector3, GameBounds3, GameRGBColor, GameRGBAColor, GameQuaternion | | [commands.md](commands.md) | `/box3script` command reference | diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/audio.md b/Box3JS-NeoForge-1.21.1/docs/en/api/audio.md new file mode 100644 index 0000000..04281f8 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/audio.md @@ -0,0 +1,75 @@ +# audio — Audio API + +Client-side audio playback and volume control. + +## audio.playSound(path, volume, pitch) + +Plays a sound effect (SoundSource.PLAYERS category). + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `path` | string | (required) | Sound ID, e.g. `"minecraft:block.note_block.pling"` | +| `volume` | number | `1.0` | Volume (0–1) | +| `pitch` | number | `1.0` | Pitch (0.5–2) | + +```js +audio.playSound("minecraft:block.note_block.pling", 1.0, 1.0); +audio.playSound("minecraft:entity.experience_orb.pickup", 0.5, 1.5); +``` + +## audio.playMusic(path, volume, pitch) + +Plays music (SoundSource.MUSIC category). Same parameters as `playSound`. + +```js +audio.playMusic("minecraft:music.creative", 0.5, 1.0); +``` + +## audio.stopAll() + +Stops all currently playing sounds and music. + +```js +audio.stopAll(); +``` + +## audio.getVolume(category) + +Gets the volume of a specific audio category. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `category` | string | Category name, see list below | + +```js +var musicVol = audio.getVolume("music"); // 0.0–1.0 +``` + +## audio.setVolume(category, value) + +Sets the volume of a specific audio category. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `category` | string | Category name | +| `value` | number | Volume (0–1) | + +```js +audio.setVolume("music", 0.5); +audio.setVolume("player", 0.8); +``` + +## Audio Categories + +| Category | Description | +|----------|-------------| +| `master` | Master volume | +| `music` | Music | +| `record` | Records/note blocks | +| `weather` | Weather (rain) | +| `block` | Blocks | +| `hostile` | Hostile mobs | +| `neutral` | Neutral mobs | +| `player` | Players | +| `ambient` | Ambient | +| `voice` | Voice | diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/chat.md b/Box3JS-NeoForge-1.21.1/docs/en/api/chat.md new file mode 100644 index 0000000..e9e752a --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/chat.md @@ -0,0 +1,41 @@ +# chat — Chat API + +Client-side chat message sending/receiving and command sending. + +## chat.sendMessage(text) + +Sends a chat message to the server. + +```js +chat.sendMessage("Hello everyone!"); +``` + +## chat.sendCommand(cmd) + +Sends a command to the server (equivalent to typing a `/` command in chat). + +```js +chat.sendCommand("spawn"); +chat.sendCommand("home"); +``` + +## chat.onMessage(handler) + +Registers a handler for incoming chat messages. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. + +Callback: `(message: string, sender: string, isSystem: boolean) => boolean | void` + +Return `false` to suppress the message from appearing in chat. + +```js +var token = chat.onMessage((message, sender, isSystem) => { + console.log(`[chat] ${sender}: ${message}`); + + if (message.includes("filtered_word")) { + return false; // Suppress this message + } +}); + +// Unregister +token.cancel(); +``` diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/client.md b/Box3JS-NeoForge-1.21.1/docs/en/api/client.md index 383325a..8cee98a 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/client.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/client.md @@ -1,24 +1,21 @@ ---- ---- - # client — Client-side API -Client scripts run locally on the player's Minecraft client. The entry file is `src/client/app.ts`, and the compiled output is `dist/client.js`. Client APIs handle local UI, input, audio, chat helpers, local storage, local HTTP/SQLite, and cross-side events. +Client scripts run locally on the player's Minecraft client. The entry file is `src/client/app.ts`, and the compiled output is `dist/client.js`. -Client scripts access APIs through these globals: +## Client Globals -| Object | Type | Purpose | -|--------|------|---------| -| `audio` | `GameAudio` | Sound & music playback, volume control | -| `client` | `GameClient` | Lifecycle callbacks | -| `input` | `GameInput` | Keyboard input detection | -| `ui` | `GameUI` | On-screen text (ActionBar, titles) | -| `chat` | `GameChat` | Send/receive chat, send commands | -| `storage` | `GameStorage` | Client-side persistent key-value storage | -| `db` | `GameDatabase` | Client-side SQLite database | -| `http` | `GameHttpAPI` | HTTP requests (sync/async) | -| `gui` | `GameGUI` | Custom container GUI interface | -| `remoteChannel` | `RemoteChannel` | Client ↔ Server event communication | +| Object | Type | Purpose | Docs | +|--------|------|---------|------| +| `client` | `GameClient` | Lifecycle callbacks, player info, fog | This page | +| `audio` | `GameAudio` | Sound & music playback, volume control | [audio.md](audio.md) | +| `input` | `GameInput` | Keyboard input detection, mouse events | [input.md](input.md) | +| `ui` | `GameUI` | On-screen text (ActionBar, titles, custom draw) | [ui.md](ui.md) | +| `chat` | `GameChat` | Send/receive chat, send commands | [chat.md](chat.md) | +| `gui` | `GameGUI` | Custom container GUI interface | [gui.md](gui.md) | +| `remoteChannel` | `RemoteChannel` | Client ↔ Server event communication | [remote-channel.md](remote-channel.md) | +| `storage` | `GameStorage` | Client-side persistent key-value storage | [storage.md](storage.md) | +| `db` | `GameDatabase` | Client-side SQLite database | [database.md](database.md) | +| `http` | `GameHttpAPI` | HTTP requests (sync/async) | [http.md](http.md) | ::: info The client must have the Box3JS mod installed. Client scripts go in `src/client/`, server scripts in `src/server/`. The client type entry is `types/client/index.d.ts`; it does not include server APIs such as `world` / `voxels`. @@ -30,80 +27,6 @@ Client scripts cannot directly modify the server world. To change blocks, player remoteChannel.sendServerEvent({ type: "requestTeleport" }); ``` -## audio — Sound Playback - -### audio.playSound(path, volume, pitch) - -Plays a sound effect (SoundSource.PLAYERS category). - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `path` | string | (required) | Sound ID, e.g. `"minecraft:block.note_block.pling"` | -| `volume` | number | `1.0` | Volume (0–1) | -| `pitch` | number | `1.0` | Pitch (0.5–2) | - -```js -audio.playSound("minecraft:block.note_block.pling", 1.0, 1.0); -audio.playSound("minecraft:entity.experience_orb.pickup", 0.5, 1.5); -``` - -### audio.playMusic(path, volume, pitch) - -Plays music (SoundSource.MUSIC category). Same parameters as `playSound`. - -```js -audio.playMusic("minecraft:music.creative", 0.5, 1.0); -``` - -### audio.stopAll() - -Stops all currently playing sounds and music. - -```js -audio.stopAll(); -``` - -### audio.getVolume(category) - -Gets the volume of a specific audio category. - -| Parameter | Type | Description | -|-----------|------|-------------| -| `category` | string | Category name, see list below | - -```js -var musicVol = audio.getVolume("music"); // 0.0–1.0 -``` - -### audio.setVolume(category, value) - -Sets the volume of a specific audio category. - -| Parameter | Type | Description | -|-----------|------|-------------| -| `category` | string | Category name | -| `value` | number | Volume (0–1) | - -```js -audio.setVolume("music", 0.5); -audio.setVolume("player", 0.8); -``` - -### Audio Categories - -| Category | Description | -|----------|-------------| -| `master` | Master volume | -| `music` | Music | -| `record` | Records/note blocks | -| `weather` | Weather (rain) | -| `block` | Blocks | -| `hostile` | Hostile mobs | -| `neutral` | Neutral mobs | -| `player` | Players | -| `ambient` | Ambient | -| `voice` | Voice | - ## client — Lifecycle ### client.onTick(callback) @@ -170,7 +93,7 @@ if (!info.isLocal) { } ``` -### Fog Control +## Fog Control The Box3JS client can override Minecraft's fog colour and distance, providing effects similar to Box3's `world.fogColor` / `world.maxFog`. @@ -234,311 +157,6 @@ Resets fog to Minecraft's default behaviour. client.resetFog(); ``` -## input — Keyboard Input - -### input.isKeyDown(key) - -Checks whether a key is currently held down. - -| Parameter | Type | Description | -|-----------|------|-------------| -| `key` | string | Key name (lowercase), see key list below | - -```js -if (input.isKeyDown("space")) { - // Space key is held -} -``` - -### input.onKeyPress(key, callback) - -Registers a callback fired once when the key is pressed. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. - -```js -var token = input.onKeyPress("f", () => { - chat.sendCommand("fly"); -}); - -// Unregister -token.cancel(); -``` - -### input.getMouseX() - -Gets the current mouse X position in screen pixels. - -```js -var mx = input.getMouseX(); -``` - -### input.getMouseY() - -Gets the current mouse Y position in screen pixels. - -```js -var my = input.getMouseY(); -``` - -### input.onMouseClick(callback) - -Registers a mouse button callback. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. - -Callback: `(button: number, action: number, x: number, y: number) => void` - -| Parameter | Description | -|-----------|-------------| -| `button` | 0=left, 1=right, 2=middle | -| `action` | 0=release, 1=press, 2=repeat | -| `x` | Mouse X in screen pixels | -| `y` | Mouse Y in screen pixels | - -```js -var token = input.onMouseClick((button, action, x, y) => { - if (action === 1) { // pressed - console.log(`Clicked button ${button} at (${x}, ${y})`); - } -}); - -// Unregister -token.cancel(); -``` - -### Supported Key Names - -| Category | Keys | -|----------|------| -| Letters | `a`–`z` | -| Digits | `0`–`9` | -| Function keys | `f1`–`f12` | -| Arrow keys | `up`, `down`, `left`, `right` | -| Special keys | `space`, `enter`, `escape`, `tab`, `backspace`, `delete` | -| Modifiers | `shift`, `left_shift`, `right_shift`, `ctrl`, `left_ctrl`, `right_ctrl`, `alt`, `left_alt`, `right_alt` | - -## ui — Screen UI - -### ui.showOverlay(text) - -Displays text in the action bar (above the hotbar). Supports color codes (`§a`, `§b`, etc.). - -```js -ui.showOverlay("§aWelcome to the server!"); -``` - -### ui.showTitle(title, subtitle, fadeIn?, stay?, fadeOut?) - -Displays a large centered screen title. - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `title` | string | (required) | Main title | -| `subtitle` | string | (required) | Subtitle | -| `fadeIn` | number | `10` | Fade-in ticks | -| `stay` | number | `70` | Stay ticks | -| `fadeOut` | number | `20` | Fade-out ticks | - -```js -ui.showTitle("Boss Incoming!", "Get ready", 10, 70, 20); -ui.showTitle("§cGame Over", "§7Try again"); -``` - -### ui.showActionBar(text) - -Displays text in the action bar (same as `showOverlay`). - -```js -ui.showActionBar("§ePress F to use ability"); -``` - -### ui.getScreenSize() - -Gets the current game window and GUI-scaled dimensions. - -```js -var size = ui.getScreenSize(); -console.log(size.width, size.height); // window pixels -console.log(size.scaledWidth, size.scaledHeight); // GUI-scaled -``` - -### ui.drawText(id, x, y, text, color?) - -Draws custom text on screen (persists every frame until removed via `removeDrawText`). - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `id` | number | (required) | Text ID for later removal or update | -| `x` | number | (required) | X position (GUI-scaled coordinates) | -| `y` | number | (required) | Y position (GUI-scaled coordinates) | -| `text` | string | (required) | Text to display | -| `color` | GameRGBColor | white | Text colour | - -Returns the text ID (same as the passed `id`). Reusing the same ID overwrites the previous entry. - -```js -var textId = ui.drawText(1, 10, 10, "Hello, Box3JS!"); -// Update position or content -ui.drawText(1, 10, 30, "Updated text", new GameRGBColor(1, 0, 0)); // red -``` - -### ui.removeDrawText(id) - -Removes the drawn text with the given ID. - -```js -ui.removeDrawText(1); -``` - -### ui.clearDrawTexts() - -Clears all texts drawn via `drawText()`. - -```js -ui.clearDrawTexts(); -``` - -## chat — Chat Messages & Commands - -### chat.sendMessage(text) - -Sends a chat message to the server. - -```js -chat.sendMessage("Hello everyone!"); -``` - -### chat.sendCommand(cmd) - -Sends a command to the server (equivalent to typing a `/` command in chat). - -```js -chat.sendCommand("spawn"); -chat.sendCommand("home"); -``` - -### chat.onMessage(handler) - -Registers a handler for incoming chat messages. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. - -Callback: `(message: string, sender: string, isSystem: boolean) => boolean | void` - -Return `false` to suppress the message from appearing in chat. - -```js -var token = chat.onMessage((message, sender, isSystem) => { - console.log(`[chat] ${sender}: ${message}`); - - if (message.includes("filtered_word")) { - return false; // Suppress this message - } -}); - -// Unregister -token.cancel(); -``` - -## gui — Custom GUI - -### gui.openGUI(config) - -Opens a script-controlled custom container GUI (chest-like screen), returning a controller object. -The client automatically requests the server to create the container, and returns a `GuiController` for manipulating the GUI and listening to events. - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `config.title` | string | `"Container"` | Title | -| `config.rows` | number | `3` | Number of rows (1–6) | -| `config.slots` | object | `{}` | Initial items, format `{ [slot]: "itemId" }` | - -```js -var ctrl = gui.openGUI({ - title: "§6Shop", - rows: 3, - slots: { 0: "minecraft:diamond", 4: "minecraft:emerald" }, -}); - -// Set item -ctrl.setItem(1, "minecraft:gold_ingot", 5); - -// Get item -var item = ctrl.getItem(0); -console.log(item.id, item.count); // minecraft:diamond, 1 - -// Slot click listener -var clickToken = ctrl.onSlotClick((slot) => { - console.log("Clicked slot:", slot); -}); - -// Close listener -var closeToken = ctrl.onClose(() => { - console.log("GUI closed"); -}); - -// Close the GUI -ctrl.close(); -``` - -### GuiController Methods - -| Method | Description | -|--------|-------------| -| `setItem(slot, itemId, count?)` | Sets the item in the given slot | -| `getItem(slot)` | Gets the item in the given slot, returns `{ id, count }` | -| `onSlotClick(callback)` | Registers a slot click callback and returns `GameEventHandlerToken`, `callback(slot: number)` | -| `onClose(callback)` | Registers a close callback and returns `GameEventHandlerToken`, `callback()` | -| `close()` | Closes the GUI | - -## remoteChannel — Client ↔ Server Communication - -The client uses `remoteChannel` for bidirectional event communication with the server. Event data is JSON-serialized. - -### remoteChannel.sendServerEvent(event) - -Sends an event to the server. `event` is any JSON-serializable value. - -```js -remoteChannel.sendServerEvent({ - type: "clientReady", - timestamp: Date.now(), -}); -``` - -### remoteChannel.onClientEvent(handler) - -Registers a handler for remote events sent from the server. Returns `GameEventHandlerToken`. - -Callback: `(event: { tick: number, args: T }) => void` - -```js -remoteChannel.onClientEvent((event) => { - const { tick, args } = event; - - switch (args.type) { - case "ping": - console.log(`[client] Ping: ${args.message}`); - remoteChannel.sendServerEvent({ type: "pong" }); - break; - case "notify": - ui.showOverlay(`§b${args.message}`); - break; - } -}); -``` - -::: info -Server-side equivalents: `remoteChannel.sendClientEvent()` / `broadcastClientEvent()` / `onServerEvent()`. See type declarations in `server.d.ts`. -::: - -## storage — Client-side Storage - -The client has its own `storage`, saving data locally under `.minecraft/config/box3/data//`. The API is identical to the server-side `storage`: - -```js -var store = storage.getDataStorage("settings"); -store.set("volume", 0.8); -var volume = store.get("volume"); // 0.8 -``` - -Full API reference: [storage.md](storage.md). - ## Complete Client Example ```js diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/entity.md b/Box3JS-NeoForge-1.21.1/docs/en/api/entity.md index 8eaa364..2cf07a6 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/entity.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/entity.md @@ -48,20 +48,21 @@ entity.position.set(0, 100, 0); Readonly `GameVector3`. **LiveVec3**: reading syncs to current velocity; `.set(x,y,z)` directly sets the velocity vector. ```js -entity.velocity.set(0, 1, 0); // Launch upward -entity.velocity.set(2, 0, 2); // Horizontal velocity +entity.velocity.set(0, 1, 0); // Launch upward +entity.velocity.set(2, 0, 2); // Horizontal velocity ``` ### entity.bounds Readonly `GameVector3`. The entity's bounding box **half-extents**: + - `x` = width / 2 - `y` = height / 2 - `z` = width / 2 ### entity.onGround -⬆ MC Extension | Readonly. Whether the entity is standing on a block. +Readonly. Whether the entity is standing on a block. ```js if (entity.onGround) { @@ -71,7 +72,7 @@ if (entity.onGround) { ### entity.eyePosition -⬆ MC Extension | Readonly `GameVector3`. Eye position (raycast origin). +Readonly `GameVector3`. Eye position (raycast origin). ```js var eye = entity.eyePosition; @@ -102,13 +103,13 @@ Deals `amount` generic damage to the entity (triggers damage events). Heals the entity by `amount` (capped at maxHp). ```js -zombie.hurt(10); // Deal 10 damage -zombie.heal(5); // Heal 5 +zombie.hurt(10); // Deal 10 damage +zombie.heal(5); // Heal 5 ``` ### entity.invulnerable -⬆ MC Extension | Gets/sets whether the entity is invulnerable (immune to damage). +Gets/sets whether the entity is invulnerable (immune to damage). ```js entity.invulnerable = true; @@ -128,7 +129,7 @@ The following properties control entity physics behavior. Gets/sets whether the entity participates in collisions. Default `true`. When `false`, disables physics for LivingEntity (setNoPhysics). ```js -entity.collides = false; // No-collision ghost +entity.collides = false; // No-collision ghost ``` ### entity.fixed @@ -136,7 +137,7 @@ entity.collides = false; // No-collision ghost Gets/sets whether the entity is fixed in place. Default `false`. When `true`, disables gravity and zeros velocity each tick. ```js -entity.fixed = true; // Stationary decoration, no gravity +entity.fixed = true; // Stationary decoration, no gravity ``` ### entity.gravity @@ -144,7 +145,7 @@ entity.fixed = true; // Stationary decoration, no gravity Gets/sets whether the entity is affected by gravity. Default `true`. When `false`, disables gravity (setNoGravity). ```js -entity.gravity = false; // Floats without gravity +entity.gravity = false; // Floats without gravity ``` ### entity.friction @@ -167,7 +168,7 @@ var ball = world.createEntity({ gravity: true, collides: true, restitution: 0.8, - mass: 0.5 + mass: 0.5, }); ``` @@ -178,13 +179,13 @@ var ball = world.createEntity({ Controls entity invisibility. ```js -entity.meshInvisible = true; // Invisible +entity.meshInvisible = true; // Invisible console.log(entity.meshInvisible); ``` ### entity.glowing -⬆ MC Extension | Gets/sets the glow outline effect (similar to spectral arrow). +Gets/sets the glow outline effect (similar to spectral arrow). ```js entity.glowing = true; @@ -193,47 +194,47 @@ console.log(entity.glowing); ### entity.setGlowColor(color) -⬆ MC Extension | Sets the glow outline color via team color, mapping RGB to the nearest `ChatFormatting` (16 colors). +Sets the glow outline color via team color, mapping RGB to the nearest `ChatFormatting` (16 colors). ```js entity.glowing = true; -entity.setGlowColor(new GameRGBColor(1, 0, 0)); // Red glow -entity.setGlowColor(new GameRGBColor(0, 0, 1)); // Blue glow +entity.setGlowColor(new GameRGBColor(1, 0, 0)); // Red glow +entity.setGlowColor(new GameRGBColor(0, 0, 1)); // Blue glow ``` ### entity.setText(text) -⬆ MC Extension | Sets the text content of a text display entity (only effective on `minecraft:text_display` entities). +Sets the text content of a text display entity (only effective on `minecraft:text_display` entities). ### entity.setTextColor(color) -⬆ MC Extension | Sets the text color for text display entities. +Sets the text color for text display entities. ### entity.setTextBackgroundColor(color) -⬆ MC Extension | Sets the background color for text display entities. `GameRGBAColor` can be used for semi-transparent backgrounds. +Sets the background color for text display entities. `GameRGBAColor` can be used for semi-transparent backgrounds. ```js // Create a text display entity var textEntity = world.createEntity("minecraft:text_display", pos); textEntity.setText("Hello, World!"); -textEntity.setTextColor(new GameRGBColor(1, 1, 1)); // White text +textEntity.setTextColor(new GameRGBColor(1, 1, 1)); // White text textEntity.setTextBackgroundColor(new GameRGBAColor(0, 0, 0, 0.5)); // Semi-transparent black background ``` ### entity.nameTag -⬆ MC Extension | Gets/sets the entity's custom display name (supports color codes). Empty string = no name. +Gets/sets the entity's custom display name (supports color codes). Empty string = no name. ```js entity.nameTag = "§cBoss Mob"; -console.log(entity.nameTag); // Property access -entity.setNameTag("§eGuard"); // Method access +console.log(entity.nameTag); // Property access +entity.setNameTag("§eGuard"); // Method access ``` ## Tag System - Tags are string markers attached to entities (backed by Minecraft scoreboard tags), used for classification and queries. +Tags are string markers attached to entities (backed by Minecraft scoreboard tags), used for classification and queries. ### entity.addTag(tag) @@ -273,38 +274,38 @@ var bosses = world.querySelectorAll(".boss"); ### entity.setFire(ticks) -⬆ MC Extension | Sets the entity on fire for the given number of ticks. 20 ticks = 1 second. +Sets the entity on fire for the given number of ticks. 20 ticks = 1 second. ### entity.clearFire() -⬆ MC Extension | Extinguishes any fire on the entity. +Extinguishes any fire on the entity. ```js -entity.setFire(100); // Ignite for 5 seconds -entity.clearFire(); // Extinguish immediately +entity.setFire(100); // Ignite for 5 seconds +entity.clearFire(); // Extinguish immediately ``` ## AI & Navigation ### entity.setAI(enabled) -⬆ MC Extension | Enables/disables the entity's AI (Mob only). When disabled, the entity won't move or attack. +Enables/disables the entity's AI (Mob only). When disabled, the entity won't move or attack. ```js -entity.setAI(false); // Freeze entity +entity.setAI(false); // Freeze entity ``` ### entity.setTarget(target) -⬆ MC Extension | Sets the mob's attack target (Mob only). The mob will pathfind to and attack it. +Sets the mob's attack target (Mob only). The mob will pathfind to and attack it. ### entity.getTarget() -⬆ MC Extension | Returns the current attack target, or `null`. +Returns the current attack target, or `null`. ### entity.clearTarget() -⬆ MC Extension | Clears the attack target, stopping pursuit. +Clears the attack target, stopping pursuit. ```js var boss = world.spawnEntity("minecraft:skeleton", new GameVector3(0, 100, 0)); @@ -316,7 +317,7 @@ boss.clearTarget(); ### entity.navigateTo(x, y, z, speed) -⬆ MC Extension | Orders a pathfinder mob to navigate to the given coordinates. Returns `true` if path calculation succeeded. +Orders a pathfinder mob to navigate to the given coordinates. Returns `true` if path calculation succeeded. ### entity.navigateTo(pos, speed) @@ -329,7 +330,7 @@ entity.navigateTo(target.position, 1.0); ### entity.lookAt(x, y, z) -⬆ MC Extension | Makes the entity look at the given coordinates. +Makes the entity look at the given coordinates. ### entity.lookAt(pos) @@ -353,9 +354,9 @@ Applies a status effect. `duration` in ticks (20 ticks = 1 second), `amplifier` Applies an effect, optionally hiding particles. ```js -entity.addEffect("minecraft:speed", 600, 2); // Speed III, 30 seconds -entity.addEffect("minecraft:strength", 99999, 1, true); // Permanent Strength II, no particles -entity.addEffect("minecraft:glowing", 200, 0); // Glowing 10 seconds +entity.addEffect("minecraft:speed", 600, 2); // Speed III, 30 seconds +entity.addEffect("minecraft:strength", 99999, 1, true); // Permanent Strength II, no particles +entity.addEffect("minecraft:glowing", 200, 0); // Glowing 10 seconds // Common effects: // minecraft:speed, minecraft:slowness, minecraft:strength @@ -372,14 +373,14 @@ All ⬆ MC Extension. Equips an item onto a mob. **Slot values:** -| slot | Description | -|------|-------------| -| `"mainhand"` | Main hand | -| `"offhand"` | Off hand | -| `"head"`, `"helmet"`, `"helm"` | Helmet | -| `"chest"`, `"chestplate"` | Chestplate | -| `"legs"`, `"leggings"` | Leggings | -| `"feet"`, `"boots"` | Boots | +| slot | Description | +| ------------------------------ | ----------- | +| `"mainhand"` | Main hand | +| `"offhand"` | Off hand | +| `"head"`, `"helmet"`, `"helm"` | Helmet | +| `"chest"`, `"chestplate"` | Chestplate | +| `"legs"`, `"leggings"` | Leggings | +| `"feet"`, `"boots"` | Boots | ```js entity.setEquipment("mainhand", "minecraft:diamond_sword"); @@ -393,8 +394,8 @@ entity.setEquipment("feet", "minecraft:leather_boots"); Sets the drop chance for an equipment slot, range 0.0–1.0. Use `"all"` for `slot` to set all slots at once (both hands + four armor slots). ```js -entity.setDropChance("mainhand", 0.5); // 50% chance to drop main hand item -entity.setDropChance("all", 0); // Drop nothing +entity.setDropChance("mainhand", 0.5); // 50% chance to drop main hand item +entity.setDropChance("all", 0); // Drop nothing ``` ## Attributes @@ -433,23 +434,23 @@ Destroys the entity. If a callback was registered via `setOnDestroy()`, it will Registers a callback called when the entity is destroyed. `handler` receives one argument `(entity)`. ```js -entity.setOnDestroy(function(e) { +entity.setOnDestroy(function (e) { console.log("Entity " + e.id + " destroyed"); }); ``` ### entity.setPersistent(v) -⬆ MC Extension | When `true`, prevents the mob from despawning naturally (Mob only). Write-only method, no getter. +When `true`, prevents the mob from despawning naturally (Mob only). Write-only method, no getter. ```js var boss = world.spawnEntity( "minecraft:wither_skeleton", new GameVector3(0, 100, 0), ); -boss.setPersistent(true); // Won't despawn +boss.setPersistent(true); // Won't despawn boss.setNameTag("§c§lWither Guard"); -boss.setOnDestroy(function(e) { +boss.setOnDestroy(function (e) { world.say("Boss defeated!"); }); ``` diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/gui.md b/Box3JS-NeoForge-1.21.1/docs/en/api/gui.md new file mode 100644 index 0000000..fbe9704 --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/gui.md @@ -0,0 +1,52 @@ +# gui — Custom GUI + +Client-side custom container GUI (chest-like screen), fully controlled by scripts. + +## gui.openGUI(config) + +Opens a script-controlled custom container GUI, returning a `GuiController` object. +The client automatically requests the server to create the container. + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `config.title` | string | `"Container"` | Title | +| `config.rows` | number | `3` | Number of rows (1–6) | +| `config.slots` | object | `{}` | Initial items, format `{ [slot]: "itemId" }` | + +```js +var ctrl = gui.openGUI({ + title: "§6Shop", + rows: 3, + slots: { 0: "minecraft:diamond", 4: "minecraft:emerald" }, +}); + +// Set item +ctrl.setItem(1, "minecraft:gold_ingot", 5); + +// Get item +var item = ctrl.getItem(0); +console.log(item.id, item.count); // minecraft:diamond, 1 + +// Slot click listener +var clickToken = ctrl.onSlotClick((slot) => { + console.log("Clicked slot:", slot); +}); + +// Close listener +var closeToken = ctrl.onClose(() => { + console.log("GUI closed"); +}); + +// Close the GUI +ctrl.close(); +``` + +## GuiController Methods + +| Method | Description | +|--------|-------------| +| `setItem(slot, itemId, count?)` | Sets the item in the given slot | +| `getItem(slot)` | Gets the item in the given slot, returns `{ id, count }` | +| `onSlotClick(callback)` | Registers a slot click callback and returns `GameEventHandlerToken`, `callback(slot: number)` | +| `onClose(callback)` | Registers a close callback and returns `GameEventHandlerToken`, `callback()` | +| `close()` | Closes the GUI | diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/input.md b/Box3JS-NeoForge-1.21.1/docs/en/api/input.md new file mode 100644 index 0000000..bd37a8f --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/input.md @@ -0,0 +1,81 @@ +# input — Input API + +Client-side keyboard and mouse input detection. + +## input.isKeyDown(key) + +Checks whether a key is currently held down. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | string | Key name (lowercase), see key list below | + +```js +if (input.isKeyDown("space")) { + // Space key is held +} +``` + +## input.onKeyPress(key, callback) + +Registers a callback fired once when the key is pressed. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. + +```js +var token = input.onKeyPress("f", () => { + chat.sendCommand("fly"); +}); + +// Unregister +token.cancel(); +``` + +## input.getMouseX() + +Gets the current mouse X position in screen pixels. + +```js +var mx = input.getMouseX(); +``` + +## input.getMouseY() + +Gets the current mouse Y position in screen pixels. + +```js +var my = input.getMouseY(); +``` + +## input.onMouseClick(callback) + +Registers a mouse button callback. Returns `GameEventHandlerToken`; call `.cancel()` to unregister. + +Callback: `(button: number, action: number, x: number, y: number) => void` + +| Parameter | Description | +|-----------|-------------| +| `button` | 0=left, 1=right, 2=middle | +| `action` | 0=release, 1=press, 2=repeat | +| `x` | Mouse X in screen pixels | +| `y` | Mouse Y in screen pixels | + +```js +var token = input.onMouseClick((button, action, x, y) => { + if (action === 1) { // pressed + console.log(`Clicked button ${button} at (${x}, ${y})`); + } +}); + +// Unregister +token.cancel(); +``` + +## Supported Key Names + +| Category | Keys | +|----------|------| +| Letters | `a`–`z` | +| Digits | `0`–`9` | +| Function keys | `f1`–`f12` | +| Arrow keys | `up`, `down`, `left`, `right` | +| Special keys | `space`, `enter`, `escape`, `tab`, `backspace`, `delete` | +| Modifiers | `shift`, `left_shift`, `right_shift`, `ctrl`, `left_ctrl`, `right_ctrl`, `alt`, `left_alt`, `right_alt` | diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/player.md b/Box3JS-NeoForge-1.21.1/docs/en/api/player.md index 126bbbd..92ac144 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/player.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/player.md @@ -6,8 +6,8 @@ Obtained via `entity.player`. Includes all `entity` capabilities plus inventory, XP, flight, messaging, teleport, etc. ```js -world.onPlayerJoin(function(entity, tick) { - var p = entity.player; // p is the player object +world.onPlayerJoin(function (entity, tick) { + var p = entity.player; // p is the player object p.directMessage("Welcome back, " + p.name + "!"); }); ``` @@ -26,19 +26,19 @@ Readonly. Player UUID string (same as `entity.id`). Gets/sets the player's operator permission level (0–4). -| Level | Description | -|-------|-------------| -| 0 | Normal player | -| 1 | Can bypass spawn protection | -| 2 | Can use most commands | -| 3 | Can manage players | -| 4 | Full admin (equivalent to `/op`) | +| Level | Description | +| ----- | -------------------------------- | +| 0 | Normal player | +| 1 | Can bypass spawn protection | +| 2 | Can use most commands | +| 3 | Can manage players | +| 4 | Full admin (equivalent to `/op`) | ```js if (player.opLevel >= 2) { // Operations requiring permission level 2 } -player.opLevel = 3; // Set to level 3 via property +player.opLevel = 3; // Set to level 3 via property ``` There is also `player.getOpLevel()` method returning the permission level number. @@ -54,7 +54,7 @@ Gets/sets whether the player is invisible. Readonly. Player model scale (Minecraft native scale, not Box3 scale). ```js -player.invisible = true; // Invisible +player.invisible = true; // Invisible console.log("Player scale: " + player.scale); ``` @@ -76,8 +76,6 @@ Readonly. Player bounding-box half extents. Readonly. Whether the player is currently standing on a block. - - ### player.walkSpeed Walk speed, maps to `MOVEMENT_SPEED` attribute base value. Default ~0.1. @@ -95,8 +93,8 @@ Jump strength, maps to `JUMP_STRENGTH` attribute base value. Default ~0.42. Gets/sets whether jumping is enabled. Default `true`. When set to `false`, saves the current jump strength and sets `JUMP_STRENGTH` to 0; set back to `true` to restore. ```js -player.enableJump = false; // Disable jumping -player.enableJump = true; // Re-enable jumping +player.enableJump = false; // Disable jumping +player.enableJump = true; // Re-enable jumping ``` ### player.crouchSpeed @@ -108,38 +106,38 @@ Gets/sets crouch speed (custom property, default `0.0`). MC has no independent s Gets/sets swim speed. Backed by the `WATER_MOVEMENT_EFFICIENCY` attribute. ```js -player.swimSpeed = 0.5; // Swim faster +player.swimSpeed = 0.5; // Swim faster ``` ### player.moveState Readonly. Current movement state string: -| Value | Description | -|-------|-------------| +| Value | Description | +| ---------- | ---------------- | | `"FLYING"` | Currently flying | -| `"SWIM"` | In water | -| `"JUMP"` | Jumping upward | -| `"FALL"` | Falling | -| `"GROUND"` | On the ground | +| `"SWIM"` | In water | +| `"JUMP"` | Jumping upward | +| `"FALL"` | Falling | +| `"GROUND"` | On the ground | ### player.walkState Readonly. Current walk state string: -| Value | Description | -|-------|-------------| +| Value | Description | +| ---------- | -------------------- | | `"CROUCH"` | Crouching / sneaking | -| `"RUN"` | Sprinting | -| `"WALK"` | Walking | -| `"NONE"` | Standing still | +| `"RUN"` | Sprinting | +| `"WALK"` | Walking | +| `"NONE"` | Standing still | ```js -player.walkSpeed = 0.2; // Speed up -player.jumpPower = 0.6; // Jump higher -player.swimSpeed = 0.3; // Swim speed +player.walkSpeed = 0.2; // Speed up +player.jumpPower = 0.6; // Jump higher +player.swimSpeed = 0.3; // Swim speed -world.onTick(function() { +world.onTick(function () { if (player.walkState === "RUN") { // Player is sprinting } @@ -182,16 +180,16 @@ player.disableFly = true; ### player.collision -⬆ MC Extension | Gets/sets team collision. Set to `false` to prevent players from pushing each other. Backed by the player's team `CollisionRule` (ALWAYS / NEVER). +Gets/sets team collision. Set to `false` to prevent players from pushing each other. Backed by the player's team `CollisionRule` (ALWAYS / NEVER). ```js -player.collision = false; // Disable collision +player.collision = false; // Disable collision console.log(player.collision); ``` ## Health -⬆ MC Extension | Gets/sets player health. `ServerPlayer` is a `LivingEntity`, so health is operated on directly. +Gets/sets player health. `ServerPlayer` is a `LivingEntity`, so health is operated on directly. ### player.hp @@ -207,8 +205,8 @@ Readonly. Whether the player is dead or dying (`isDeadOrDying()`). ```js // Set class-specific health -player.maxHp = 40; // Warrior 40 HP -player.hp = 40; // Full health +player.maxHp = 40; // Warrior 40 HP +player.hp = 40; // Full health // Current health is clamped when max decreases player.maxHp = 20; @@ -226,17 +224,15 @@ if (player.dead) { Gets/sets game mode. Get returns a name string; set accepts a string or number. ```js -player.gameMode = "creative"; // Creative -player.gameMode = "survival"; // Survival -player.gameMode = "adventure"; // Adventure -player.gameMode = "spectator"; // Spectator +player.gameMode = "creative"; // Creative +player.gameMode = "survival"; // Survival +player.gameMode = "adventure"; // Adventure +player.gameMode = "spectator"; // Spectator // Or by number: 0=survival, 1=creative, 2=adventure, 3=spectator ``` ## Camera - - ### player.cameraMode Gets/sets the camera mode: `"FPS"` (first-person) or `"FOLLOW"` (follow entity). Setting to `"FPS"` clears the follow target. @@ -259,7 +255,7 @@ Readonly `GameVector3`. A point 5 blocks ahead of the player's eyes. ### player.lookAt(x, y, z) -⬆ MC Extension | Makes the player look at the given coordinates. +Makes the player look at the given coordinates. ### player.lookAt(pos) @@ -304,7 +300,7 @@ Forces the player to respawn (only works when dead). ### player.dimension -⬆ MC Extension | Gets/sets the player's dimension. Setting it performs a cross-dimensional teleport. +Gets/sets the player's dimension. Setting it performs a cross-dimensional teleport. ```js player.teleport(new GameVector3(0, 100, 0)); @@ -337,10 +333,10 @@ Sends a chat message visible only to this player (system message). ### player.directMessage(msg, color) -⬆ MC Extension | Sends a colored chat message. +Sends a colored chat message. ```js -player.directMessage("Success!", new GameRGBColor(0, 1, 0)); // Green +player.directMessage("Success!", new GameRGBColor(0, 1, 0)); // Green player.directMessage("Warning!", new GameRGBColor(1, 0.5, 0)); // Orange ``` @@ -354,7 +350,7 @@ Displays a screen title with default animation: fade-in 10 ticks, stay 70 ticks, ### player.title(title, subtitle, fadeIn, stay, fadeOut) -⬆ MC Extension | Title with full animation parameters. `fadeIn`/`stay`/`fadeOut` are all in ticks (20 ticks = 1 second). +Title with full animation parameters. `fadeIn`/`stay`/`fadeOut` are all in ticks (20 ticks = 1 second). ### player.dialog(config) @@ -384,7 +380,7 @@ player.link("https://example.com"); // Dialog tree player.directMessage("Enter your choice: A or B"); -player.onChat(function(entity, msg, tick) { +player.onChat(function (entity, msg, tick) { if (msg === "A") { player.directMessage("You chose A"); } @@ -395,23 +391,23 @@ player.onChat(function(entity, msg, tick) { ### player.xp -⬆ MC Extension | Gets/sets experience level. +Gets/sets experience level. ### player.addExperienceLevels(levels) -⬆ MC Extension | Adds `levels` experience levels. +Adds `levels` experience levels. ### player.food -⬆ MC Extension | Gets/sets food level (0–20). +Gets/sets food level (0–20). ### player.saturation -⬆ MC Extension | Gets/sets saturation level (0–20, floating-point). +Gets/sets saturation level (0–20, floating-point). ```js -player.xp = 10; // Set to level 10 -player.addExperienceLevels(3); // Add 3 levels +player.xp = 10; // Set to level 10 +player.addExperienceLevels(3); // Add 3 levels player.food = 20; player.saturation = 10; ``` @@ -468,7 +464,7 @@ Returns the currently held main-hand item as `{id, count}`. Empty hand returns ` ```js var held = player.getHeldItem(); -console.log(held.id, held.count); // "minecraft:diamond_sword" 1 +console.log(held.id, held.count); // "minecraft:diamond_sword" 1 ``` ### player.clearInventory() @@ -481,30 +477,30 @@ player.clearInventory(); ## Custom Container GUI -⬆ MC Extension | Opens a script-controlled container GUI (chest-like screen) for the player, with custom slot contents, click behavior, and close callbacks. +Opens a script-controlled container GUI (chest-like screen) for the player, with custom slot contents, click behavior, and close callbacks. ### player.openGUI(config?) Opens a container GUI and returns a `GUIController` handle. -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `title` | `string` | `"Container"` | Container title | -| `rows` | `number` | `3` | Number of rows (1–6), 9 slots each | -| `slots` | `{ [slot: number]: string }` | `{}` | Pre-fill slots, key = slot index, value = item ID | +| Parameter | Type | Default | Description | +| --------- | ---------------------------- | ------------- | ------------------------------------------------- | +| `title` | `string` | `"Container"` | Container title | +| `rows` | `number` | `3` | Number of rows (1–6), 9 slots each | +| `slots` | `{ [slot: number]: string }` | `{}` | Pre-fill slots, key = slot index, value = item ID | **Returned `GUIController` methods:** -| Method | Description | -|--------|-------------| -| `setItem(slot, itemId, count?)` | Place an item in the given slot | -| `getItem(slot)` | Get item info as `{ id, count }` | -| `onSlotClick(callback)` | Register click callback; `return false` to cancel | -| `onClose(callback)` | Register close callback (ESC or `close()` fires it) | -| `close()` | Close the container | +| Method | Description | +| ------------------------------- | --------------------------------------------------- | +| `setItem(slot, itemId, count?)` | Place an item in the given slot | +| `getItem(slot)` | Get item info as `{ id, count }` | +| `onSlotClick(callback)` | Register click callback; `return false` to cancel | +| `onClose(callback)` | Register close callback (ESC or `close()` fires it) | +| `close()` | Close the container | ```js -world.onChat(function(entity, msg, tick) { +world.onChat(function (entity, msg, tick) { if (msg === "!shop") { var gui = entity.player.openGUI({ title: "§6§lShop", @@ -518,12 +514,12 @@ world.onChat(function(entity, msg, tick) { gui.setItem(1, "minecraft:netherite_ingot", 5); - gui.onSlotClick(function(slot, player) { + gui.onSlotClick(function (slot, player) { console.log("Clicked slot: " + slot); - if (slot === 0) return false; // prevent taking the diamond + if (slot === 0) return false; // prevent taking the diamond }); - gui.onClose(function(player) { + gui.onClose(function (player) { player.directMessage("Shop closed"); }); } @@ -534,19 +530,19 @@ world.onChat(function(entity, msg, tick) { ### player.addEffect(effectId, duration, amplifier) -⬆ MC Extension | Applies a status effect. `duration` in ticks, `amplifier` starts at 0. +Applies a status effect. `duration` in ticks, `amplifier` starts at 0. ### player.addEffect(effectId, duration, amplifier, hideParticles) -⬆ MC Extension | Applies an effect, optionally hiding particles. +Applies an effect, optionally hiding particles. ### player.clearEffects() -⬆ MC Extension | Removes all status effects. +Removes all status effects. ```js player.addEffect("minecraft:speed", 600, 2); -player.addEffect("minecraft:jump_boost", 99999, 1, true); // Permanent, no particles +player.addEffect("minecraft:jump_boost", 99999, 1, true); // Permanent, no particles player.clearEffects(); ``` @@ -554,11 +550,11 @@ player.clearEffects(); ### player.playSound(path, volume, pitch) -⬆ MC Extension | Plays a sound to this player only. `path` is a namespace ID (e.g. `"minecraft:block.note_block.pling"`), `volume` 0–1, `pitch` 0.5–2. +Plays a sound to this player only. `path` is a namespace ID (e.g. `"minecraft:block.note_block.pling"`), `volume` 0–1, `pitch` 0.5–2. ### player.runCommand(cmd) -⬆ MC Extension | Executes a Minecraft command as this player. +Executes a Minecraft command as this player. ```js player.playSound("minecraft:block.note_block.pling", 0.8, 1.5); @@ -569,11 +565,11 @@ player.runCommand("say hello"); ### player.grantAdvancement(advancementId) -⬆ MC Extension | Grants an advancement to this player. +Grants an advancement to this player. ### player.revokeAdvancement(advancementId) -⬆ MC Extension | Revokes an advancement from this player. +Revokes an advancement from this player. ```js player.grantAdvancement("minecraft:story/mine_stone"); @@ -585,7 +581,7 @@ player.revokeAdvancement("minecraft:story/mine_stone"); ### player.setPlayerListName(name) -⬆ MC Extension | Changes the player's display name in the tab list (supports color codes). +Changes the player's display name in the tab list (supports color codes). ```js player.setPlayerListName("§e[CP3] §f" + player.name); diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/remote-channel.md b/Box3JS-NeoForge-1.21.1/docs/en/api/remote-channel.md new file mode 100644 index 0000000..4d7fffa --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/remote-channel.md @@ -0,0 +1,40 @@ +# remoteChannel — Client ↔ Server Communication + +The client uses `remoteChannel` for bidirectional event communication with the server. Event data is JSON-serialized. + +## remoteChannel.sendServerEvent(event) + +Sends an event to the server. `event` is any JSON-serializable value. + +```js +remoteChannel.sendServerEvent({ + type: "clientReady", + timestamp: Date.now(), +}); +``` + +## remoteChannel.onClientEvent(handler) + +Registers a handler for remote events sent from the server. Returns `GameEventHandlerToken`. + +Callback: `(event: { tick: number, args: T }) => void` + +```js +remoteChannel.onClientEvent((event) => { + const { tick, args } = event; + + switch (args.type) { + case "ping": + console.log(`[client] Ping: ${args.message}`); + remoteChannel.sendServerEvent({ type: "pong" }); + break; + case "notify": + ui.showOverlay(`§b${args.message}`); + break; + } +}); +``` + +::: info +Server-side equivalents: `remoteChannel.sendClientEvent()` / `broadcastClientEvent()` / `onServerEvent()`. See type declarations in `server.d.ts`. +::: diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/ui.md b/Box3JS-NeoForge-1.21.1/docs/en/api/ui.md new file mode 100644 index 0000000..fe20fac --- /dev/null +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/ui.md @@ -0,0 +1,82 @@ +# ui — UI API + +Client-side screen UI display: titles, action bar, custom drawn text. + +## ui.showOverlay(text) + +Displays text in the action bar (above the hotbar). Supports color codes (`§a`, `§b`, etc.). + +```js +ui.showOverlay("§aWelcome to the server!"); +``` + +## ui.showTitle(title, subtitle, fadeIn?, stay?, fadeOut?) + +Displays a large centered screen title. + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `title` | string | (required) | Main title | +| `subtitle` | string | (required) | Subtitle | +| `fadeIn` | number | `10` | Fade-in ticks | +| `stay` | number | `70` | Stay ticks | +| `fadeOut` | number | `20` | Fade-out ticks | + +```js +ui.showTitle("Boss Incoming!", "Get ready", 10, 70, 20); +ui.showTitle("§cGame Over", "§7Try again"); +``` + +## ui.showActionBar(text) + +Displays text in the action bar (same as `showOverlay`). + +```js +ui.showActionBar("§ePress F to use ability"); +``` + +## ui.getScreenSize() + +Gets the current game window and GUI-scaled dimensions. + +```js +var size = ui.getScreenSize(); +console.log(size.width, size.height); // window pixels +console.log(size.scaledWidth, size.scaledHeight); // GUI-scaled +``` + +## ui.drawText(id, x, y, text, color?) + +Draws custom text on screen (persists every frame until removed via `removeDrawText`). + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `id` | number | (required) | Text ID for later removal or update | +| `x` | number | (required) | X position (GUI-scaled coordinates) | +| `y` | number | (required) | Y position (GUI-scaled coordinates) | +| `text` | string | (required) | Text to display | +| `color` | GameRGBColor | white | Text colour | + +Returns the text ID (same as the passed `id`). Reusing the same ID overwrites the previous entry. + +```js +var textId = ui.drawText(1, 10, 10, "Hello, Box3JS!"); +// Update position or content +ui.drawText(1, 10, 30, "Updated text", new GameRGBColor(1, 0, 0)); // red +``` + +## ui.removeDrawText(id) + +Removes the drawn text with the given ID. + +```js +ui.removeDrawText(1); +``` + +## ui.clearDrawTexts() + +Clears all texts drawn via `drawText()`. + +```js +ui.clearDrawTexts(); +``` diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/voxels.md b/Box3JS-NeoForge-1.21.1/docs/en/api/voxels.md index 4e55b7a..ef9c650 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/voxels.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/voxels.md @@ -73,7 +73,7 @@ Place a block, `voxelId` is the internal ID with encoded rotation. ### voxels.fillVoxel(x1, y1, z1, x2, y2, z2, voxel) -⬆ MC Extension | Fill a rectangular region with a block. Corner coordinates are auto-sorted (no need to ensure x1 ≤ x2). +Fill a rectangular region with a block. Corner coordinates are auto-sorted (no need to ensure x1 ≤ x2). ### voxels.fillVoxel(pos1, pos2, voxel) @@ -143,7 +143,7 @@ var name = voxels.getVoxelName(new GameVector3(0, 100, 0)); ### voxels.countVoxel(x1, y1, z1, x2, y2, z2, voxel) -⬆ MC Extension | Count matching blocks in a region. `voxel` can be a string or numeric ID. +Count matching blocks in a region. `voxel` can be a string or numeric ID. ### voxels.countVoxel(pos1, pos2, voxel) @@ -171,7 +171,7 @@ var count = voxels.countVoxel( ### voxels.setSpawner(x, y, z, entityType) -⬆ MC Extension | Set the spawn type of the spawner at the given coordinates. Only effective if that block is `minecraft:spawner`. +Set the spawn type of the spawner at the given coordinates. Only effective if that block is `minecraft:spawner`. ### voxels.setSpawner(pos, entityType) diff --git a/Box3JS-NeoForge-1.21.1/docs/en/api/world.md b/Box3JS-NeoForge-1.21.1/docs/en/api/world.md index e90b74a..9dd191f 100644 --- a/Box3JS-NeoForge-1.21.1/docs/en/api/world.md +++ b/Box3JS-NeoForge-1.21.1/docs/en/api/world.md @@ -48,7 +48,7 @@ console.log(world.rainDensity); // 0.0 ~ 1.0 ### world.thunderDensity -⬆ MC Extension | Get/set thunderstorm intensity, range 0.0–1.0. +Get/set thunderstorm intensity, range 0.0–1.0. ```js world.thunderDensity = 0.5; @@ -56,7 +56,7 @@ world.thunderDensity = 0.5; ### world.clearWeather() -⬆ MC Extension | Clear both rain and thunder. +Clear both rain and thunder. ```js world.clearWeather(); @@ -123,11 +123,11 @@ world.setWorldSpawn(new GameVector3(0, 70, 0)); ### world.getGameRule(name) -⬆ MC Extension | Get a game rule boolean value. +Get a game rule boolean value. ### world.setGameRule(name, value) -⬆ MC Extension | Set a game rule. `value` is a boolean. +Set a game rule. `value` is a boolean. **Supported rules:** @@ -257,38 +257,38 @@ var token = world.onTick(function (info) { }); ``` -| Event | Type | Callback Signature | Trigger | -| ---------------------------- | ------- | ------------------------------------------------------ | --------------------------------------------------- | -| `world.onTick(fn)` | | `(info)` → `{tick, prevTick, elapsedTimeMS, skip}` | Every tick | -| `world.onPlayerJoin(fn)` | | `(entity, tick)` | Player logs in | -| `world.onPlayerLeave(fn)` | | `(entity, tick)` | Player leaves | -| `world.onChat(fn)` | | `(entity, message, tick) => boolean \| void` | Player sends chat message; return `false` to cancel | -| `world.onVoxelDestroy(fn)` | | `(entity, x, y, z, voxel, tick)` | Player breaks a block | -| `world.onBlockPlace(fn)` | ⬆ MC | `(entity, x, y, z, voxel, voxelId, tick)` | Player places a block | -| `world.onBlockActivate(fn)` | ⬆ MC | `(entity, x, y, z, voxel, tick)` | Player right-clicks a block | -| `world.onInteract(fn)` | | `(entity, target, tick)` | Player right-clicks an entity | -| `world.onVoxelContact(fn)` | | `(entity, voxelId, x, y, z, contactType, force, tick)` | Entity contacts a block | -| `world.onEntityContact(fn)` | | `(entity, other, tick)` | Two entities contact | -| `world.onEntitySeparate(fn)` | | `(entity, other, tick)` | Two entities separate | -| `world.onFluidEnter(fn)` | | `(entity, fluid, x, y, z, tick)` | Entity enters a fluid | -| `world.onFluidLeave(fn)` | | `(entity, fluid, x, y, z, tick)` | Entity leaves a fluid | -| `world.onEntityDeath(fn)` | ⬆ MC | `(entity, killer, tick)` | Entity dies; `killer` may be null | -| `world.onEntityDamage(fn)` | ⬆ MC | `(entity, amount, source, attacker, tick)` | Entity takes damage (Pre phase) | -| `world.onPlayerRespawn(fn)` | ⬆ MC | `(entity, tick)` | Player respawns | -| `world.onButtonPressed(fn)` | ⬆ MC | `(entity, button, tick)` | Player presses a button | -| `world.onMessage(fn)` | ⬆ MC | `(from, data)` | Receives `world.sendMessage()` message | +| Event | Type | Callback Signature | Trigger | +| ---------------------------- | ---- | ------------------------------------------------------ | --------------------------------------------------- | +| `world.onTick(fn)` | | `(info)` → `{tick, prevTick, elapsedTimeMS, skip}` | Every tick | +| `world.onPlayerJoin(fn)` | | `(entity, tick)` | Player logs in | +| `world.onPlayerLeave(fn)` | | `(entity, tick)` | Player leaves | +| `world.onChat(fn)` | | `(entity, message, tick) => boolean \| void` | Player sends chat message; return `false` to cancel | +| `world.onVoxelDestroy(fn)` | | `(entity, x, y, z, voxel, tick)` | Player breaks a block | +| `world.onBlockPlace(fn)` | ⬆ MC | `(entity, x, y, z, voxel, voxelId, tick)` | Player places a block | +| `world.onBlockActivate(fn)` | ⬆ MC | `(entity, x, y, z, voxel, tick)` | Player right-clicks a block | +| `world.onInteract(fn)` | | `(entity, target, tick)` | Player right-clicks an entity | +| `world.onVoxelContact(fn)` | | `(entity, voxelId, x, y, z, contactType, force, tick)` | Entity contacts a block | +| `world.onEntityContact(fn)` | | `(entity, other, tick)` | Two entities contact | +| `world.onEntitySeparate(fn)` | | `(entity, other, tick)` | Two entities separate | +| `world.onFluidEnter(fn)` | | `(entity, fluid, x, y, z, tick)` | Entity enters a fluid | +| `world.onFluidLeave(fn)` | | `(entity, fluid, x, y, z, tick)` | Entity leaves a fluid | +| `world.onEntityDeath(fn)` | ⬆ MC | `(entity, killer, tick)` | Entity dies; `killer` may be null | +| `world.onEntityDamage(fn)` | ⬆ MC | `(entity, amount, source, attacker, tick)` | Entity takes damage (Pre phase) | +| `world.onPlayerRespawn(fn)` | ⬆ MC | `(entity, tick)` | Player respawns | +| `world.onButtonPressed(fn)` | ⬆ MC | `(entity, button, tick)` | Player presses a button | +| `world.onMessage(fn)` | ⬆ MC | `(from, data)` | Receives `world.sendMessage()` message | ### GameButtonType The `button` parameter in `world.onButtonPressed` callbacks is one of the following string constants: -| Constant | Description | -| ----------- | ------------------ | -| `"WALK"` | Walk (hold) | -| `"RUN"` | Run / sprint (hold) | +| Constant | Description | +| ----------- | --------------------- | +| `"WALK"` | Walk (hold) | +| `"RUN"` | Run / sprint (hold) | | `"CROUCH"` | Crouch / sneak (hold) | -| `"JUMP"` | Jump | -| `"FLY"` | Fly (hold) | +| `"JUMP"` | Jump | +| `"FLY"` | Fly (hold) | | `"ACTION0"` | Screen button 0 (tap) | | `"ACTION1"` | Screen button 1 (tap) | @@ -599,14 +599,20 @@ world.launchFirework(new GameVector3(0, 100, 0), "red", "star"); ### world.launchFirework(x, y, z, colors, shape) -⬆ MC Extension | Launches a firework with an array of `GameRGBColor` values for arbitrary RGB colors. +Launches a firework with an array of `GameRGBColor` values for arbitrary RGB colors. ### world.launchFirework(pos, colors, shape) ⬆ GameVector3 + `GameRGBColor[]` overload. ```js -world.launchFirework(0, 100, 0, [new GameRGBColor(1, 0, 0), new GameRGBColor(1, 0.5, 0)], "large_ball"); +world.launchFirework( + 0, + 100, + 0, + [new GameRGBColor(1, 0, 0), new GameRGBColor(1, 0.5, 0)], + "large_ball", +); ``` ### world.spawnParticle(type, x, y, z, count, dx, dy, dz, speed) @@ -619,7 +625,7 @@ Spawn particles at coordinates. Particle type uses namespaced ID. ### world.spawnParticle(x, y, z, color, count, dx, dy, dz, speed) -⬆ MC Extension | Spawns colored particles (dust type) using `GameRGBColor` to specify the color. +Spawns colored particles (dust type) using `GameRGBColor` to specify the color. ### world.spawnParticle(pos, color, count, dx, dy, dz, speed) @@ -627,10 +633,28 @@ Spawn particles at coordinates. Particle type uses namespaced ID. ```js // Spawn red particles -world.spawnParticle(0, 100, 0, new GameRGBColor(1, 0, 0), 20, 0.5, 0.5, 0.5, 0.1); +world.spawnParticle( + 0, + 100, + 0, + new GameRGBColor(1, 0, 0), + 20, + 0.5, + 0.5, + 0.5, + 0.1, +); // Spawn cyan particles -world.spawnParticle(entity.position, new GameRGBColor(0, 1, 1), 10, 0.2, 0.2, 0.2, 0); +world.spawnParticle( + entity.position, + new GameRGBColor(0, 1, 1), + 10, + 0.2, + 0.2, + 0.2, + 0, +); ``` ### world.spawnParticleCircle(x, y, z, radius, type, count) @@ -770,7 +794,7 @@ Returns all entities within the AABB defined by two corner positions. ### world.entitiesInRadius(x, y, z, radius) -⬆ MC Extension | Returns all entities within a spherical radius. Convenience wrapper around `entitiesInArea`. +Returns all entities within a spherical radius. Convenience wrapper around `entitiesInArea`. ### world.entitiesInRadius(pos, radius) @@ -787,7 +811,7 @@ for (var i = 0; i < nearby.length; i++) { ### world.getBiome(x, y, z) -⬆ MC Extension | Returns the biome namespaced ID string. +Returns the biome namespaced ID string. ### world.getBiome(pos) @@ -803,11 +827,11 @@ var biome = world.getBiome(entity.position); ### world.sendMessage(target, data) -⬆ MC Extension | Send a message to another script project. `target` is `"*"` (broadcast) or a project name. Receivers listen via `world.onMessage()`. +Send a message to another script project. `target` is `"*"` (broadcast) or a project name. Receivers listen via `world.onMessage()`. ### world.runCommand(cmd) -⬆ MC Extension | Execute a command as the server console. +Execute a command as the server console. ```js world.runCommand("time set day"); @@ -818,7 +842,7 @@ world.runCommand("weather clear"); ### world.placeStructure(x, y, z, structureId) -⬆ MC Extension | Places a datapack structure template (NBT) at the given position. +Places a datapack structure template (NBT) at the given position. ### world.placeStructure(pos, structureId) @@ -836,7 +860,7 @@ world.placeStructure(pos, "box3js:arena"); ### world.grantAdvancement(playerName, advancementId) -⬆ MC Extension | Grants an advancement to a player by name. +Grants an advancement to a player by name. ```js world.grantAdvancement("Steve", "minecraft:story/mine_stone"); @@ -846,7 +870,7 @@ world.grantAdvancement("Steve", "minecraft:story/mine_stone"); ### world.listRecipes(filter) -⬆ MC Extension | Searches recipe IDs matching a keyword. +Searches recipe IDs matching a keyword. ```js var recipes = world.listRecipes("diamond"); @@ -855,7 +879,7 @@ console.log(recipes); // ["minecraft:diamond_sword", "minecraft:diamond_block", ### world.removeRecipe(recipeId) -⬆ MC Extension | Blacklists a recipe so it's no longer craftable. Returns whether successful. +Blacklists a recipe so it's no longer craftable. Returns whether successful. ```js world.removeRecipe("minecraft:iron_pickaxe"); @@ -863,7 +887,7 @@ world.removeRecipe("minecraft:iron_pickaxe"); ### world.clearRecipes() -⬆ MC Extension | Clears the recipe blacklist, restoring all original recipes. +Clears the recipe blacklist, restoring all original recipes. ```js world.clearRecipes();