Repository navigation
EventHandler
前面所有脚本都是"运行一次就结束"。事件驱动是另一种模式:脚本定义逻辑,等待游戏事件触发。例如玩家上线、破坏方块、执行命令——这些时刻触发对应的处理函数。
Every script so far ran once and finished. Event-driven is another model: the script defines logic and waits for game events. A player joins, a block breaks, a command runs — these moments trigger the corresponding handler.
用 @EventHandler 注解标记处理函数:
Mark a handler function with @EventHandler:
@EventHandler
void onJoin(event(PlayerJoinEvent)) {
player p = @s;
runcmd("CONSOLE", "say 欢迎 " + p.name);
}
几点说明:
-
@EventHandler是注解,写在返回类型前面。 - 参数
event(PlayerJoinEvent)声明这个函数处理哪种事件。 -
@s在事件里指向触发者(这里是加入的玩家)。 - 返回类型通常是
void。
A few notes:
-
@EventHandleris an annotation, placed before the return type. - The parameter
event(PlayerJoinEvent)declares which event this handles. -
@sinside an event points at the trigger (the joining player here). - The return type is usually
void.
仅仅写 @EventHandler 函数不会让它生效。你必须在脚本的某个入口显式启动:
Writing the function alone does nothing. You must explicitly start it from a script entry:
@EventHandler
void onJoin(event(PlayerJoinEvent)) {
player p = @s;
runcmd("CONSOLE", "say 欢迎 " + p.name);
}
int main() {
start("onJoin");
}
这个设计让事件监听的生命周期可控:脚本决定什么时候开始监听,也可以随时 stop 停止。
This design keeps event listener lifecycle under control: the script decides when to start and can stop at any time.
如果你把事件函数定义在 onServerLoad.himdsl 里,main 会在服务器加载完成后执行,start 就在那时生效。这是最常见的事件脚本写法。
Defining event functions in onServerLoad.himdsl and starting them in main is the most common pattern: main runs after server load, so start takes effect then.
把事件监听写进 onServerLoad.himdsl,每次玩家加入时欢迎他们:
Put the listener in onServerLoad.himdsl to welcome every player on join:
@EventHandler
void onJoin(event(PlayerJoinEvent)) {
player p = @s;
runcmd("CONSOLE", "say 欢迎 " + p.name + " 加入服务器!");
}
@EventHandler
void onQuit(event(PlayerQuitEvent)) {
player p = @s;
runcmd("CONSOLE", "say " + p.name + " 离开了");
}
int main() {
start("onJoin");
start("onQuit");
runcmd("CONSOLE", "say 事件监听已启动");
}
每个事件函数都要单独 start。启动不是批量的。
Each event function is started individually. There is no batch start.
同一个事件可以有多个处理函数,它们都会被触发,顺序不保证:
One event may have several handlers; all fire, order not guaranteed:
@EventHandler
void logJoin(event(PlayerJoinEvent)) {
player p = @s;
runcmd("CONSOLE", "say [日志] " + p.name + " 加入");
}
@EventHandler
void welcomeJoin(event(PlayerJoinEvent)) {
player p = @s;
runcmd(p.name, "title @s title {\"text\":\"欢迎\"}");
}
int main() {
start("logJoin");
start("welcomeJoin");
}
不要让多个处理函数依赖彼此的执行顺序。需要顺序时,把逻辑合并进一个函数。
Never rely on handler ordering. If order matters, merge the logic into one function.
事件函数和普通函数一样,可以用变量、条件、循环、调用其他函数:
Event functions are ordinary functions — variables, conditionals, loops, calls all work:
@EventHandler
void onBreak(event(BlockBreakEvent)) {
player p = @s;
if (p.gamemode == "creative") {
return; // 创造模式不处理
}
runcmd("CONSOLE", "say " + p.name + " 破坏了方块");
}
return 在事件函数里结束当前这次处理,不影响后续事件的触发。
return ends this invocation; future events still fire.
事件函数的返回值被忽略。写 int 返回类型不会让调用方拿到什么。
The event function's return value is ignored. An int return type does not deliver anything to the caller.
@EventHandler
int onJoin(event(PlayerJoinEvent)) { ... } // 返回类型无意义
统一用 void。
Use void uniformly.
-
@EventHandler标记事件处理函数。 -
参数
event(TypeName)声明事件类型。 -
@s在事件里指向触发者。 -
函数必须
start才生效。 -
同一事件可以有多个处理函数,顺序不保证。
-
返回值被忽略,统一用
void。 -
常见模式:写在
onServerLoad.himdsl里,main中start。 -
@EventHandlermarks an event handler. -
Parameter
event(TypeName)declares the event type. -
@spoints at the trigger. -
The function only works after
start. -
Multiple handlers per event; order not guaranteed.
-
Return value ignored; use
void. -
Common pattern: place in
onServerLoad.himdsl,startinsidemain.
下一章 [事件类型解析 / Event-Type-Resolution] 讲怎么知道用哪个事件类型名。
Next, [事件类型解析 / Event-Type-Resolution] shows how to find the right event type name.
- 首页 / Home
- 安装与快速开始 / Installation & Quick Start
- 第一个脚本 / Your First Script
- 命令速查 / Command Reference
- 自动执行脚本 / Auto-run Scripts
- 定义函数 / Defining Functions
- 函数重载 / Function Overloading
- Lambda 表达式 / Lambda Expressions
- 函数式接口 / Functional Interfaces
- 选择器总览 / Selectors Overview
- 选择器过滤器 / Selector Filters
- EntityRef 引用 / EntityRef
- 占位符参考 / Placeholders Reference
- PlaceholderAPI 桥接 / PAPI Bridge
- 创建 GUI / Creating a GUI
- GUISlot 槽位 / GUISlot
- 点击回调 / Click Callbacks
- onClose 回调 / onClose Callback
- GUI 刷新 / GUI Refresh
- 数学函数 / Math Built-ins
- 高精度计算 / BigDecimal Built-ins
- 字符串函数 / String Built-ins
- 集合函数 / Collection Built-ins
- 文件 I/O / File I/O
- 命令与 sleep / Commands & sleep