Commands and Sleep - HimxhMC/HimDSL GitHub Wiki
命令与 sleep / Commands and sleep
runcmd:执行命令 / runcmd: Run a Command
runcmd(executor, command) 是 HimDSL 里执行 Minecraft 命令的方式。第一个参数是执行者,第二个是命令文本。
runcmd(executor, command) executes a Minecraft command. First is the executor, second is the command text.
runcmd("CONSOLE", "say 服务器已就绪");
runcmd("Steve", "spawn");
runcmd(p.name, "give " + p.name + " diamond 5");
命令文本不带前导斜杠。写 "spawn",不写 "/spawn"。
No leading slash in the command text. Write "spawn", not "/spawn".
执行者 / Executor
| 执行者 | 效果 |
|---|---|
"CONSOLE" |
控制台执行,权限最高 |
| 玩家名 | 该玩家执行,受权限限制 |
| Executor | Effect |
|---|---|
"CONSOLE" |
console executes, full permission |
| player name | that player executes, subject to permissions |
"CONSOLE" 不区分大小写:"console"、"Console" 都行。
"CONSOLE" is case-insensitive: "console" and "Console" work.
给玩家执行命令时,玩家必须在线。玩家名拼错或玩家已离线,命令会静默丢弃——不报错,也不执行。这是常见的"命令没反应"原因。
When executing as a player, they must be online. A misspelled name or offline player results in the command being silently dropped — no error, no execution. This is a common cause of "command does nothing".
稳妥的做法:
Safe pattern:
var p = Bukkit.getPlayerExact("Steve");
if (p != null) {
runcmd(p.name, "spawn");
}
(用 Bukkit.getPlayerExact 通过 Java 互操作检查玩家是否存在。)
(Use Bukkit.getPlayerExact via Java interop to check existence.)
异步派发 / Asynchronous Dispatch
runcmd 不会立即执行命令。它把命令排入主线程的下一 tick 执行。
runcmd does not run the command immediately. It schedules it for the next tick on the main thread.
这意味着:
This means:
-
runcmd之后紧接着的代码,命令还没执行。 -
脚本执行完成时,命令可能还在队列里。
-
命令之间顺序保证,但与其他脚本的命令顺序不保证。
-
Right after
runcmd, the command has not run yet. -
When the script finishes, commands may still be queued.
-
Commands are ordered among themselves, but not against other scripts' commands.
日常脚本里不需要关心这些。只想说"我不依赖执行结果"——runcmd 是"发出命令",不是"执行并等待"。
Daily scripts need not worry. Just remember runcmd fires and forgets — it dispatches, it does not wait.
常用命令模式 / Common Command Patterns
广播 / Broadcast
runcmd("CONSOLE", "say " + message);
给玩家发消息 / Message a Player
runcmd(p.name, "msg " + p.name + " 你好");
发放物品 / Give Items
runcmd("CONSOLE", "give " + p.name + " diamond 5");
传送 / Teleport
runcmd("CONSOLE", "tp " + p.name + " 100 64 200");
显示标题 / Title
runcmd(p.name, "title @s title {\"text\":\"欢迎\"}");
runcmd(p.name, "title @s subtitle {\"text\":\"欢迎回来\"}");
sleep:阻塞当前线程 / sleep: Block the Current Thread
sleep(ms) 让脚本暂停指定毫秒数。参数是毫秒。
sleep(ms) pauses the script for the given milliseconds.
runcmd("CONSOLE", "say 开始");
sleep(2000); // 停 2 秒
runcmd("CONSOLE", "say 结束");
这个函数会阻塞当前线程。
This function blocks the current thread.
sleep 的危险性 / Why sleep Is Dangerous
在 main 里调用 sleep 会阻塞服务器主线程。主线程负责处理玩家动作、更新世界、运行所有插件的逻辑。阻塞它意味着整个服务器卡住。
Calling sleep inside main blocks the server main thread. That thread handles player actions, world updates, and every plugin. Blocking it freezes the whole server.
int main() {
runcmd("CONSOLE", "say 处理中");
sleep(10000); // ✗ 所有玩家卡 10 秒
runcmd("CONSOLE", "say 完成");
}
10 秒的 sleep 会让所有玩家卡 10 秒——TPS 掉到 2 以下,服务器基本不可用。
A 10-second sleep freezes every player for 10 seconds — TPS drops below 2, essentially unusable.
正确的"等待"方式 / The Right Way to Wait
需要"等一段时间再执行下一步"时,用 @BukkitRunnable 定时任务,把逻辑拆成多次执行:
To "wait then continue", use a @BukkitRunnable scheduled task, splitting logic across ticks:
int step;
@BukkitRunnable
void process() sche = 2s {
if (step == 0) {
runcmd("CONSOLE", "say 第一步");
step = 1;
} else if (step == 1) {
runcmd("CONSOLE", "say 第二步");
step = 2;
} else {
runcmd("CONSOLE", "say 完成");
stop("process");
step = 0;
}
}
int main() {
step = 0;
start("process");
}
这是唯一正确的"延迟执行"模式——用状态变量 + 定时任务,把等待拆成多次 tick。
This is the correct pattern — state variable + scheduled task, splitting waits across ticks.
一次性延迟 / One-Shot Delay
如果只需要"延迟一次",@BukkitRunnable 不带 sche 是异步的,仍然不能直接操作游戏。稳妥做法是用带 sche 的任务执行一次然后 stop:
For a one-shot delay, @BukkitRunnable without sche runs async — still cannot directly touch the game. A safer pattern: a scheduled task that runs once and stops.
@BukkitRunnable
void delayed() sche = 3s {
runcmd("CONSOLE", "say 3 秒后执行");
stop("delayed");
}
int main() {
start("delayed");
}
注意:start("delayed") 后 3 秒才触发,下次想再启动需要先 stop。上面代码里任务自己 stop 了,所以可以再次 start。
Note: after start("delayed"), it fires 3s later. To fire again, stop first. The code above stops itself, so re-start works.
什么时候可以用 sleep / When sleep Is Acceptable
唯一安全的使用场景是异步线程里——但 HimDSL 里你很少直接控制线程。
The only safe place is inside an async thread — rare in HimDSL.
实际建议:日常脚本里不要用 sleep。它带来的麻烦远大于便利。
Practical advice: avoid sleep in daily scripts. Its problems outweigh its convenience.
常见错误 / Common Mistakes
错误一:命令带了斜杠
runcmd("CONSOLE", "/say hello"); // ✗ 报错:未知命令 "/say"
去掉前导斜杠。
错误二:玩家名拼错
runcmd("Stev", "spawn"); // ✗ 静默失败
检查拼写,或先用 Java 互操作确认在线。
错误三:main 里 sleep
sleep(5000); // ✗ 卡服
用 @BukkitRunnable 替代。
Mistake 1: Leading slash
Drop it.
Mistake 2: Misspelled player name
Silent failure. Verify online first.
Mistake 3: sleep in main
Blocks the server. Use @BukkitRunnable.
小结 / Summary
-
runcmd(executor, command),命令不带斜杠。 -
"CONSOLE"或玩家名作为执行者。 -
玩家离线时命令静默丢弃。
-
命令在下一 tick 执行,异步派发。
-
sleep(ms)阻塞当前线程,main里不要用。 -
"等待后执行"用
@BukkitRunnable+ 状态变量。 -
日常脚本不要
sleep。 -
runcmd(executor, command); no leading slash. -
"CONSOLE"or a player name as executor. -
Offline players: command silently dropped.
-
Commands run next tick, async dispatch.
-
sleep(ms)blocks the thread; avoid inmain. -
"Wait then continue" via
@BukkitRunnable+ state variable. -
No
sleepin daily scripts.
内置函数部分回顾 / Built-ins Review
内置函数部分到此结束。六章覆盖了:数学、高精度、字符串速查、集合速查、文件 I/O、命令与 sleep。
The Built-ins section ends here. Six chapters: math, BigDecimal, string cheat sheet, collection cheat sheet, file I/O, commands and sleep.
关键约定:
Key conventions:
-
数学:多数返回
double,参数是弧度。 -
钱:用
big*,不用double。 -
字符串与集合:优先方法形式,别用函数形式。
-
文件:日常用
freadlines/fwritelines;追加用"a"模式。 -
命令:
runcmd不带斜杠。 -
sleep:日常脚本不要用。 -
Math: mostly returns
double; angles in radians. -
Money: use
big*, notdouble. -
Strings and collections: method form over function form.
-
Files:
freadlines/fwritelinesdaily;"a"for appends. -
Commands:
runcmdwithout slash. -
sleep: avoid in daily scripts.
下一步 / Next Steps
下一部分进入进阶。第十章 [反射与类解析 / Reflection] 讲 HimDSL 怎么定位 Java 类。
The next part covers Advanced. Chapter [反射与类解析 / Reflection] explains how HimDSL locates Java classes.