Repository navigation
Debugging
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.
脚本能运行但结果不对时。日志会显示每一步变量值、函数调用、分支选择。用来追"为什么这里走了 else 分支"这类问题。
Script runs but produces wrong results. Logs show variable values, function calls, branch choices. Use for "why did this go to else".
改了脚本但行为没变——往往是因为 /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.
| 信息 | 原因 |
|---|---|
语法错误: ... |
缺少分号、括号不匹配等 |
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");
}
在关键位置插入 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.
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;
}
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.
服务器启动后立刻执行一次:
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.
-
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.
下一章 [常见陷阱 / Pitfalls] 汇总所有踩坑点,作为最后的速查。
Next, [常见陷阱 / Pitfalls] aggregates all traps as a final reference.
- 首页 / 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