iridium-script
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese简介
Introduction
Iridium 是一个 Minecraft 1.20.1/1.21.10 客户端,基于Forge运行,带有一个基于Java Script的脚本执行器
脚本可以注册模块、设置项、HUD 元素和聊天命令,监听游戏事件,直接调用 Java API。
Iridium is a Minecraft 1.20.1/1.21.10 client running on Forge, with a JavaScript-based script executor.
Scripts can register modules, settings, HUD elements, and chat commands, listen to game events, and directly call Java APIs.
开始之前
Before You Start
确保以下材料已经获得:
- : 所有脚本API、Minecraft API大致定义,大部分为Minecraft API,你需要至少阅读Client API章节,Minecraft Types章节供速查
types.d.ts - : 提供一些工具帮助你开发
IridiumMCP
必须先咨询用户(如果用户未提供)写的脚本需要哪个版本,根据不同的版本下载types.d.ts,了解对应的Minecraft API
- https://iridium.styles.wtf/assets/1.21.10/types.d.ts
- https://iridium.styles.wtf/assets/1.20.1/types.d.ts
如果用户要求两个版本都兼容则使用来判断版本,执行对应的逻辑。
client.getMinecraftVersion()所有的API定义都在务必看
types.d.ts文件位置:
| 用途 | 路径 |
|---|---|
| 脚本 | |
| 本地库 | |
Make sure you have the following resources:
- : General definitions for all script APIs and Minecraft APIs, most of which are Minecraft APIs. You need to at least read the Client API chapter, and the Minecraft Types chapter is for quick reference.
types.d.ts - : Provides tools to assist you with development.
IridiumMCP
You must first consult the user (if not provided) which version the script is intended for, download the corresponding according to the version, and familiarize yourself with the corresponding Minecraft API.
types.d.ts- https://iridium.styles.wtf/assets/1.21.10/types.d.ts
- https://iridium.styles.wtf/assets/1.20.1/types.d.ts
If the user requires compatibility with both versions, use to determine the version and execute the corresponding logic.
client.getMinecraftVersion()All API definitions are in — be sure to read it.
types.d.tsFile locations:
| Purpose | Path |
|---|---|
| Scripts | |
| Local libraries | |
MCP
MCP
MCP 提供 Harness 和客户端交互的接口,对开发有很大帮助。
即使客户端没打开,MCP也可以连接因为MCP和客户端是分离的,你可以通过工具确保客户端在线。
ping如果你无法使用IridiumMCP,按照以下步骤安装或者排查
MCP provides an interface for Harness to interact with the client, which is very helpful for development.
Even if the client is not open, MCP can still connect because MCP and the client are separate. You can use the tool to ensure the client is online.
pingIf you cannot use IridiumMCP, follow the steps below to install it or troubleshoot:
未安装MCP
MCP Not Installed
下载到当前目录,不要放在临时目录不然下次可能找不到
https://iridium.styles.wtf/assets/IridiumMCP.exe根据任意方式配置,添加到你的harness mcp配置里,并且尽可能自主完成配置,如果有权限问题等实在无法自主完成的事情再找用户操作。
安装完毕之后用下方文案告知用户(根据用户的提示词语言翻译):
┌─ IridiumMCP Server Setup Complete ────────────────────┐
│ ✓ Config <path> │
│ ✓ MCPs <path> │
│ │
│ ⚡ Restart your agent to load the MCP servers │
└──────────────────────────────────────────────────────┘Download to the current directory. Do not place it in a temporary directory, otherwise it may not be found next time.
https://iridium.styles.wtf/assets/IridiumMCP.exeConfigure it in any way, add it to your harness MCP configuration, and complete the configuration on your own as much as possible. Only ask the user for operations if you really cannot complete them independently, such as permission issues.
After installation, inform the user with the following message (translate according to the language of the user's prompt):
┌─ IridiumMCP Server Setup Complete ────────────────────┐
│ ✓ Config <path> │
│ ✓ MCPs <path> │
│ │
│ ⚡ Restart your agent to load the MCP servers │
└──────────────────────────────────────────────────────┘StreamHTTP
StreamHTTP
MCP会打开在
http://127.0.0.1:6767/mcp如果端口被占用应使用
6767IridiumMCP.exe -http 127.0.0.1:6768MCP will run at
http://127.0.0.1:6767/mcpIf port is occupied, use:
6767IridiumMCP.exe -http 127.0.0.1:6768stdio
stdio
IridiumMCP.exe -stdioIridiumMCP.exe -stdio无法使用MCP
MCP Not Working
- 先判断是不是HTTP URL写错了,正确的URL应该包含,如果不包含
/mcp就是错误的/mcp - 重点检查Claude Code,Open Code等工具的settings代理配置,是否忘记配置NO_PROXY,放行127.0.0.1
- First check if the HTTP URL is written incorrectly. The correct URL should include ; if it does not include
/mcp, it is wrong./mcp - Focus on checking the proxy settings in tools like Claude Code, Open Code, etc. — whether you forgot to configure NO_PROXY to allow .
127.0.0.1
库
Libraries
先读取有一些预制的库目录,如果你认为用户的诉求可能需要这个库,使用工具获得源码以便确认用法,然后用来导入,示例:
reference/library.mdget_libraryclient.importjs
var clip = client.import("cubk/clipboard");
log("import ok, keys: " + Object.keys(clip).join(", "));
log("write: " + clip.write("MARKER-8964"));First read which contains a directory of pre-built libraries. If you think the user's request may require a library, use the tool to obtain the source code to confirm usage, then import it with . Example:
reference/library.mdget_libraryclient.importjs
var clip = client.import("cubk/clipboard");
log("import ok, keys: " + Object.keys(clip).join(", "));
log("write: " + clip.write("MARKER-8964"));开发流程
Development Workflow
- 理解用户诉求,创建,还是修改现有脚本
- 尝试连接MCP,并使用工具确保客户端在线,如果客户端不在线告知用户需要启动客户端才能使用MCP,当然没有MCP也不是不能写,只是调试会很难
ping - 阅读理解客户端API
types.d.ts - 找到文件目录,寻找用户要修改的脚本或者创建脚本,可以使用MCP工具快速查看
list_scripts - 编写测试版脚本,确保所有逻辑跑通,期间可以通过,
eval,get_errors,grep_logs工具调试,使用get_logs接口输出的的日志将可以通过log()和grep_logs获得,优先使用get_logs来节省上下文grep_logs - 如果用户编写的是视觉功能,通过来获得游戏内截图确认效果
screenshot - 修改脚本之后使用来重载,客户端不会自动重载
reload_script - 使用可以查看某个library源码
get_library - 确保所有功能跑通之后要求用户确认符合诉求
- 用户如果提出了进一步修改意见,则修改
- 如果用户确认符合诉求则问用户是否要清理调试代码等,清理掉调试代码等以便用户使用
- Understand the user's request: whether to create a new script or modify an existing one.
- Try to connect to MCP and use the tool to ensure the client is online. If the client is offline, inform the user that the client needs to be started to use MCP. Of course, you can still write scripts without MCP, but debugging will be very difficult.
ping - Read to understand the client API.
types.d.ts - Locate the file directory, find the script the user wants to modify or create a new script. You can use the MCP tool for quick viewing.
list_scripts - Write a test version of the script to ensure all logic works. During this process, you can debug using tools like ,
eval,get_errors, andgrep_logs. Logs output via theget_logsinterface can be retrieved vialog()andgrep_logs; prioritize usingget_logsto save context.grep_logs - If the user is developing a visual feature, use to get an in-game screenshot to confirm the effect.
screenshot - After modifying the script, use to reload it. The client does not auto-reload.
reload_script - Use to view the source code of a library.
get_library - After ensuring all features work, ask the user to confirm that the requirements are met.
- If the user raises further modification suggestions, implement them.
- If the user confirms that the requirements are met, ask the user if they want to clean up debugging code, etc. Clean up debugging code and other unnecessary content for the user's convenience.
脚本的结构
Script Structure
一个脚本就是一个 文件,加载时整体执行一次:先注册模块和设置,
再用 挂行为:
.jsevents.on(...)js
client.registerModule("Auto Sprint", -1, "Movement", false);
client.registerSlider("Auto Sprint", "Delay", 5, 1, 20, 1);
events.on("tick", function () {
if (!client.isEnabled("Auto Sprint")) return;
// ...
});脚本被自动预处理包在一个 IIFE 里执行(),所以顶层的 和
都是私有的,不同脚本之间不会互相覆盖。要跨脚本共享代码请用库
(function(){ ...你的代码... })()varfunction分类请用这六个之一: 。
CombatMovementRenderWorldPlayerInventory一个脚本可以注册多个模块、命令、HUD。
A script is a single file that executes entirely once when loaded: first register modules and settings,
then attach behaviors with :
.jsevents.on(...)js
client.registerModule("Auto Sprint", -1, "Movement", false);
client.registerSlider("Auto Sprint", "Delay", 5, 1, 20, 1);
events.on("tick", function () {
if (!client.isEnabled("Auto Sprint")) return;
// ...
});Scripts are automatically preprocessed and wrapped in an IIFE for execution (), so top-level and
declarations are private and will not overwrite each other across different scripts. To share code across scripts, use libraries.
(function(){ ...your code... })()varfunctionUse one of these six categories: , , , , , .
CombatMovementRenderWorldPlayerInventoryA single script can register multiple modules, commands, and HUD elements.
Java调用
Java Interop
引擎提供 Nashorn 风格的 Java 互操作。 以及从它拿到的一切(玩家、实体、物品、世界)
都是 Java 对象,直接调它们的方法就行:
mcjs
mc.player.getX();
mc.player.getMainHandItem().getCount();
mc.level.getBlockState(pos).getBlock();The engine provides Nashorn-style Java interoperation. and everything obtained from it (players, entities, items, worlds)
are Java objects — you can directly call their methods:
mcjs
mc.player.getX();
mc.player.getMainHandItem().getCount();
mc.level.getBlockState(pos).getBlock();取类
Getting Classes
Java.type()newjs
var BlockPos = Java.type("net.minecraft.core.BlockPos");
var Items = Java.type("net.minecraft.world.item.Items");
var Component = Java.type("net.minecraft.network.chat.Component");
var pos = new BlockPos(100, 64, 200); // 构造
var stick = Items.STICK; // 静态字段
var text = Component.literal("hello"); // 静态方法用点号写全限定名(),不是斜杠。
数组类型写 、。
net.minecraft.core.BlockPos"int[]""java.lang.String[]"内部类(嵌套类、枚举)用 分隔,不是点。 引擎直接把名字交给
,不会自动把点换成 ,写错会报 :
$Class.forName$Java class not foundjs
Java.type("com.mojang.blaze3d.vertex.VertexFormat$Mode"); // 对
Java.type("net.minecraft.world.entity.Entity$RemovalReason"); // 对
Java.type("com.mojang.blaze3d.vertex.VertexFormat.Mode"); // 错,找不到类枚举常量当静态字段取:
js
var Mode = Java.type("com.mojang.blaze3d.vertex.VertexFormat$Mode");
var quads = Mode.QUADS;Java.typeUse to get a class, which can be used for instances, reading static fields, and calling static methods:
Java.type()newjs
var BlockPos = Java.type("net.minecraft.core.BlockPos");
var Items = Java.type("net.minecraft.world.item.Items");
var Component = Java.type("net.minecraft.network.chat.Component");
var pos = new BlockPos(100, 64, 200); // Constructor
var stick = Items.STICK; // Static field
var text = Component.literal("hello"); // Static methodWrite fully qualified names with dots (), not slashes.
net.minecraft.core.BlockPosFor array types, write , .
"int[]""java.lang.String[]"Inner classes (nested classes, enums) are separated by , not dots. The engine directly passes the name to
and does not automatically convert dots to . Incorrect names will throw :
$Class.forName$Java class not foundjs
Java.type("com.mojang.blaze3d.vertex.VertexFormat$Mode"); // Correct
Java.type("net.minecraft.world.entity.Entity$RemovalReason"); // Correct
Java.type("com.mojang.blaze3d.vertex.VertexFormat.Mode"); // Wrong, class not foundEnum constants are accessed as static fields:
js
var Mode = Java.type("com.mojang.blaze3d.vertex.VertexFormat$Mode");
var quads = Mode.QUADS;The result of is cached, so repeated calls have no extra overhead. You can safely write it in event callbacks,
though placing it at the top level of the script is clearer.
Java.type名字映射
Name Mapping
引擎在查字段和方法时会自己做重映射,所以使用 Mojang 名(、)
getXgetMainHandItem如果你确定你写了正确的Mojang名仍然有问题,可以先使用进行探测,因为映射器不是100%能映射所有字段和方法。
eval类名同理,写 即可。
net.minecraft.core.BlockPosThe engine performs remapping automatically when looking up fields and methods, so use Mojang names (, ).
getXgetMainHandItemIf you are sure you have written the correct Mojang name but still have issues, you can use to probe first, as the mapper does not map 100% of all fields and methods.
evalThe same applies to class names — just write .
net.minecraft.core.BlockPos重载和类型转换
Overloading and Type Conversion
参数会按 Java 方法签名自动转换:JS 数字转 //,字符串转 ,
JS 函数可以传给函数式接口(单方法接口)。有重载时引擎按参数个数和类型挑一个匹配的。
intfloatdoubleString拿不准某个方法存不存在、返回什么,用当场试:
evaljs
mc.player.getMainHandItem().getItem().toString()Parameters are automatically converted according to Java method signatures: JS numbers convert to //, strings convert to ,
and JS functions can be passed to functional interfaces (single-method interfaces). When there are overloads, the engine selects a matching one based on the number and type of parameters.
intfloatdoubleStringIf you are unsure whether a method exists or what it returns, test it on the spot with :
evaljs
mc.player.getMainHandItem().getItem().toString()数组
Arrays
Java 数组比集合友好,有 ,也能用下标:
.lengthjs
var arr = someJavaMethodReturningArray();
arr.length;
arr[0];但集合不是数组,见下面的提示一节。
Java arrays are more user-friendly than collections: they have and can be accessed by index:
.lengthjs
var arr = someJavaMethodReturningArray();
arr.length;
arr[0];But collections are not arrays — see the Tips section below.
类型判断
Type Checking
js
var Player = Java.type("net.minecraft.world.entity.player.Player");
if (Java.isType(entity, Player)) { ... }instanceofJava.isTypeJava.isJavaObject(x)js
var Player = Java.type("net.minecraft.world.entity.player.Player");
if (Java.isType(entity, Player)) { ... }instanceofJava.isTypeJava.isJavaObject(x)提示
Tips
一些脚本系统的规范等
Some specifications and notes for the script system.
Java 集合不是 JS 数组
Java Collections Are Not JS Arrays
mc.level.players()java.util.List.lengthfor (var i = 0; i < list.length; i++)0 < undefinedjs
var players = mc.level.players();
players.length // undefined
players.size(); players.get(0) // 可以
Java.from(players).length // 可以,转成真正的 JS 数组Java.from()IterableMap.entrySet().values()mc.level.players()java.util.List.lengthfor (var i = 0; i < list.length; i++)0 < undefinedjs
var players = mc.level.players();
players.length // undefined
players.size(); players.get(0) // Works
Java.from(players).length // Works, converts to a real JS arrayJava.from()IterableMap.entrySet().values()设置项 id 永远是 "模块名:设置名"
"模块名:设置名"Setting IDs Are Always "ModuleName:SettingName"
"ModuleName:SettingName"注册时是两个参数,读取时是一个拼接的字符串:
js
client.registerSlider("My Module", "Speed", 1, 0, 5, 0.1);
client.getNumber("My Module:Speed");HUD 的设置项不属于模块本身,必须用 生成 id,不要手拼。
client.hudProperty(hud, label)Registration takes two parameters, but reading uses a concatenated string:
js
client.registerSlider("My Module", "Speed", 1, 0, 5, 0.1);
client.getNumber("My Module:Speed");HUD settings do not belong to the module itself. You must use to generate the ID — do not concatenate it manually.
client.hudProperty(hud, label)HUD 必须回写 ctx.width
/ ctx.height
ctx.widthctx.heightHUD Must Write Back ctx.width
/ ctx.height
ctx.widthctx.height不写的话元素没有碰撞箱,用户在 HUD 编辑模式里拖不动也点不着,但画面看起来是正常的。
js
client.registerHud("Coords", { anchor: "Left Bottom", x: 4, y: 4 }, function (graphics, ctx) {
var text = "X " + Math.round(mc.player.getX());
render.drawString(graphics, text, ctx.x, ctx.y, 0xFFFFFFFF);
ctx.width = render.getStringWidth(text); // 必须
ctx.height = render.fontHeight(); // 必须
});Without these, the element has no hitbox, and users cannot drag or click it in HUD edit mode, even though it looks normal on screen.
js
client.registerHud("Coords", { anchor: "Left Bottom", x: 4, y: 4 }, function (graphics, ctx) {
var text = "X " + Math.round(mc.player.getX());
render.drawString(graphics, text, ctx.x, ctx.y, 0xFFFFFFFF);
ctx.width = render.getStringWidth(text); // Required
ctx.height = render.fontHeight(); // Required
});3D 标签要传实体,不要传坐标
3D Tags Should Take an Entity, Not Coordinates
传实体时引擎会用 做插值,实体移动时标签跟得住;自己传 拿到的是
tick 末的位置,标签会抖动、和实体渲染位置对不上。
partialTicksgetX()js
render.drawTag("§e" + p.getName().getString(), p, 0.4, { autoScale: true }); // 推荐
render.drawTag("§aSpawn", 100.5, 65, 200.5, {}); // 固定位置才这么写第三个参数是在实体身高之上的额外偏移,碰撞箱高度引擎已经算进去了。
When passing an entity, the engine uses for interpolation, so the tag follows the entity smoothly when it moves. If you pass coordinates obtained from yourself, you get the position at the end of the tick, causing the tag to jitter and not align with the entity's rendered position.
partialTicksgetX()js
render.drawTag("§e" + p.getName().getString(), p, 0.4, { autoScale: true }); // Recommended
render.drawTag("§aSpawn", 100.5, 65, 200.5, {}); // Only use for fixed positionsThe third parameter is the extra offset above the entity's height; the engine already accounts for the hitbox height.
颜色是 ARGB,alpha 在最前
Colors Are ARGB, Alpha First
0xFF55FF550x55FF55文本颜色代码用 (U+00A7),例如 、。
§"§c红色""§l粗体"0xFF55FF550x55FF55Text color codes use (U+00A7), e.g., , .
§"§cRed""§lBold"模块开关要自己判断
Module Enable/Disable Must Be Checked Manually
注册模块不会让事件只在开启时触发。每个回调都要自己检查:
js
events.on("tick", function () {
if (!client.isEnabled("My Module")) return;
// ...
});也可以监听 / 事件做初始化和清理。
enabledisable当然,你可以写其他模块的附属功能,开启某个其他已有模块才执行的逻辑。
Registering a module does not make events only fire when it is enabled. Every callback must check this on its own:
js
events.on("tick", function () {
if (!client.isEnabled("My Module")) return;
// ...
});You can also listen to / events for initialization and cleanup.
enabledisableOf course, you can write auxiliary features for other modules — logic that only executes when another existing module is enabled.
事件
Events
三类,写法不同:
通知型——只是告诉你发生了什么:
js
events.on("tick", function () { ... });
events.on("render3d", function (partialTicks) { ... });可取消型—— 阻止默认行为:
return truejs
events.on("chat", function (text) {
return text === "secret"; // true = 不发送
});可修改型——收到一个对象,改它的字段:
js
events.on("movementInput", function (e) { e.jump = true; });
events.on("fov", function (e) { e.factor = 1.5; });可修改型事件里 是没用的,必须写字段。哪个事件属于哪类、字段叫什么,
里每条 重载都有注明。
returntypes.d.tson(...)渲染分两个事件: 画屏幕 UI(给你 ), 画世界内容
( / 只能在这里调)。
render2dgraphicsrender3drender.drawTagrender.drawBoxThere are three types, with different usage patterns:
Notification type — only informs you that something happened:
js
events.on("tick", function () { ... });
events.on("render3d", function (partialTicks) { ... });Cancelable type — to prevent the default behavior:
return truejs
events.on("chat", function (text) {
return text === "secret"; // true = do not send
});Modifiable type — receives an object, modify its fields:
js
events.on("movementInput", function (e) { e.jump = true; });
events.on("fov", function (e) { e.factor = 1.5; });In modifiable events, has no effect — you must modify the fields. Which category each event belongs to and what its fields are called
are noted in each overload in .
returnon(...)types.d.tsThere are two rendering events: for drawing screen UI (provides ), and for drawing world content
( / can only be called here).
render2dgraphicsrender3drender.drawTagrender.drawBox3.2.0 更新内容
3.2.0 Update Notes
客户端 3.2.0 对脚本系统进行了大更新(强制更新,不需要判断版本,以下特性均可直接使用),如果你保留了之前的记忆需要了解如下更新的新特性:
Client version 3.2.0 brings major updates to the script system (it is a mandatory update, no version check is needed — all the following features can be used directly). If you have memories of previous versions, you need to understand the new features below:
Java特性
Java Features
| 特性 | 示例 |
|---|---|
| Method Reference | |
| 包名直接访问类 | |
| |
| |
| 函数自动转接口(SAM) | |
| 匿名类 | |
| 继承类 / 实现多个接口 | |
| 在覆盖方法里调用父类实现 |
| |
| |
| 迭代 Java 集合 | |
| 对象相等 | |
| |
| JS 数组传给 Java | 自动转成 Java 数组或 |
| 静态字段 | 实时读写,并按字段类型转换(以前读到的是快照);final 字段只读 |
| Feature | Example |
|---|---|
| Method Reference | |
| Direct class access via package name | |
| |
| |
| Automatic function-to-interface conversion (SAM) | |
| Anonymous classes | |
| Class inheritance / implementing multiple interfaces | |
| Call the parent class implementation in an overridden method |
| |
| |
| Iterating Java collections | |
| Object equality | |
| |
| Passing JS arrays to Java | Automatically converted to Java arrays or |
| Static fields | Read and write in real time, with type conversion based on field type (previously, reads returned snapshots); final fields are read-only |
客户端API
Client API
旧的 等扁平接口全部保留,新增一套对象接口:
client.getBool(...)js
var aura = moduleManager.getModule('Legit Aura');
aura.enabled = true; // 与点击 GUI 一致(有通知)
aura.key = 'R'; // 支持键名
for (var p of aura.getProperties()) {
log(p.label, p.type, p.value, p.visible);
}
var mode = aura.getProperty('Mode');
mode.cycle(); // Single -> Switch
mode.children; // 只返回当前条件下可见的子设置- :
moduleManager、getModule、getModules(category?)、getEnabledModules、getCategories、getCategoryParents、getProperty(id)。hasModule Module- 基本信息:、
name/category/categoryParent、categoryLeaf(可写)、description、icon、inline、script。keyName - 可读写:、
enabled。key - 方法:/
toggle/enable/disable、setEnabled(v, silent)/getProperties/getAllProperties、getProperty、getBinds。bind(key, options)
- 基本信息:
Property- 可读写:,写入时会校验:滑块限制范围并对齐步长,mode 拒绝未知选项,multi 丢弃未知选项。
value - 只读信息:、
type、defaultValue/min/max、inc、options、optionIcons、hint。condition - 界面相关:(包含父级条件)、
visible(可写)、hidden(可写)。label - 层级关系:、
parent、children。swatch - 方法:、
reset、toggle、cycle/select/deselect/isSelected。toggleOption
- 可读写:
- 包装对象会被缓存(同一模块/属性总是同一个对象),每次读取都拿实时状态;对象被注销后再访问会抛 。
ReferenceError
js
var bind = keybindManager.add(aura, 'KP_8', { mode: 'hold' });
bind.key = 'MOUSE4';
bind.remove();
var m = macroManager.add('Message', { name: 'gg', message: '/hub', key: 'H' });
m.run();- :
keybindManager、getBinds、getBind、find(target)、add、remove、keyCode。keyName - :
Bind、target、key、mode、value、visible、isModule、module、property、update()。remove() - :
macroManager、getMacros、getMacro、add('Message' | 'Item', options)、remove。run - :
Macro、name、key、message、item、match、rotation、switchMode、yawOffset、pitch、update()、run()。remove()
| 事件 | 参数 | 说明 |
|---|---|---|
| | 所有鼠标按键的按下/松开,返回 true 取消 |
| | 滚轮,返回 true 取消(例如阻止切换快捷栏) |
| | 字符输入(支持中文),返回 true 取消 |
| | 所有键盘事件(按下 1 / 松开 0 / 重复 2),任何界面下都触发,返回 true 可吞掉按键 |
原有的 事件语义不变(只在游戏中或容器界面里触发,只报告按下)。
keyinputgetMouseX/Yrender2dgetScreenWidth/HeightgetGuiScaleisMouseDownisKeyDownisMouseGrabbedsetMouseGrabbedisScreenOpenkeyCodekeyName键名:凡是需要按键的地方都接受 、、、/、/、,或直接传键码。 和 可以互相转换回来。
'R''F5''LSHIFT''KP_9''NUMPAD9''M4''MOUSE4''key.keyboard.r'keyNamekeyCode- :圆角矩形发光。
render.bloom(graphics, x, y, w, h, radius, color, spread, intensity) - 、
client.getUsername()、client.getVersion()。client.getMinecraftVersion()
All old flat interfaces like are fully retained, and a new set of object-oriented interfaces has been added:
client.getBool(...)js
var aura = moduleManager.getModule('Legit Aura');
aura.enabled = true; // Consistent with clicking the GUI (triggers notification)
aura.key = 'R'; // Supports key names
for (var p of aura.getProperties()) {
log(p.label, p.type, p.value, p.visible);
}
var mode = aura.getProperty('Mode');
mode.cycle(); // Single -> Switch
mode.children; // Only returns child settings visible under current conditions- :
moduleManager,getModule,getModules(category?),getEnabledModules,getCategories,getCategoryParents,getProperty(id).hasModule Module- Basic info: ,
name/category/categoryParent,categoryLeaf(writable),description,icon,inline,script.keyName - Read/write: ,
enabled.key - Methods: /
toggle/enable/disable,setEnabled(v, silent)/getProperties/getAllProperties,getProperty,getBinds.bind(key, options)
- Basic info:
Property- Read/write: , which is validated on write: sliders are limited to range and aligned to step size, mode rejects unknown options, multi discards unknown options.
value - Read-only info: ,
type,defaultValue/min/max,inc,options,optionIcons,hint.condition - UI-related: (includes parent conditions),
visible(writable),hidden(writable).label - Hierarchy: ,
parent,children.swatch - Methods: ,
reset,toggle,cycle/select/deselect/isSelected.toggleOption
- Read/write:
- Wrapper objects are cached (the same module/property always returns the same object), and each read gets the real-time state; accessing an object after it has been unregistered will throw a .
ReferenceError
js
var bind = keybindManager.add(aura, 'KP_8', { mode: 'hold' });
bind.key = 'MOUSE4';
bind.remove();
var m = macroManager.add('Message', { name: 'gg', message: '/hub', key: 'H' });
m.run();- :
keybindManager,getBinds,getBind,find(target),add,remove,keyCode.keyName - :
Bind,target,key,mode,value,visible,isModule,module,property,update().remove() - :
macroManager,getMacros,getMacro,add('Message' | 'Item', options),remove.run - :
Macro,name,key,message,item,match,rotation,switchMode,yawOffset,pitch,update(),run().remove()
| Event | Parameters | Description |
|---|---|---|
| | All mouse button presses/releases, return true to cancel |
| | Mouse wheel, return true to cancel (e.g., prevent hotbar switching) |
| | Character input (supports Chinese), return true to cancel |
| | All keyboard events (press 1 / release 0 / repeat 2), triggered in any interface, return true to consume the key |
The semantics of the original event remain unchanged (only triggered in-game or in container interfaces, only reports presses).
keyinputgetMouseX/Yrender2dgetScreenWidth/HeightgetGuiScaleisMouseDownisKeyDownisMouseGrabbedsetMouseGrabbedisScreenOpenkeyCodekeyNameKey names: Anywhere a key is required, it accepts , , , /, /, , or directly passing a key code. and can be converted to each other.
'R''F5''LSHIFT''KP_9''NUMPAD9''M4''MOUSE4''key.keyboard.r'keyNamekeyCode- : Rounded rectangle glow effect.
render.bloom(graphics, x, y, w, h, radius, color, spread, intensity) - ,
client.getUsername(),client.getVersion().client.getMinecraftVersion()
Forge 事件 Hook
Forge Event Hook
js
var id = events.onForge('LivingDeathEvent', function (e) { log(e.getEntity()); });
events.onForge('ClientChatReceivedEvent', function (e) { return /spam/.test(e.getMessage().getString()); }); // true = 取消
events.offForge(id);- 事件类型可以传 Java 类,也可以传名字:简单名()、嵌套名(
LivingDeathEvent)或全名,子类同样会匹配。RenderGuiOverlayEvent.Pre - 选项:(在 Forge 自己的监听器之前或之后)、
phase: 'pre' | 'post'、receiveCanceled(默认只收主线程发出的事件)。anyThread
js
var id = events.onForge('LivingDeathEvent', function (e) { log(e.getEntity()); });
events.onForge('ClientChatReceivedEvent', function (e) { return /spam/.test(e.getMessage().getString()); }); // true = cancel
events.offForge(id);- Event types can be passed as Java classes or by name: simple name (), nested name (
LivingDeathEvent), or full name. Subclasses will also be matched.RenderGuiOverlayEvent.Pre - Options: (before or after Forge's own listeners),
phase: 'pre' | 'post',receiveCanceled(default only receives events from the main thread).anyThread
Event Loop
Event Loop
setTimeoutsetIntervalclearTimeoutclearIntervalqueueMicrotasksetTimeoutsetIntervalclearTimeoutclearIntervalqueueMicrotaskFetch(WHATWG)
Fetch (WHATWG)
js
const res = await fetch('https://example.com/api', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ a: 1 }),
});
const data = await res.json();- 重定向支持 、
follow、manual三种模式,最多 20 跳。error - 支持 /
AbortController,包括AbortSignal/AbortSignal.timeout。any - 流式读取:响应头一到就 resolve,响应体通过 (
res.body)分块到达。ReadableStream - 自动发送 并自动解压。
accept-encoding: gzip, deflate - 配套对象:、
Request(包括Response/json/redirect/error)、clone、Headers、URL、URLSearchParams、Blob、TextEncoder、TextDecoder。DOMException
js
const res = await fetch('https://example.com/api', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ a: 1 }),
});
const data = await res.json();- Redirects support three modes: ,
follow,manual, with a maximum of 20 hops.error - Supports /
AbortController, includingAbortSignal/AbortSignal.timeout.any - Streaming read: Resolves as soon as response headers arrive, and the response body arrives in chunks via (
res.body).ReadableStream - Automatically sends and automatically decompresses responses.
accept-encoding: gzip, deflate - Supporting objects: ,
Request(includingResponse/json/redirect/error),clone,Headers,URL,URLSearchParams,Blob,TextEncoder,TextDecoder.DOMException
Deno
Deno
js
const server = Deno.serve({ port: 8080 }, async (req) => {
const url = new URL(req.url);
switch (url.pathname) {
case '/hello': return new Response('hi');
case '/echo': return Response.json(await req.json());
case '/sse': return new Response(new ReadableStream({
async pull(c) { await new Promise(r => setTimeout(r, 1000)); c.enqueue('data: tick\n\n'); },
cancel() { log('client left'); }
}), { headers: { 'content-type': 'text/event-stream' } });
default: return new Response('not found', { status: 404 });
}
});js
const server = Deno.serve({ port: 8080 }, async (req) => {
const url = new URL(req.url);
switch (url.pathname) {
case '/hello': return new Response('hi');
case '/echo': return Response.json(await req.json());
case '/sse': return new Response(new ReadableStream({
async pull(c) { await new Promise(r => setTimeout(r, 1000)); c.enqueue('data: tick\n\n'); },
cancel() { log('client left'); }
}), { headers: { 'content-type': 'text/event-stream' } });
default: return new Response('not found', { status: 404 });
}
});