Debugging - HimxhMC/HimDSL GitHub Wiki
调试技巧 / Debugging
打开调试 / Enabling Debug
HimDSL 有两个调试开关:
Two debug switches:
/himdsl debug on
/himdsl debug codeon
-
on—— 打开详细日志:脚本解析、函数收集、执行流程都会打印。 -
codeon—— 每次run前,把脚本内容完整打印到控制台。 -
on— verbose logs: parsing, function collection, execution flow. -
codeon— prints the full script text before eachrun.
关掉:
Turn off:
/himdsl debug off
/himdsl debug codeoff
重启服务器会重置为关闭状态,不持久化。
Server restart resets them to off. Not persisted.
什么时机用哪个 / When to Use Which
debug on 用于:逻辑不对
debug on for: wrong behavior
脚本能运行但结果不对时。日志会显示每一步变量值、函数调用、分支选择。用来追"为什么这里走了 else 分支"这类问题。
Script runs but produces wrong results. Logs show variable values, function calls, branch choices. Use for "why did this go to else".
debug codeon 用于:脚本内容对不上
debug codeon for: mismatch between intent and file
改了脚本但行为没变——往往是因为 /himdsl run 执行的是另一个文件。codeon 会把当前脚本原文打印出来,对照你改的内容是否一致。
Changed the script but behavior did not — usually running the wrong file. codeon prints the actual text, so you can compare.
日常建议:始终打开 debug on。日志不会影响性能太多,出错时省时间。
Daily advice: keep debug on. Logs barely affect performance, save time when things break.
常见错误信息 / Common Error Messages
语法类
| 信息 | 原因 |
|---|---|
语法错误: ... |
缺少分号、括号不匹配等 |
token recognition error |
非法字符,例如中文标识符、不支持的语法 |
编译阶段错误(compile 命令),脚本未运行。
Parse-time errors (from compile); the script never runs.
运行类
| 信息 | 原因 |
|---|---|
变量 X 未定义 |
用了未声明的变量 |
字段不存在: X |
访问不存在的字段 |
未定义函数: X |
调用未注册的函数 |
选择器 @x 没有匹配到任何实体 |
玩家/实体不存在 |
Entity 字段 X 是只读的 |
试图给引用字段赋值 |
未知事件类型: X |
event(X) 里的事件名错误 |
函数 X 存在重载 |
start 或 stop 用在了重载函数上 |
运行阶段错误,脚本中途停止。
Runtime errors; the script aborts mid-run.
静默失败
有些错误不会报错:
Some failures are silent:
runcmd目标玩家离线 → 命令丢弃。$player(p, naem)$拼错占位符名 → 返回null。papi("unknown")→ 返回""。- 选择器匹配到空列表 → 空列表参与后续逻辑,可能"看起来像没发生"。
这些都靠不住。用显式检查:
Do not rely on silence. Check explicitly:
if (p != null) {
runcmd(p.name, "spawn");
}
找问题的常用手法 / Common Approaches
用 say 打印中间值
在关键位置插入 runcmd("CONSOLE", "say ..."),把变量值打出来:
Insert runcmd("CONSOLE", "say ...") at key points to print variable values:
var p = @p;
runcmd("CONSOLE", "say [DEBUG] p = " + p);
if (p != null) {
runcmd("CONSOLE", "say [DEBUG] hp = " + p.health);
}
加 [DEBUG] 前缀,方便日志搜索和清理。
Prefix with [DEBUG] for easy grep and cleanup.
用 fexists 排除"文件不存在"
runcmd("CONSOLE", "say 文件存在: " + fexists("data.txt"));
很多"数据没了"的问题源于文件路径错了。
Many "data vanished" issues are wrong file paths.
二分排查
脚本很长时,注释掉后半段先跑前半段:
For long scripts, comment out the latter half and run the first:
int main() {
// 前半段
runcmd("CONSOLE", "say step 1");
// 后半段——先注释掉
/*
runcmd("CONSOLE", "say step 2");
*/
}
逐步放开,找到出问题的位置。
Uncomment incrementally to locate the failure.
检查返回值
任何可能返回 null 或空值的调用都要检查:
Check every call that may return null or empty:
var p = @p;
if (p == null) {
runcmd("CONSOLE", "say 没有在线玩家");
return;
}
var lines = freadlines("data.txt");
if (lines.size() == 0) {
runcmd("CONSOLE", "say 文件为空");
return;
}
控制台日志的读法 / Reading the Console Log
HimDSL 的日志格式:
HimDSL's log format:
[HH:MM:SS] [Server thread/INFO]: [HimDSL] ...
[HH:MM:SS] [Server thread/ERROR]: [HimDSL] 执行错误: ...
关键信息:
Key fields:
-
线程:
Server thread是主线程;Async开头是异步。 -
级别:
INFO是信息;WARN/ERROR是问题。 -
堆栈:出错时有堆栈跟踪,看第一行
Caused by——真正的根源。 -
Thread:
Server threadis main;Async...is async. -
Level:
INFO/WARN/ERROR. -
Stack trace: check the first
Caused byfor the real cause.
长期调试建议 / Long-Term Tips
保持 debug on
服务器启动后立刻执行一次:
Run once after server start:
/himdsl debug on
后续 run 都有详细日志。调试完再关。
Detailed logs for later runs. Turn off when done.
用命名清晰的变量
int x = 5; // 不知道是什么
int maxLevel = 5; // 一眼看懂
日志里的变量名 = 代码里的变量名。命名清晰,日志自然好用。
Logs show variable names; clear names make logs readable.
关键操作写日志到文件
重要事件(发奖、扣费、状态切换)写进文件,方便事后查:
Important events (rewards, charges, state changes) to a file for post-mortem:
int f = fopen("actions.log", "a");
fwrite(f, "grant " + p.name + " diamond 1 at " + $server(tps)$ + "\n");
fclose(f);
不要用 fwritelines——它会覆盖文件。追加用 fopen(..., "a")。
Do not use fwritelines — it overwrites. Use fopen(..., "a").
拆分脚本
一个脚本只做一件事。100 行的脚本容易读、容易调、容易改。500 行的脚本终会变成负担。
One script, one purpose. 100-line scripts are easy to read and change. 500-line scripts become a liability.
小结 / Summary
-
debug on打印详细流程;debug codeon打印脚本原文。 -
重启后开关重置。
-
语法错误在
compile阶段报;运行错误在执行阶段报。 -
有些错误静默——
runcmd玩家离线、占位符拼错。 -
排查手法:
say打印、fexists检查、二分注释。 -
日志看线程、级别、第一行
Caused by。 -
保持
debug on;命名清晰;重要日志写文件。 -
拆分脚本,一个脚本只做一件事。
-
debug onfor verbose flow;debug codeonfor script text. -
Switches reset on restart.
-
Parse errors at
compile; runtime errors at execution. -
Some failures are silent — offline
runcmdtargets, placeholder typos. -
Approaches:
sayprints,fexistschecks, binary search with comments. -
Logs: check thread, level, first
Caused by. -
Keep
debug on; name things clearly; log important actions to files. -
Split scripts — one script, one purpose.
下一步 / Next Steps
下一章 [常见陷阱 / Pitfalls] 汇总所有踩坑点,作为最后的速查。
Next, [常见陷阱 / Pitfalls] aggregates all traps as a final reference.