Start Stop - HimxhMC/HimDSL GitHub Wiki

start / stop

生命周期的概念 / Lifecycle

事件处理函数和定时任务都是长期运行的——它们定义之后一直等在那里,直到被触发。HimDSL 用 start 和 stop 控制它们的活跃状态。

Event handlers and scheduled tasks are long-running — after definition they wait until triggered. HimDSL uses start and stop to control their active state.

  • 未启动:定义了但不生效。

  • 已启动:可被事件或调度触发。

  • 已停止:和未启动一样,不再被触发。

  • Not started: defined but inactive.

  • Started: triggers fire.

  • Stopped: inactive again.


start:启动 / start: Activate

start("函数名");

参数是函数名的字符串。这与调用普通函数不同——普通函数写 foo(),这里写 start("foo")。

The argument is the function name as a string — unlike ordinary calls (foo()), you write start("foo").

@EventHandler
void onJoin(event(PlayerJoinEvent)) { ... }

@BukkitRunnable
void tick() sche = 10s { ... }

int main() {
    start("onJoin");
    start("tick");
}

start 是幂等的吗? 不是。启动一个已经在运行的任务会报错:

Is start idempotent? No — starting an already-running task errors:

start("tick");
start("tick");      // ✗ 报错:已启用

先 stop 再 start 可以重新启动。

stop then start restarts.


stop:停止 / stop: Deactivate

stop("函数名");

停止后不再被触发,但函数定义依然存在——可以再次 start。

After stopping, no more triggers, but the definition remains — start again to resume.

@BukkitRunnable
void tick() sche = 10s { ... }

int main() {
    start("tick");

    // 后面某处
    if (someCondition) {
        stop("tick");
    }
}

停止一个未启动的任务会报错。

Stopping a non-started task errors.


常见用法 / Common Patterns

条件启动 / Conditional Start

启动由脚本自身决定。可以根据环境、时间、配置选择要不要启动:

Start is decided by the script itself — based on environment, time, or config:

int main() {
    var players = @a;
    if (players.size() > 0) {
        start("onJoin");
        runcmd("CONSOLE", "say 已在服务器有人时启动监听");
    }
}

临时任务 / Temporary Tasks

定时任务可以执行完自己停:

A scheduled task can stop itself:

int counter;

@BukkitRunnable
void countdown() sche = 1s {
    counter += 1;
    runcmd("CONSOLE", "say 倒计时 " + (10 - counter));

    if (counter >= 10) {
        stop("countdown");
        runcmd("CONSOLE", "say 倒计时结束");
        counter = 0;
    }
}

int main() {
    counter = 0;
    start("countdown");
}

stop("countdown") 在任务自己内部调用是合法的,会停止后续触发。

Calling stop("countdown") inside the task itself is valid and stops further firing.

运行控制 / Runtime Toggle

一个常驻的监听器控制另一个任务:

A long-lived listener toggles another task:

bool fastMode = false;

@BukkitRunnable
void slowTick() sche = 30s {
    runcmd("CONSOLE", "say 慢速检查");
}

@BukkitRunnable
void fastTick() sche = 5s {
    runcmd("CONSOLE", "say 快速检查");
}

@EventHandler
void onCommand(event(PlayerCommandPreprocessEvent)) {
    player p = @s;
    string cmd = event.getMessage();

    if (cmd.equalsIgnoreCase("/fastmode on")) {
        if (!fastMode) {
            stop("slowTick");
            start("fastTick");
            fastMode = true;
            runcmd(p.name, "msg 快速模式已开启");
        }
    }
}

int main() {
    start("slowTick");
    start("onCommand");
}

重启脚本时的行为 / Behavior on Script Reload

脚本重载时(重新执行 /himdsl run),之前启动的事件和任务会先被清理,然后新版本重新执行。这意味着:

When a script reloads (running /himdsl run again), previously started events and tasks are cleared first, then the new version runs:

  • 不需要手动 stop 旧的任务。

  • 变量状态会丢失——counter 之类的计数会重置。

  • 数据持久化要靠文件(fwritelines / freadlines)。

  • No manual stop needed for old tasks.

  • Variable state is lost — counters reset.

  • Persist data through files (fwritelines / freadlines).

如果你想保留状态,把状态写进文件,脚本启动时读回。

To keep state across restarts, save to a file and load it at startup.


函数重载与 start / Overloading and start

start 要求函数唯一。如果脚本里有多个同名函数(重载),start 会报"存在重载,无法启动"。

start requires a unique function. With overloaded names, start errors.

void tick() { ... }
void tick(int n) { ... }

int main() {
    start("tick");       // ✗ 有重载
}

事件函数和定时任务不要重载。给它们取独特的名字。

Do not overload event handlers or scheduled tasks. Give them unique names.


小结 / Summary

  • start("name") 启动,stop("name") 停止。

  • 参数是函数名的字符串。

  • 启动已启动的、停止未启动的,都会报错。

  • 任务可以自己 stop 自己。

  • 脚本重载会清理所有事件和任务,变量状态丢失。

  • 状态持久化用文件。

  • 事件和任务函数不要重载。

  • start("name") / stop("name").

  • Argument is a function name as a string.

  • Starting already-started or stopping non-started errors.

  • Tasks can stop themselves.

  • Reload clears tasks; variable state is lost.

  • Persist via files.

  • Do not overload event/task functions.


事件与调度部分回顾 / Events & Scheduling Review

事件与调度部分到此结束。五章覆盖了:@EventHandler 注解、事件类型解析、EventWrapper 数据访问、@BukkitRunnable 定时任务、start / stop 生命周期。

The Events & Scheduling section ends here. Five chapters covered: @EventHandler, event type resolution, EventWrapper, @BukkitRunnable, and start / stop.

选择原则:

Decision guide:

  • 响应玩家动作 → @EventHandler。

  • 周期性工作 → @BukkitRunnable + sche。

  • 一次性延迟 → @BukkitRunnable 不带 sche。

  • 启动/停止 → 用 start / stop,不要指望脚本重载自动管理。

  • React to player actions → @EventHandler.

  • Periodic work → @BukkitRunnable with sche.

  • One-shot delay → @BukkitRunnable without sche.

  • Lifecycle → start / stop, not reload-based automation.


下一步 / Next Steps

下一部分进入 GUI 系统。第十章 [创建 GUI / Creating-GUI] 从 new GUI(rows, title) 开始。

The next part covers the GUI system. Chapter [创建 GUI / Creating-GUI] starts with new GUI(rows, title).