运行机制
任务类型软件包由助手内置的任务调度器驱动。理解下面几个约定,就能写出正确的任务。
任务入口的三个约定
任务根目录的 index.lua 需要定义:
| 名称 | 类型 | 必需 | 说明 |
|---|---|---|---|
CheckTime | number | ✅ | 检查间隔,单位毫秒 |
Check() | function | ✅ | 每次间隔被调用,返回数字决定是否执行 Main |
Main() | function | ✅ | 真正执行的逻辑 |
OnStart() | function | 每次任务开始执行前调用一次 | |
OnStop() | function | 保留字段,当前版本不会自动调用 |
最小骨架:
apps/黑猫@我的任务/index.lua
-- 每 1000 毫秒检查一次
CheckTime = 1000
-- 返回 0 表示继续等待;返回非 0 表示可以执行 Main
function Check()
return 1
end
function Main()
GoPrint("Main 开始执行")
-- 你的逻辑……
end
完整的执行流程
当用户启动任务,或任务被 AddTask 调入后,调度器会:
-
加载软件包
- 解析
.hm.json。 - 把依赖的函数库的
inject/脚本注入到游戏客户端。 - 加载根目录的
index.lua,并配置require搜索路径。 - 注册内置全局函数(
Delay、Exit,以及 VM 全局函数)。
- 解析
-
准备本次运行
- 读取当前任务的配置并写入全局变量
CurrentSettings。 - 如果定义了
OnStart(),调用一次。 - 读取全局变量
CheckTime(必须是数字,否则任务报错终止)。
- 读取当前任务的配置并写入全局变量
-
循环调度
┌──────────────────────────────────────────────┐│ 每 CheckTime 毫秒调用一次 Check() ││ Check() == 0 → 继续等待 ││ Check() ~= 0 → 跳出内层循环 │└──────────────────────────────────────────────┘│▼调用一次 Main()│▼回到上面的循环继续也就是说:
Check()是「是否该干活」的轮询,Main()是「干活」本身。Main()返回后会再次进入轮询,不会自动退出任务。
备注
CheckTime 只在每次任务开始时读取一次。运行期间修改它不会生效,需要停止后重新启动任务。
Check 的返回值:是否抢占
Check() 的返回值有两种含义:
0:条件不满足,继续等待。- 非
0:条件满足,执行Main()。其中:- 返回
1:执行Main()的同时抢占,即暂停优先级更低的任务; - 返回其它非
0值(如2):执行Main(),但不抢占其它任务。
- 返回
当多个任务同时运行时,任务调度器会根据优先级与抢占状态决定谁在运行。若你只是想让任务
持续工作而不打扰其它任务,返回一个非 1 的非零值即可。
Delay 与 Exit
两个内置函数控制任务的时间与生命周期:
-- 暂停指定毫秒数(会主动让出执行权)
Delay(500)
-- 立即停止当前任务
Exit()
Delay(ms)在等待期间如果任务被停止,会抛出内部的退出信号,任务随即结束,不会继续往下执行。Exit()用于在逻辑内部主动结束自己,等同于用户点击「停止」。
CurrentSettings:任务配置
任务被启动时,助手会把该任务已保存的配置写入全局变量 CurrentSettings(一个 table)。
它来自用户在界面上提交的配置,按「角色 + 任务名」持久化。
function Main()
local settings = CurrentSettings
if settings.fixedPointEnable then
-- 使用了界面上的「定点挂机」复选框
end
end
注意
CurrentSettings 是启动时的快照。在任务运行过程中修改它不会写回存储;
需要持久化时请使用 SetRoleSettings(见 VM 全局函数),
或让用户通过界面重新提交配置。
同名任务与重启
重复添加一个已经在运行的任务,会先停止旧任务再创建新的,相当于「重启」。
任务停止时,正在 Delay 中的调用会被中断。
下一步:动手写 你的第一个软件包。