Repository navigation
GUI Refresh
修改槽位的字段(icon、name、lore)后,改动只存在脚本里。要显示在玩家界面上,必须显式刷新。
Changing slot fields (icon, name, lore) modifies only the script-side data. To display it, you must refresh explicitly.
slot.name = "新名字"; // 只改了脚本数据
// 玩家界面还是旧名字,直到:
gui.update(0, 4); // 或者 gui.updateAll();
这条规则是 HimDSL 的核心设计。它避免每次字段赋值都触发界面重绘,代价是你要记得刷新。
This is a core HimDSL design. It avoids a redraw per assignment; the cost is you must remember to refresh.
刷新单个槽位:
Refresh a single slot:
gui.update(0, 4); // 刷新第 0 行第 4 列
刷新所有槽位:
Refresh every slot:
gui.updateAll();
性能差异:update 只写一格,updateAll 遍历所有格子。3 行 GUI 有 27 格,updateAll 会写 27 次。对现代服务器来说这点开销可以忽略。
Performance difference: update writes one cell; updateAll writes all. A 3-row GUI has 27 cells; updateAll writes 27 times. Negligible on modern servers.
默认用 updateAll:
Default to updateAll:
-
代码简单,不会漏刷新。
-
建立 GUI 时必须用
updateAll(否则玩家看到空界面)。 -
动态修改多格时,一次搞定。
-
性能影响可以忽略。
-
Simple code; nothing forgotten.
-
Required when building the GUI (otherwise empty).
-
One-shot for multi-slot changes.
-
Performance is negligible.
用 update(r, c) 的场景:
Use update(r, c) when:
-
明确只改了一格。
-
在一个频繁触发的回调里(例如每秒触发的定时器)。
-
想让代码"很清楚地指出只改了这一格"。
-
You know exactly one cell changed.
-
Inside a frequently firing callback (e.g. a per-second timer).
-
You want the code to "clearly say only this cell changed".
判断标准:不是"能不用 updateAll 就不用"——大多数时候 updateAll 更清晰,性能差异对玩家完全无感。
Rule of thumb: not "avoid updateAll if possible" — updateAll is clearer most of the time, and players cannot perceive the performance difference.
int main() {
var gui = new GUI(3, "菜单");
// 1. 填入所有槽位
var slotA = new GUISlot(Material.DIAMOND);
slotA.name = "§b钻石";
gui[0][4] = slotA;
var slotB = new GUISlot(Material.EMERALD);
slotB.name = "§a绿宝石";
gui[1][4] = slotB;
// 2. 一次性刷新
gui.updateAll();
// 3. 打开
gui.open(@p);
}
三步走:填 → 刷新 → 打开。顺序不能颠倒。open 之前必须刷新,否则玩家看到空界面。
Three steps: fill → refresh → open. Order matters. Refresh before open, or the player sees an empty GUI.
界面已经打开时,可以在回调里刷新:
While the GUI is open, refresh inside callbacks:
int clicks;
var counterSlot = new GUISlot(Material.CLOCK);
counterSlot.name = "§e点击计数";
counterSlot.lore = {"§7点击次数: §e0"};
counterSlot.onLeftClick = () -> {
player p = @s;
clicks += 1;
counterSlot.lore = {
"§7点击次数: §e" + clicks
};
gui.update(2, 4); // 只改了这一格
};
每点一次就改一格,用 update(2, 4) 精确刷新。用 updateAll 也可以,只是没必要。
One cell per click, so update(2, 4) is precise. updateAll also works, just unnecessary.
定时任务更新界面显示时,刷新会写进所有正在查看该 GUI 的玩家:
When a scheduled task updates the GUI, the refresh affects every viewer:
int seconds;
var timerSlot;
@BukkitRunnable
void tick() sche = 1s {
seconds += 1;
if (timerSlot != null) {
timerSlot.lore = {"§7已运行: §e" + seconds + " 秒"};
// 需要访问 gui,这里假设 gui 也是全局变量
// gui.update(1, 4);
}
}
这个模式适合实时数据展示:在线人数、TPS、倒计时。
This pattern suits live data: online count, TPS, countdowns.
玩家关闭界面后,gui.update 依然会执行,只是没人能看到。这不会报错,也不占用什么资源。
After the player closes the GUI, gui.update still runs, just invisibly. No error, negligible cost.
@BukkitRunnable
void updater() sche = 5s {
// 玩家可能已经关闭界面了
gui.updateAll(); // 安全,无效果
}
不要让刷新成为无意义的后台工作。如果明确知道没有玩家在看这个 GUI,跳过刷新:
Avoid refreshing when no one is watching. Skip when you know it is idle:
@BukkitRunnable
void updater() sche = 5s {
if (/* 有玩家在看 */) {
gui.updateAll();
}
}
判断"有玩家在看"需要自己实现——HimDSL 没有直接的 API。大多数脚本直接刷新,忽略这个小开销。
Checking "is anyone viewing?" requires your own tracking — HimDSL has no direct API. Most scripts just refresh and ignore the tiny overhead.
刷新对玩家是不可见的(一次 tick 内完成)。不要频繁刷新:
Refresh is invisible to players (done within a tick). Do not refresh too frequently:
-
每 tick(
sche = 1t):极端场景,除非有明确需要,避免。 -
每秒(
sche = 1s):实时数据展示,可以接受。 -
每 5~30 秒:更常见的节奏。
-
Every tick (
sche = 1t): avoid unless clearly needed. -
Every second (
sche = 1s): fine for live data. -
Every 5–30 seconds: more typical.
刷新频率不要超过数据变化的频率。倒计时每秒变一次,就每秒刷;TPS 每 5 秒变一次有意义,就 5 秒刷。
Do not refresh faster than the data changes. A countdown changes per second — refresh per second. TPS is meaningful on a 5s window — refresh every 5s.
gui[0][4] = slot;
gui.open(p); // ✗ 空界面
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 9; c++) {
gui.update(r, c); // ✗ 应当用 updateAll
}
}
遍历所有格调 update 等价于 updateAll,但代码更长。
没有自动同步。改字段 → 手动刷新。这条要牢记。
Empty GUI.
Just call updateAll.
No auto-sync. Change → refresh.
-
修改槽位后必须手动刷新。
-
gui.update(r, c)刷新一格;gui.updateAll()刷新全部。 -
默认用
updateAll。 -
建立流程:填 → 刷新 → 打开。
-
定时刷新用于实时数据显示,注意频率。
-
界面关闭后的刷新无害,但没必要。
-
Manual refresh after modifying slots.
-
gui.update(r, c)for one cell;gui.updateAll()for all. -
Default to
updateAll. -
Flow: fill → refresh → open.
-
Timer-based refresh for live data; watch frequency.
-
Post-close refresh is harmless but pointless.
GUI 部分到此结束。五章覆盖了:创建与打开、槽位与显示、点击回调、关闭回调、刷新策略。
The GUI section ends here. Five chapters covered: creation and opening, slots and display, click callbacks, close callbacks, and refresh strategy.
关键约定回顾:
Key conventions:
-
新建 GUI → 填槽位 →
updateAll→open:顺序固定。 -
@s在回调里是点击者:这是 GUI 交互的核心。 -
修改槽位 → 手动刷新:没有自动同步。
-
每个 GUI 一个
onClose:重复注册会覆盖。 -
New GUI → fill slots →
updateAll→open: fixed order. -
@sin callbacks is the clicker: the heart of GUI interaction. -
Modify slot → refresh manually: no auto-sync.
-
One
onCloseper GUI: re-registering overwrites.
下一部分进入内置函数参考。第十章 [数学函数 / Math-Builtins] 从最常用的 abs、max、min 讲起。
The next part covers the built-ins reference. Chapter [数学函数 / Math-Builtins] starts with the most common: abs, max, min.
- 首页 / 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