onClose - HimxhMC/HimDSL GitHub Wiki
onClose 回调 / onClose
关闭时触发 / Fired on Close
除了点击槽位,界面被关闭时也能触发逻辑。用 gui.onClose(...) 注册:
Besides slot clicks, the GUI can fire logic on close. Register with gui.onClose(...):
gui.onClose(() -> {
player p = @s;
runcmd(p.name, "msg 界面已关闭");
});
注册在 GUI 上,不是槽位上。整个界面只支持一个 onClose 回调。
Registered on the GUI, not on a slot. Each GUI supports a single onClose.
什么时候触发 / When It Fires
onClose 在这些情况下触发:
onClose fires in these cases:
-
玩家按 Esc 关闭界面。
-
脚本调用
gui.close(p)。 -
玩家打开另一个界面替换掉当前的。
-
Player presses Esc.
-
Script calls
gui.close(p). -
Player opens another inventory, replacing the current one.
不触发的情况:
Not fired for:
-
玩家断线(此时没有"关闭"动作)。
-
服务器关闭。
-
Player disconnect.
-
Server shutdown.
@s 在 onClose 里 / @s in onClose
和点击回调一样,@s 指向关闭界面的玩家:
Like click callbacks, @s is the player who closed:
gui.onClose(() -> {
player p = @s;
runcmd("CONSOLE", "say " + p.name + " 关闭了界面");
});
常见用途 / Common Uses
清理状态 / Cleaning State
玩家打开界面时锁定某些操作,关闭时解锁:
Lock something on open, unlock on close:
gui.onClose(() -> {
player p = @s;
// 例如:移除无敌标记
runcmd("CONSOLE", "effect clear " + p.name + " resistance");
});
记录关闭日志 / Logging
gui.onClose(() -> {
player p = @s;
runcmd("CONSOLE", "say [GUI] " + p.name + " 离开了菜单");
});
打开另一个界面 / Opening Another
gui.onClose(() -> {
player p = @s;
// 假设 secondGui 是另一个已定义的 GUI
// secondGui.open(p);
});
注意:open 是延迟下一 tick 执行的,不会与当前的关闭冲突。但不要在 onClose 里打开同一个 GUI,会造成无限循环。
Note: open is delayed to the next tick and does not clash with the current close. But do not open the same GUI inside its own onClose — infinite loop.
一个完整的例子 / A Complete Example
打开界面时给玩家加个标记,关闭时清除:
Add a flag on open, clear it on close:
bool inMenu;
int main() {
var gui = new GUI(1, "菜单");
var slot = new GUISlot(Material.PAPER);
slot.name = "§a继续";
slot.onLeftClick = () -> {
gui.close(@s);
};
gui[0][4] = slot;
gui.onClose(() -> {
player p = @s;
inMenu = false;
runcmd(p.name, "msg 已退出菜单");
});
gui.updateAll();
var p = @p;
inMenu = true;
gui.open(p);
}
inMenu 变量由闭包捕获。它在 main 里被声明,onClose lambda 和 main 都能访问同一个变量。
inMenu is captured by closure. Declared in main, both main and the onClose lambda see the same variable.
覆盖之前注册的回调 / Overwriting a Previous Callback
同一个 GUI 只能有一个 onClose。再次调用 onClose 会覆盖之前注册的:
A GUI has only one onClose. Calling onClose again overwrites the previous:
gui.onClose(() -> { /* 第一版 */ });
gui.onClose(() -> { /* 第二版 */ }); // 覆盖第一版
想清除已注册的回调,传 null:
To clear a registered callback, pass null:
gui.onClose(null);
与点击回调的关系 / Relation to Click Callbacks
onClose 和点击回调独立触发:
onClose and click callbacks fire independently:
-
点击"关闭"按钮 → 先触发
onLeftClick,然后触发onClose(如果按钮的 lambda 里调用了gui.close)。 -
玩家按 Esc → 只触发
onClose。 -
点击一个普通槽位 → 只触发槽位回调,界面没有关闭,所以
onClose不触发。 -
Click a "close" button →
onLeftClickfires, thenonClose(if the lambda calledgui.close). -
Press Esc → only
onClose. -
Click a normal slot → only the slot callback; the GUI stays open, so no
onClose.
onClose 不是"每次点击后触发",是"界面真的被关闭时触发"。区别很重要。
onClose is not "after every click"; it is "when the GUI is actually closed". The distinction matters.
常见错误 / Common Mistakes
错误一:把 onClose 注册在槽位上
slot.onClose = () -> { ... }; // ✗ 槽位没有 onClose
正确写法是 gui.onClose(lambda)。
错误二:以为每次点击都触发
onClose 只在界面关闭时触发,与点击无关。
错误三:在 onClose 里打开同一个 GUI
gui.onClose(() -> {
gui.open(@s); // ✗ 无限循环
});
关闭后立刻打开会让关闭再触发,进入循环。用 @BukkitRunnable 延迟几 tick 再打开。
Mistake 1: Registering on a slot
Use gui.onClose(lambda).
Mistake 2: Expecting onClose after clicks
Only when the GUI closes.
Mistake 3: Reopening the same GUI inside onClose
Infinite loop. Use @BukkitRunnable with a delay.
小结 / Summary
-
gui.onClose(lambda)注册关闭回调。 -
触发时机:玩家关闭、脚本关闭、切换界面。
-
@s是关闭的玩家。 -
每个 GUI 只有一个
onClose,重复注册会覆盖。 -
传
null清除。 -
不要在
onClose里打开同一个 GUI。 -
gui.onClose(lambda)registers the close callback. -
Fires on player-close, script-close, or inventory switch.
-
@sis the closing player. -
One
onCloseper GUI; re-registering overwrites. -
Pass
nullto clear. -
Do not reopen the same GUI inside
onClose.
下一步 / Next Steps
下一章 [GUI 刷新 / GUI-Refresh] 系统讲 update / updateAll 的时机和性能影响。
Next, [GUI 刷新 / GUI-Refresh] covers when to call update / updateAll and the performance implications.