Auto Scripts - HimxhMC/HimDSL GitHub Wiki

自动执行脚本 / Auto-run Scripts

两个约定文件 / Two Convention Files

上一章的脚本都需要你手动执行 /himdsl run。但如果一件事需要在每次服务器启动时做,每次都手动敲命令显然不现实。HimDSL 为此提供了两个约定文件:

  • onServerLoad.himdsl —— 服务器加载完成时自动执行。
  • onServerShutdown.himdsl —— 插件卸载或服务器关闭时自动执行。

The previous chapter's scripts all required you to run /himdsl run manually. But if something needs to happen on every server start, typing a command each time is unrealistic. HimDSL provides two convention files for this:

  • onServerLoad.himdsl — runs when the server finishes loading.
  • onServerShutdown.himdsl — runs on plugin unload or server shutdown.

只要你在 plugins/HimDSL/ 目录下创建了这两个文件,插件就会在对应时机自动运行。文件名和大小写必须完全一致,否则会被忽略。

As long as you create these files under plugins/HimDSL/, the plugin runs them at the corresponding moments. File names are case-sensitive; anything else is ignored.


onServerLoad / 启动后执行

onServerLoad.himdsl 在 ServerLoadEvent 触发时运行。这个时机意味着:

  • 所有插件都已启用。
  • 所有世界都已加载。
  • 玩家可能已经连接。

onServerLoad.himdsl runs when ServerLoadEvent fires. That moment means:

  • Every plugin is enabled.
  • Every world is loaded.
  • Players may already be connected.

这是做全局初始化最理想的时机。常见用法:注册事件监听、启动定时任务、加载配置数据、广播欢迎消息。

It is the ideal moment for global initialization. Common uses: register event listeners, start scheduled tasks, load configuration data, broadcast welcome messages.

一个最小示例:

A minimal example:

int main() {
    runcmd("CONSOLE", "say §a服务器已就绪。");
}

把这段保存为 plugins/HimDSL/onServerLoad.himdsl,重启服务器,你会在启动完成后看到广播。

Save this as plugins/HimDSL/onServerLoad.himdsl, restart the server, and you will see the broadcast after startup.


onServerShutdown / 关闭前执行

onServerShutdown.himdsl 在插件卸载或服务器关闭时运行。这个时机适合做清理:

  • 保存运行时状态到文件。
  • 通知玩家即将关闭。
  • 停止正在运行的定时任务。

onServerShutdown.himdsl runs during plugin unload or server shutdown. Suitable for cleanup:

  • Save runtime state to files.
  • Notify players of the impending shutdown.
  • Stop any running scheduled tasks.
int main() {
    runcmd("CONSOLE", "say §c服务器即将关闭,感谢游玩。");
}

值得注意的是,这个时机做的事情应该尽量快。如果关闭脚本运行时间过长,服务器的关停流程会被拖慢。避免在这里写复杂逻辑或长循环。

Keep this script fast. If it takes too long, the server shutdown sequence is delayed. Avoid complex logic or long loops here.


静默执行 / Silent Execution

这两个自动脚本有一套特殊的行为:成功时没有任何额外日志,失败时只写一条警告,不会中断服务器生命周期。

These auto scripts have special behavior: no extra log on success, only a warning on failure, without interrupting the server lifecycle.

这意味着两个事情。第一,你的初始化脚本即使有 bug,服务器也不会因为 HimDSL 而启动失败——这很安全。第二,你不能靠"服务器起来了吗"来判断脚本是否成功,必须主动查看日志。

This means two things. First, even if your initialization script has a bug, the server will not fail to start because of HimDSL — that's safe. Second, you cannot judge success by "did the server come up"; you must read the logs.

开发阶段建议打开详细日志:

During development, enable verbose logging:

/himdsl debug on

重启服务器后,控制台会告诉你脚本是否被找到、是否执行成功、执行耗时等信息。确认脚本稳定后,可以关掉调试。

After a restart, the console tells you whether the script was found, executed successfully, and how long it took. Once the script is stable, turn debug off.


典型场景 / Typical Scenarios

场景一:启动时广播 / Scenario 1: Startup Broadcast

服务器每次重启后向所有玩家打招呼。

Greet every player each time the server restarts.

int main() {
    var players = @a;
    int total = players.size();
    for (int i = 0; i < total; i = i + 1) {
        var p = players.get(i);
        string who = p.name;
        runcmd("CONSOLE", "say §e欢迎回来," + who + "!");
    }
}

留意这里读取玩家名的方式:p.name。在上一章的示例里,我们用的是 $player(p, name)$;两种写法效果完全相同,p.name 更短。本章之后,示例会更多地使用后一种写法。

Note how the player name is read here: p.name. In the previous chapter we used $player(p, name)$; both do the same thing, and p.name is shorter. From this chapter on, examples lean toward the latter.

场景二:写入启动时间 / Scenario 2: Write Startup Time

把启动时间记录到一个文件,方便以后排查。

Record the startup time to a file for later reference.

int main() {
    string t = $server(tps)$;
    fwritelines("startup.log", {"startup ok, tps=" + t});
}

fwritelines 会把一个字符串列表逐行写入文件,路径相对于 plugins/HimDSL/。

fwritelines writes a list of strings to a file line by line, with the path relative to plugins/HimDSL/.

场景三:清理临时数据 / Scenario 3: Clean Temp Data

关闭前删除一个临时文件。

Delete a temporary file before shutdown.

int main() {
    if (fexists("temp_cache.txt")) {
        fdelete("temp_cache.txt");
    }
}

一个提示 / A Tip

自动脚本里最常见的错误是忘记把文件名拼对。onserverload.himdsl(小写 s)不会被识别。建议直接从本章复制文件名,或者先手动 /himdsl compile onServerLoad.himdsl 确认文件确实存在。

The most common mistake with auto scripts is a wrong filename. onserverload.himdsl (lowercase s) is not recognized. Copy the filename directly from this chapter, or run /himdsl compile onServerLoad.himdsl to confirm the file exists.


小结 / Summary

  • onServerLoad.himdsl 在服务器加载完成时运行。

  • onServerShutdown.himdsl 在插件卸载或服务器关闭时运行。

  • 两者都以 main 作为入口,写法与普通脚本相同。

  • 执行是静默的,成功无日志,失败只有警告。

  • 关机脚本要尽量快。

  • onServerLoad.himdsl runs after the server finishes loading.

  • onServerShutdown.himdsl runs on plugin unload or server shutdown.

  • Both use main as the entry point, same as ordinary scripts.

  • Execution is silent: no log on success, a warning on failure.

  • Keep the shutdown script fast.


下一步 / Next Steps

到这里,"入门"部分结束了。你已经能装插件、写脚本、传参数、设自动执行。下一部分开始系统讲解语言本身。请翻到 [词法结构 / Lexical-Structure],我们从注释、字面量、标识符这些最小的单位讲起。

That wraps up the "Getting Started" part. You can now install the plugin, write scripts, pass arguments, and set up auto-run. The next part introduces the language itself. Turn to [词法结构 / Lexical-Structure], starting from the smallest units: comments, literals, and identifiers.