| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688 |
- #nop vim: set filetype=tt:;
- /*
- 本文件属于 PaoTin++ 的一部分。
- PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
- 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
- */
- #nop 本文件是 xtintin 的一部分,实现了一些实用命令。;
- ///=== {
- ///// 实用命令:
- //
- // ## clear
- // 清屏。类似于 DOS/Unix,也可以用 cls,作用相同。
- // };
- #alias {cls} {clear};
- #alias {clear} {
- #system {tput clear};
- tmux.SetTheme GAME;
- prompt.refresh;
- };
- ///=== {
- // ## exit
- // 退出客户端,但不退出游戏角色。也可以用 quit,作用相同。
- // 一些中文 MUD 服务器在接收到 quit 命令时会让角色从服务器上下线,
- // 这往往会导致玩家丢失背包里的物品。新手玩家常常因此懊恼万分。
- // 为了避免悲剧发生,这里特别映射一下,改成仅断开连接,而不退出服务器角色。
- // 如果玩家真的需要向服务器发送 quit 指令,请输入 #send quit。exit 同理。
- // };
- #alias {exit} {#end};
- #alias {quit} {#end};
- ///=== {
- // ## xtt.Tick <ID> <代码> <间隔时间> [<触发次数>]
- // 跟 #tick 功能类似,但是会立即执行一次代码。对于间隔时间比较长的定时器来说尤其有用。
- // 可选的触发次数会导致定时器在次数达到限制后自动销毁。省略此参数时将不限制触发次数。
- // 你也可以通过 Tick 别名来使用本别名。
- // };
- #alias {Tick} {xtt.Tick};
- #alias {xtt.Tick} {
- #local id {%1};
- #local code {%2};
- #local interval {%3};
- #local times {@defaultNum{%4;0}};
- #math times {$times - 1};
- #line sub var #untick {$id};
- #if { $times > 0 } {
- #line sub {var;escapes;functions} #line multishot {$times} #tick {$id} {$code} $interval;
- };
- #elseif { $times < 0 } {
- #line sub var #tick {$id} {$code} $interval;
- };
- #line sub {var;escapes;functions} $code;
- };
- ///=== {
- // ## xtt.ListTicker
- // 列出系统中所有的定时器。因为定时器一般不会很多因此暂时没有做过滤功能。
- // 你也可以通过 TICKS 别名来使用本别名。
- // };
- #alias {TICKS} {xtt.ListTicker};
- #alias {xtt.ListTicker} {
- #info tickers save;
- #echo {<128> %-30s %+20s %+10s %+20s} {所属模块} {定时器名称} {执行周期} {距离下次执行(s)};
- #draw Yellow scroll line 1 1 1 90;
- #format utime %U;
- #local index {};
- #loop {1} {&info[TICKERS][]} {index} {
- #local uval {};
- #math uval $info[TICKERS][+$index][arg3] * 1000000;
- #local name {$info[TICKERS][+$index][arg1]};
- #echo { %-30s %+20s %+10s %+20m}
- {@genModuleLink{$info[TICKERS][+$index][class];MOD}}
- {$name @mslp.Exec{{xtt.delTrigger tick $name};<119>✗<269>;false}}
- {$info[TICKERS][+$index][arg3]}
- {($uval - ($utime - $info[TICKERS][+$index][arg4]) % $uval) / 1000000.00};
- };
- };
- ///=== {
- // ## xtt.ListAlias [<正则表达式>]
- // 列出系统中符合条件的别名,如果省略条件则列出所有别名。
- // 一些不够规整的别名不会被列出。只有符合 PaoTin++ 规范的别名才会被列出。
- // 正则表达式会被运用到别名所属模块名称和别名名称上,两者符合其一即可被列出。
- // 你也可以通过 ALIS 别名来使用本别名。
- // };
- #alias {ALIS} {xtt.ListAlias};
- #alias {xtt.ListAlias} {
- #local pattern {%1};
- #info aliases save;
- #local aliasTable {};
- #local index {};
- #loop {1} {&info[ALIASES][]} {index} {
- #local name {$info[ALIASES][+$index][arg1]};
- #local class {$info[ALIASES][+$index][class]};
- #if { "$class" == "" && "$pattern" != "all" } {
- #continue;
- };
- #if { "$class" == "" } {
- #local class {未分组};
- };
- #if { "$name" == "%*{[^a-zA-Z0-9-_.]}%*" } {
- #continue;
- };
- #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
- #continue;
- };
- #list {aliasTable[$class]} sort {$name};
- };
- #local format { %-30s %-40s %-10s};
- #echo {<128>$format} {class} {别名} {类型};
- #draw Yellow scroll line 1 1 1 90;
- #local classList {@list.Sort{*aliasTable[]}};
- #local class {};
- #foreach {$classList} {class} {
- #local name {};
- #foreach {${aliasTable[$class][]}} {name} {
- #local type {<139>自定义<299>};
- #if { "$name" == "%*.{[A-Z][a-zA-Z0-9]+}" } {
- #local type {<129>开放API<299>};
- };
- #if { "$class" == "module-loader" } {
- #if { "$name" == "{[A-Z]+}" } {
- #local type {<169>快捷方式<299>};
- };
- #else {
- #local type {<229>语法增强<299>};
- }
- };
- #if { "${class}.$name" == "main.class.%*" } {
- #local type {<229>语法增强<299>};
- };
- #if { "${class}.$name" == "main.load-{file|config}" } {
- #local type {<229>语法增强<299>};
- };
- #if { "${class}.$name" == "main.%*Log" } {
- #local type {<129>日志接口<299>};
- };
- #if { "$pattern" == "" && "$type" == "%*自定义%*" } {
- #continue;
- };
- #echo {<060>$format}
- {@genModuleLink{$class;MOD}<060>}
- {@mslp.Exec{{xtt.delTrigger alias $name};<119>✗<269>;false} @linkToHelp{$class;$name}}
- {$type};
- };
- };
- };
- ///=== {
- // ## xtt.ListVar [<正则表达式>]
- // 列出系统中符合条件的变量,如果省略条件则列出所有变量。
- // 一些不够规整的变量不会被列出。只有符合 PaoTin++ 规范的变量才会被列出。
- // 正则表达式会被运用到变量所属模块名称和变量名称上,两者符合其一即可被列出。
- // 你也可以通过 VARS 别名来使用本别名。
- // };
- #alias {VARS} {xtt.ListVar};
- #alias {xtt.ListVar} {
- #local pattern {%1};
- #info variable save;
- #local varTable {};
- #local index {};
- #loop {1} {&info[VARIABLES][]} {index} {
- #local name {$info[VARIABLES][+$index][arg1]};
- #local class {$info[VARIABLES][+$index][class]};
- #local value {$info[VARIABLES][+$index][arg2]};
- #local nest {$info[VARIABLES][+$index][nest]};
- #if { "$class" == "" && "$pattern" != "all" } {
- #continue;
- };
- #if { "$class" == "" } {
- #local class {未分组};
- };
- #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
- #continue;
- };
- #local {varTable[$class][$name]} {
- {nest}{$nest}
- {value}{$value}
- };
- };
- #local format { %-35s %-30s %-10s %s};
- #echo {<128>$format} {class} {变量} {类型} {值};
- #draw Yellow scroll line 1 1 1 95;
- #local classList {@slist.Sort{*varTable[]}};
- #local class {};
- #foreach {$classList} {class} {
- #local name {};
- #local nameList {@slist.Sort{*varTable[$class][]}};
- #foreach {$nameList} {name} {
- #local type {<229>字符串<299>};
- #local value {<169>$varTable[$class][$name][value]<299>};
- #local nest {$varTable[$class][$name][nest]};
- #if { $nest > 0 } {
- #local type {<259>表格<299>};
- #local value {@mslp.Var{$name;<139>[... 共 $nest 项数据]<299>}};
- };
- #local showClass {$class};
- #replace showClass {^data/} {};
- #echo {<060>$format}
- {@genModuleLink{$showClass;MOD}<060>}
- {@mslp.Exec{{xtt.delTrigger var $name};<119>✗<269>;false} @linkToHelp{$showClass;$name}}
- {$type}
- {$value};
- #if { "$gPaoTinVars[$name]" != "" } {
- #echo {$format}
- {}
- { ╰── $gPaoTinVars[$name][cnName]}
- {}
- {};
- };
- };
- };
- };
- #alias {xtt.delTrigger} {
- #local type {%1};
- #local trigger {%2};
- #local cmd {#un$type {$trigger}};
- #replace cmd {\\} {};
- $cmd;
- };
- ///=== {
- // ## xtt.ListFunc [<正则表达式>]
- // 列出系统中符合条件的函数,如果省略条件则列出所有函数。
- // 正则表达式会被运用到函数所属模块名称和函数名称上,两者符合其一即可被列出。
- // 一些不够规整的函数不会被列出。只有符合 PaoTin++ 规范的函数才会被列出。
- // 你也可以通过 FUNCS 别名来使用本别名。
- // };
- #alias {FUNCS} {xtt.ListFunc};
- #alias {xtt.ListFunc} {
- #local pattern {%1};
- #info functions save;
- #local funcsTable {};
- #local index {};
- #loop {1} {&info[FUNCTIONS][]} {index} {
- #local name {$info[FUNCTIONS][+$index][arg1]};
- #local class {$info[FUNCTIONS][+$index][class]};
- #if { "$class" == "" && "$pattern" != "all" } {
- #continue;
- };
- #if { "$class" == "" } {
- #local class {未分组};
- };
- #if { "$name" == "%*{[^a-zA-Z0-9_./-]}%*" } {
- #continue;
- };
- #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
- #continue;
- };
- #list {funcsTable[$class]} sort {$name};
- };
- #local format { %-30s %-40s %-10s};
- #echo {<128>$format} {class} {函数} {类型};
- #draw Yellow scroll line 1 1 1 90;
- #local classList {@list.Sort{*funcsTable[]}};
- #local class {};
- #foreach {$classList} {class} {
- #local name {};
- #foreach {${funcsTable[$class][]}} {name} {
- #local type {<139>自定义<299>};
- #if { "$name" == "%*.{[A-Z][a-zA-Z0-9]+}" } {
- #local type {<129>开放API<299>};
- };
- #if { "$class" == "{lib/xtintin|main}" } {
- #local type {<229>语法增强<299>};
- };
- #if { "${class}.$name" == "main.%*Log" } {
- #local type {<129>日志接口<299>};
- };
- #if { "$pattern" == "" && "$type" == "%*自定义%*" } {
- #continue;
- };
- #echo {<060>$format}
- {@genModuleLink{$class;MOD}<060>}
- {@mslp.Exec{{xtt.delTrigger func $name};<119>✗<269>;false} @linkToHelp{$class;$name}}
- {$type};
- };
- };
- };
- ///=== {
- // ## xtt.ListAction [<正则表达式>]
- // 列出系统中符合条件的文本触发,如果省略条件则列出所有文本触发。
- // 正则表达式会被运用到文本触发所属模块名称和文本触发的条件上,两者符合其一即可被列出。
- // 你也可以通过 ACTS 别名来使用本别名。
- // };
- #alias {ACTS} {xtt.ListAction};
- #alias {xtt.ListAction} {
- #local pattern {%1};
- #info actions save;
- #local actionTable {};
- #local index {};
- #loop {1} {&info[ACTIONS][]} {index} {
- #local name {$info[ACTIONS][+$index][arg1]};
- #local class {$info[ACTIONS][+$index][class]};
- #if { "$class" == "" && "$pattern" != "all" } {
- #continue;
- };
- #if { "$class" == "" } {
- #local class {未分组};
- };
- #if { "$pattern" != "{|all}" && "$class/$name" != "%*$pattern%*" } {
- #continue;
- };
- #list {actionTable[$class]} sort {$name};
- };
- #local format { %-30s %-40s %-10s};
- #echo {<128>$format} {class} {文本触发};
- #draw Yellow scroll line 1 1 1 90;
- #local classList {@list.Sort{*actionTable[]}};
- #local class {};
- #foreach {$classList} {class} {
- #local name {};
- #foreach {${actionTable[$class][]}} {name} {
- #echo {<060>$format}
- {@genModuleLink{$class;MOD}<060>}
- {@mslp.Exec{{xtt.delTrigger action {$name}};<119>✗<269>;false} $name}
- };
- };
- };
- ///=== {
- // ## xtt.Var <变量中文含义> <变量名> <值>
- // 声明并初始化变量。和 #var 不同,如果该变量已存在,则不会修改它的值。
- // 另外,如果在模块中使用本方法,则声明的变量会自动存放在 #class data/$MODULE 中。
- // 这意味着即使你重新载入模块代码,也不会破坏该变量的值。
- // 因此建议将通过触发抓取到的任务进度信息用本方法存储,可以有效避免机器代码迭代
- // 开发过程中,丢失任务信息从而导致任务失败。
- //
- // 也可以通过短名称 VAR 来使用本命令,效果相同。
- // };
- #alias {VAR} {xtt.Var};
- #alias {xtt.Var} {
- #local cnName {%1};
- #local name {%2};
- #local value {%3};
- #if { @existsVar{$name} } {
- #return;
- };
- #if { @existsVar{MODULE} } {
- #class data/$MODULE open;
- #var {$name} {$value};
- #class data/$MODULE close;
- };
- #else {
- #var {$name} {$value};
- };
- #var gPaoTinVars[$name] {
- {name} {$name}
- {cnName} {$cnName}
- };
- };
- VAR {用 VAR 关键字定义的 PaoTin++ 变量清单,包含其中文含义} gPaoTinVars {};
- load-lib option;
- option.Define {DisableOutput} {Bool} {是否禁止向服务器发送命令} {false};
- ///=== {
- // ## xtt.Send <命令> [<参数> ...]
- // 向服务器发送命令。如果命令拦截总开关被打开,则不会真的向服务器发送。
- // };
- #alias {xtt.Send} {
- #if { @option.IsEnable{DisableOutput} } {
- #echo {<169>命令已被抑制: <429>%p<299>} {%0};
- #return;
- };
- #send %0;
- };
- ///=== {
- // ## xtt.SendAtOnce <分号分隔的命令序列>
- // 一次性向服务器发送多条命令。
- // 有的 MUD 服务器专门为这种方式开辟了通道,本方法可以使用这种通道。
- // TODO: 需要区分 MUD,需要支持定制的命令分隔符。
- // };
- #alias {xtt.SendAtOnce} {
- #local cmds {%1};
- xtt.Send {#$cmds#};
- };
- ///=== {
- // ## xtt.Answer <问题答复>
- // 如果游戏中有需要回答的问题,并且给出了特定的提示符(就是不带换行的文本),
- // 那么由于 TinTin++ 的某种机制,导致回答的内容和问题就会有重叠,不能正确显示。
- // 此时建议用 xtt.Answer 来回答此类问题。将会留下美观的 buffer 记录。
- // };
- #alias {xtt.Answer} {
- #delay 0 {
- #echo {};
- #buffer end;
- xtt.Send {%1};
- };
- };
- ///=== {
- // ## xtt.Stop <命令>
- // 暂时阻断某个命令的执行。
- // 某些基于触发的机器会周而复始地执行动作。本命令可以用来终止它的运行,并保留状态。
- // 例如新手机器人会循环执行 ask job/do/finish 流程,那么只需要输入 xtt.Stop ask,
- // 就可以在下一次 ask NPC 时,暂停机器执行,但并不影响机器状态。此时玩家可以手动
- // 操作角色,临时去做点别的,比如收个包袱之类的,然后回到房间,手动执行一次 ask 命令,
- // 就可以继续机器运行了。
- // };
- #alias {xtt.Stop} {
- #if { "%1" == "" } {
- xtt.Usage xtt.Stop;
- #return;
- };
- #line oneshot #alias {%1} {halt; #echo {<119>任务已暂停,请输入 <139>%1 %s <119>继续运行。<299>} {%%0}}
- };
- option.Define {DisableAllCommands} {Bool} {是否禁用所有的触发器和定时器} {false};
- ///=== {
- // ## xtt.DisableAllCommands
- // 禁止发送任何命令。
- // 某些游戏模式下,玩家必须小心地输入,否则一旦输错会造成损失。此时可以用本
- // 命令来禁止所有的触发、定时器、事件,防止误发命令。
- // 此时玩家只能用 #send {.....} 命令来发送命令。
- // 注意快捷键并不会被禁止,所以玩家可以通过快捷键来切换状态。
- // };
- #alias {xtt.DisableAllCommands} {
- #class disable-all-commands open;
- option.Enable DisableAllCommands;
- warnLog 所有定时器、触发器和事件句柄已被禁用。;
- warnLog 600 秒后自动解除该状态。;
- #alias {^%*{|ID=paotin/disable-all-commands}$} {
- #echo {<119>命令已被抑制,可用 <129>#send<119> 强制发送。撤销请用 <129>xtt.UndoDisableAllCommands<119> : <139>%s<299>} {%%0}
- } {1.001};
- #gts {#delay 600 {#ats xtt.UndoDisableAllCommands}};
- #line quiet #ignore actions on;
- #line quiet #ignore tickers on;
- #line quiet #ignore events on;
- #class disable-all-commands close;
- };
- ///=== {
- // ## xtt.UndoDisableAllCommands
- // 取消 xtt.DisableAllCommands 效果,恢复正常状态。
- // 参见 HELP xtt.DisableAllCommands
- // };
- #alias {xtt.UndoDisableAllCommands} {
- #class disable-all-commands kill;
- #line quiet #ignore actions off;
- #line quiet #ignore tickers off;
- #line quiet #ignore events off;
- okLog 命令已恢复正常。;
- option.Disable DisableAllCommands;
- } {1.000};
- ///=== {
- // ## xtt.ToggleDisableCommands
- // 在禁止和打开所有的定时器、触发器和事件句柄之间来回切换。
- // 本命令可用作绑定快捷键使用。
- // };
- #alias {xtt.ToggleDisableCommands} {
- #if { @option.IsEnable{DisableAllCommands} } {
- xtt.UndoDisableAllCommands;
- };
- #else {
- xtt.DisableAllCommands;
- };
- } {1.000};
- #func {linkToHelp} {
- #local module {%1};
- #local keyword {%2};
- #local text {$keyword};
- #local cmd {HELP $keyword};
- #if { "$keyword" == "" } {
- #local text {$module};
- #local keyword {MODULE};
- #local cmd {HELP $module};
- };
- #if { "$module" == "" } {
- #return {$text};
- };
- #if { &xtt.module-doc[$module][] == 0 } {
- #return {$text};
- };
- #if { &xtt.module-doc[$module][$keyword][] == 0 } {
- #return {$text};
- };
- #return {<149>@mslp.Exec{{$cmd};{$text}}<299>};
- };
- ///=== {
- // ## cli.SmartToggle
- // 命令行智能切换。
- // 出于方便起见,该命令实际上集成了三个作用,并推荐使用快捷键来调用本命令。
- // - 作用1: 当命令行尚未输入内容时,用来切换 PaoTin++ 的调试开关。
- // 调试开关开启时,玩家可以看到触发的执行细节,方便调试代码。
- // - 作用2: 当命令行输入了 #alias/#action 等 TinTin++ 可被取消的触发时,会
- // 自动修改成对应的 #unalias/#unaction 命令,利用这一点可以方便取
- // 消已有触发。可被取消的触发列表见下方完整清单。
- // - 作用3: 当命令行输入了其它命令时,会自动开启或关闭以调试方式执行该命令。
- // 该切换并不会影响全局调试开关。因此不会受到来自其它触发的干扰,
- // 内容更精准,方便查看。
- //
- // 作用2中可被取消的命令清单:
- // - 常用 TinTin++ 命令: action alias tick variable delay gag
- // - 不常用 TinTin++ 命令: button event function highlight macro pathdir
- // prompt substitute tab
- // 以上命令的 3 字母以上简写,无论大小写,都会被自动添加或者删除 un,
- // 以达到切换的目的。
- // - 常用的 PaoTin++ 命令: event.Handle/event.HandleOnce VS event.UnHandle
- // };
- #alias {cli.SmartToggle} {
- #local input {};
- #cursor get input;
- #line quiet #ignore function on;
- #if { {$input} == {} } {
- #line quiet #ignore function off;
- xtt.ToggleDebug;
- #return;
- };
- #if { {$input} == {#line debug %*} } {
- #replace input {^#line debug } {};
- };
- #else {
- #local cmds {act(|i(|o(|n)))|ali(|a(|s))|tic(|k(|e(|r)))
- |var(|i(|a(|b(|l(|e)))))
- |del(|a(|y))|gag|tab
- |but(|t(|o(|n)))|eve(|n(|t))
- |fun(|c(|t(|i(|o(|n)))))
- |hig(|h(|l(|i(|g(|h(|t))))))
- |mac(|r(|o))|pat(|h(|d(|i(|r))))
- |pro(|m(|p(|t)))
- |sub(|s(|t(|i(|t(|u(|t(|e)))))))};
- #replace cmds { } {};
- #if { {$input} == {{?i}#un{$cmds} %*} } {
- #replace input {{?i}#un} {#};
- };
- #elseif { {$input} == {{?i}#{$cmds} %*} } {
- #replace input {^#} {#un};
- };
- #elseif { {$input} == {{tt|}event.{Class|}Handle{|Once} %*} } {
- #replace input {^{tt|}event.{Class|}Handle{Once|}} {&1event.UnHandle};
- };
- #elseif { {$input} == {{tt|}event.UnHandle %*} } {
- #replace input {^{tt|}event.UnHandle} {&1event.Handle};
- };
- #else {
- #local input {#line debug $input};
- };
- };
- #cursor clear;
- #local cmd {
- #line quiet #ignore variable on;
- #line quiet #line sub escapes #cursor set {$input};
- #line quiet #ignore variable off;
- };
- $cmd;
- #line quiet #ignore function off;
- };
- ///=== {
- // ## xtt.Ping [<次数>]
- // 计算服务器延迟,输出以毫秒为单位的统计数据;
- // };
- #alias {PING} {xtt.Ping};
- #alias {xtt.Ping} {
- #class xtt.Ping open;
- #list xtt-ping-samples create {};
- #var xtt-ping-send-time {};
- #var xtt-ping-times {10};
- #alias {xtt.Ping.ping} {
- #if { $xtt-ping-times <= 0 } {
- xtt.Ping.done;
- #return;
- };
- #var xtt-ping-send-time {@str.Format{%U}};
- sync.Wait xtt.Ping.pong;
- };
- #alias {xtt.Ping.pong} {
- #math xtt-ping-times {$xtt-ping-times - 1};
- #list xtt-ping-samples add {@math.Eval{ @str.Format{%U} - $xtt-ping-send-time }};
- xtt.Ping.ping;
- };
- #alias {xtt.Ping.done} {
- #list xtt-ping-samples order;
- #list xtt-ping-samples delete -1;
- #list xtt-ping-samples delete 1;
- #local min {@math.Eval{ $xtt-ping-samples[1] / 1000 }};
- #local max {@math.Eval{ $xtt-ping-samples[-1] / 1000 }};
- #local avg {@math.Eval{ @math.Sum{$xtt-ping-samples[]} / &xtt-ping-samples[] / 1000 }};
- #class xtt.Ping kill;
- okLog 网络测速结果如右:最大值 $max 毫秒,最小值 $min 毫秒,平均值 $avg 毫秒;
- };
- #class xtt.Ping close;
- sync.Wait {xtt.Ping.ping};
- };
|