Selaa lähdekoodia

feat: 为新用户提供指引,引导用户创建启动配置文件

dzp 2 vuotta sitten
vanhempi
sitoutus
6c000af989
15 muutettua tiedostoa jossa 396 lisäystä ja 79 poistoa
  1. 22 11
      HOW-TO-PLAY.md
  2. 11 1
      bin/doc
  3. 15 0
      bin/start
  4. 3 5
      bin/start-ui
  5. 10 2
      docs/DIRECTORY.md
  6. 32 0
      docs/tmux.md
  7. 9 1
      framework/log.tin
  8. 22 12
      framework/main.tin
  9. 2 1
      ids/EXAMPLE
  10. 0 0
      ids/paotin
  11. 38 0
      ids/pkuxkx
  12. 5 3
      ids/thuxyj
  13. 6 0
      init.tin
  14. 88 3
      mud/pkuxkx/plugins/basic/login.tin
  15. 133 40
      mud/thuxyj/plugins/basic/login.tin

+ 22 - 11
HOW-TO-PLAY.md

@@ -1,20 +1,31 @@
-## 如何开始
+## 这是哪里?
 
-你现在就可以输入 `tt++` 来启动 TinTin++
+你现在看到的这个画面,是 bash 命令行。没错,你还没有进入游戏,还没有真正启动客户端
 
-或者你如果已经准备好了启动配置文件的话,也可以直接输入 `start <你的ID>` 来启动。
-如果你还没有准备好启动配置文件,可以参考 `ids/EXAMPLE` 文件写一个。
+## 那么我该如何开始?
 
-```
-# cp ids/EXAMPLE ids/myid   # Docker 环境下用: cp ids/EXAMPLE var/ids/myid
-# vi ids/myid               # Docker 环境下用: vi var/ids/myid
-```
+朋友,听我说,先别急着动手,把这十几行文字看完。有几个重要的命令你需要记一下。
 
-## 了解目录结构
+你可以输入 `start <游戏名称>` 来进入某个游戏:
+  - 输入 `start pkuxkx` 可以连接北大侠客行。
+  - 输入 `start thuxyj` 可以连接清华西游记。
+  - 输入 `start paotin` 可以进入 PaoTin++ 学习环境,而不用连接任何游戏。
+  - 输入 `start tintin` 可以进入 TinTin++ 环境。如果你之前没有接触过 TinTin++,请忽略这条。
+
+## 怎么自动登录游戏?
+
+如果你已经准备好了启动配置文件的话,也可以直接输入 `start <你的ID>` 来启动,例如 `start dzp`。
+如果你还没有准备好启动配置文件,你可以用前面的方法先手动登录,然后 PaoTin++ 会自动为你
+生成启动配置文件,下次你就可以用 `start <你的ID>` 自动登录了。
+
+启动配置文件统一存放在 `ids/` 目录下,但如果存在 `var/ids/` 目录,则会在那里。
+
+## 几点忠告
 
 建议先了解一下本客户端的目录结构,以及主要文件的作用和位置,搞清楚有哪些需要你
 配合修改的地方。请输入 `doc docs/DIRECTORY.md` 来了解客户端的目录结构。
 
-## 再次查看本说明
+任何时候,只要你是在 bash 命令行下,你都可以通过输入 `doc` 命令来再次查看本说明。
+如果你不确定自己是不是在 bash 命令行下,请多输入几次 `#end` 然后回车。
 
-任何时候你都可以通过输入 `doc HOW-TO-PLAY.md` 来再次查看本说明。
+交流 QQ 群: 951665549 入群暗号:「PaoTin++ 新用户」

+ 11 - 1
bin/doc

@@ -1,4 +1,14 @@
-cat $1 \
+#!/bin/sh
+
+DOC_FILE=$1
+
+if [ "x$DOC_FILE" = "x" ]; then
+    DOC_FILE=HOW-TO-PLAY
+fi
+
+DOC_FILE=${DOC_FILE%%.md}.md
+
+cat $DOC_FILE \
 | sed '/^```/,/^```/s/^//'            \
 | sed '/^\[32m```$/d'                     \
 | sed 's/^\(##* .*\)$/\1/'     \

+ 15 - 0
bin/start

@@ -15,6 +15,17 @@ if [ "x$START_FILE" = "x" ]; then
     exit
 fi
 
+if [ "x$START_FILE" = "xtintin" ]; then
+    tt++ -G -r init.tin
+    clear; doc
+    exit
+fi
+
+NEWBIE=false
+if [ "x$START_FILE" = "xpkuxkx" -o "x$START_FILE" = "xthuxyj" ]; then
+    NEWBIE=true
+fi
+
 if [ ! -z $(which tt-beta 2>/dev/null) ]; then
     TT=tt-beta
 elif [ ! -z $(which tt++ 2>/dev/null) ]; then
@@ -65,3 +76,7 @@ while [ "$CODE" -ne "0" ]; do
 done
 
 log "TinTin++ 正常退出,exit code = $CODE"
+
+if [ "$NEWBIE" = "true" ]; then
+    clear; doc
+fi

+ 3 - 5
bin/start-ui

@@ -22,12 +22,10 @@ function create-ui() {
     # 创建一个标准会话
     $TMUXCMD new-session -d -s $SESSION
     $TMUXCMD new-window     -t $SESSION
-    $TMUXCMD select-window  -t $SESSION:0
-    $TMUXCMD split-window   -t $SESSION -vb
-    $TMUXCMD send-keys      -t $SESSION 'clear; echo "You could input \"mtail id\" to watch your game log."; mtail'
+    $TMUXCMD send-keys      -t $SESSION "sleep 1; clear; doc docs/tmux.md"
     $TMUXCMD send-keys      -t $SESSION Enter
-    $TMUXCMD last-pane
-    $TMUXCMD send-keys      -t $SESSION "sleep 0.1; tmux resize-pane -y $HEIGHT; clear; doc HOW-TO-PLAY.md"
+    $TMUXCMD select-window  -t $SESSION:0
+    $TMUXCMD send-keys      -t $SESSION "sleep 0.5; clear; doc HOW-TO-PLAY.md"
     $TMUXCMD send-keys      -t $SESSION Enter
 
     echo UI 已创建。

+ 10 - 2
docs/DIRECTORY.md

@@ -3,28 +3,36 @@
 ```
 > tree -L 2
 .
-├── HOW-TO-PLAY.md      -- 简要说明文件
+├── HOW-TO-PLAY.md      -- 简要说明,新手指引文件
 ├── bin
 │   ├── start-ui        -- 启动游戏环境(第一步,如果是 Docker 环境则已执行过了)
 │   ├── start           -- 启动游戏账号(第二步)
 │   ├── doc             -- markdown 文档查看工具。如果显示异常,请用 cat 代替。
+│   ├── mtail           -- 日志查看工具
 │   └── tt++            -- tintin++ 主程序
 ├── docs
+│   ├── tmux.md         -- PaoTin++ 快捷键说明
 │   └── DIRECTORY.md    -- 本文件
 ├── etc                 -- 客户端配置文件目录(跨 ID 共享)
 ├── data                -- 客户端数据文件目录(跨 ID 共享)
 ├── framework           -- 主框架程序,不建议修改
 ├── ids                 -- 启动配置文件存放目录。建议以 ID 命名,不同 ID 不同文件
 │   ├── DEFAULT         -- 所有 ID 的默认配置,可以在启动配置文件里定制
+│   ├── pkuxkx          -- 连接北大侠客行游戏服务器
+│   ├── thuxyj          -- 连接清华西游记游戏服务器
+│   ├── paotin          -- 启动 PaoTin++ 学习环境
 │   └── EXAMPLE         -- 一个启动配置文件的例子
 ├── log                 -- 日志存放目录
 ├── plugins             -- 插件存放目录
 │   ├── lib             -- 基础插件
 │   ├── basic           -- 基本插件
+│   ├── job             -- 任务插件目录
+│   ├── bot             -- 常用机器人目录
+│   ├── quest           -- 一些小任务或者解密文件
 │   └── shortcut.tin    -- 其它插件
 └── var                 -- Docker 环境下用作本地存储用的挂载目录
     ├── ids             -- 本地启动配置文件
     ├── etc             -- 本地配置
     ├── log             -- 本地日志
-    └── plugins         -- 本地插件目录
+    └── plugins         -- 本地插件目录,其内部结构和上面的 plugins 相同
 ```

+ 32 - 0
docs/tmux.md

@@ -0,0 +1,32 @@
+## 什么是 tmux?
+
+tmux 是一个先进的终端复用器,非常有用。
+PaoTin++ 用它来管理 UI,切分屏幕,创建多窗口画面,同时挂机多个 ID。
+
+简单入门建议看这篇博文: https://www.ruanyifeng.com/blog/2019/10/tmux.html
+
+别担心,tmux 虽然非常有用,但学习起来很容易,只需要记住几个快捷键就可以正常使用了。
+
+## 前缀键
+
+了解 tmux 的朋友可能知道什么是前缀键,PaoTin++ 的 tmux 前缀键已经被修改为 `<ctrl+a>`。
+如果你不知道什么是前缀键,只需要记住,下面所有的快捷键都是先按 `<ctrl+a>`,然后松开,
+继续按后面的字母就可以了。
+
+## 快捷键
+
+PaoTin++ 常用的快捷键有:
+
+  * `<ctrl+a> d` 退出界面,但并不退出游戏。
+  * `<ctrl+a> -` 横着划一道,将屏幕分成上下两部分。继续按可以继续分。
+  * `<ctrl+a> |` 竖着划一道,将屏幕分成左右两部分。继续按可以继续分。
+  * `<ctrl+a> - <ctrl+a> |` 先横着划一道,再竖着划一道,形成一个「品」字形结构。
+  * `<ctrl+a> | <ctrl+a> -` 先横着划一道,再竖着划一道,形成一个「唱」字形结构。
+  * `<ctrl+a> c` 打开一个新窗口。
+  * `<ctrl+a> 0` 回到 0 号窗口。`<ctrl+a> 1` 回到 1 号窗口。十个数字都可以用。
+
+上面的窗口和分屏都可以用鼠标点击选择。
+
+## 进一步学习
+
+  * tao-of-tmux: https://tao-of-tmux.readthedocs.io/zh_CN/latest/

+ 9 - 1
framework/log.tin

@@ -21,6 +21,8 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 
 #var gLog[PATH]     {log};
 
+#var gLog[initialled]   {false};
+
 #func {InitLog} {
     #local path {%1};
 
@@ -37,7 +39,8 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
         #return 0;
     };
 
-    #var gLog[PATH] {$gLog[PATH]/$path};
+    #var gLog[PATH]         {$gLog[PATH]/$path};
+    #var gLog[initialled]   {true};
 
     load-lib option;
     option.Define {EchoCommand} {Bool} {是否回显发送的命令} {false};
@@ -66,6 +69,8 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
     #local text {%2};
     #local echo {%3};
 
+    #if { "$gLog[initialled]" != "true" } {#return};
+
     #line logmode stamp #line log {$gLog[PATH]/$file} {$text<099>};
 
     #if { "$echo" == "ECHO" } {
@@ -74,6 +79,8 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 };
 
 #event {RECEIVED INPUT} {
+    #if { "$gLog[initialled]" != "true" } {#return};
+
     #local needEcho {false};
 
     #if @option.IsDisable{EchoCommand} {
@@ -96,6 +103,7 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 };
 
 #alias {log.Open} {
+    #if { "$gLog[initialled]" != "true" } {#return};
     #config {LOG} {RAW};
     #config {LOG LEVEL} {HIGH};
     #log timestamp {%Y-%m-%d %H:%M:%S };

+ 22 - 12
framework/main.tin

@@ -15,20 +15,28 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 #kill all;
 
 #event {PROGRAM START} {
-    #if { "$user[id]" != "{[A-Za-z0-9]+}" } {
-        #echo {<119>请参考使用文档指定用户正确的 user id。<299>};
-        #return;
+    #if { "$user[manual]" == "true" } {
+        #var user[id]       {};
+        #var user[name]     {};
+        #var user[passwd]   {};
+        #screen set title {};
     };
+    #else {
+        #if { "$user[id]" != "{[A-Za-z0-9]+}" } {
+            #echo {<119>请参考使用文档指定用户正确的 user id。<299>};
+            #return;
+        };
 
-    #local path {$user[id]};
-    #if { "$session[log_path]" != "" } {
-        #local path {$session[log_path]};
-    };
+        #local path {$user[id]};
+        #if { "$session[log_path]" != "" } {
+            #local path {$session[log_path]};
+        };
 
-    #if { !@InitLog{$path} } {
-        #echo {<119>创建日志目录 $gLog[PATH]/$path 时遇到错误。<299>};
-        #echo {<139>请检查你的安装环境,或者参考使用手册重新安装本软件。<299>};
-        #return;
+        #if { !@InitLog{$path} } {
+            #echo {<119>创建日志目录 $gLog[PATH]/$path 时遇到错误。<299>};
+            #echo {<139>请检查你的安装环境,或者参考使用手册重新安装本软件。<299>};
+            #return;
+        };
     };
 
     load-module basic/login;
@@ -54,7 +62,9 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
         load-module lib/event;
         event.Define {user-online} {无参} {framework} {已经登录到服务器,所有命令都可以正常使用了。};
         load-module lib/ui;
-        #delay KeepAlive {#zap} {$session[reconnect]};
+        #if { "$user[manual]" != "true" } {
+            #delay KeepAlive {#zap} {$session[reconnect]};
+        };
     };
 };
 

+ 2 - 1
ids/EXAMPLE

@@ -14,8 +14,9 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 #nop 载入 PaoTin++ 环境;
 #read {framework/main.tin};
 
-#nop 你要连哪个接入;
+#nop 游戏入口,服务器和端口需要分别设置。;
 #var session[host]  mud.pkuxkx.net;
+#var session[port]  8081;
 #nop 你的账号英文 ID;
 #var user[id]       foo;
 #nop 你的大名;

+ 0 - 0
ids/LOCAL → ids/paotin


+ 38 - 0
ids/pkuxkx

@@ -0,0 +1,38 @@
+#!/usr/bin/env tt++
+#nop vim: set filetype=tt:;
+
+/*
+模块名称:用户配置文件模版
+模块说明:本文件是 PaoTin++ 的命令行入口程序
+版权声明:本文件属于 PaoTin++ 的一部分
+===========
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+===========
+*/
+
+#nop 载入 PaoTin++ 环境;
+#read {framework/main.tin};
+
+#nop 你要连哪个接入,海外用户需要用 pkuxkx.com 或 hk.pkuxkx.com;
+#var session[host]  mud.pkuxkx.net;
+#nop 你的账号英文 ID;
+#var user[id]       {这里写你的游戏账号,例如 pkuxkx};
+#nop 你的大名;
+#var user[name]     {这里写你的游戏中文名,例如 北大侠客行};
+#nop 你的账号密码;
+#var user[passwd]   {这里写你的游戏密码,例如 123456};
+#nop 上面三处修改完毕之后,请删除下面这行文字:;
+#var user[manual]   {true};
+
+#nop XXX: 所有 ids/DEFAULT 里的内容都可以在这里定制;
+#nop 这里为了简单起见没有全部列出,如有更多需求请参考 ids/DEFAULT 定制;
+
+#nop 用户上线之后想要自动执行的代码写这里;
+#alias {user-online} {
+    chat* back;
+};
+
+#nop 也可以在下面继续定义自己的别名和触发,均在 #gts 生效(会继承到所有 session);
+
+#alias {hello} {hi};

+ 5 - 3
ids/EXAMPLE-xyj → ids/thuxyj

@@ -22,11 +22,13 @@ mudlib.Set thuxyj;
 #var session[port]  6666;
 #var session[UTF8]  false;
 #nop 你的账号英文 ID;
-#var user[id]       foo;
+#var user[id]       {花括号里写你的游戏账号,例如 thuxyj};
 #nop 你的大名;
-#var user[name]     小虾米;
+#var user[name]     {花括号里写你的游戏中文名,例如 清华西游记};
 #nop 你的账号密码;
-#var user[passwd]   bar;
+#var user[passwd]   {花括号里写你的游戏密码,例如 123456};
+#nop 上面三处修改完毕之后,请删除下面这行文字:;
+#var user[manual]   {true};
 
 #nop XXX: 所有 ids/DEFAULT 里的内容都可以在这里定制;
 #nop 这里为了简单起见没有全部列出,如有更多需求请参考 ids/DEFAULT 定制;

+ 6 - 0
init.tin

@@ -0,0 +1,6 @@
+#read framework/settings.tin;
+#config {command echo} {on};
+#echo {<131>请注意:这不是 PaoTin++!这只是担子炮魔改版的 TinTin++。<099>};
+#echo {<129>退出请输入 <134>#end<129> 帮助请输入 <134>#help<129> 小乖乖中文手册最新版: <099>https://github.com/zixijian/tt/blob/master/Wiki.md};
+#echo {<129>连接北大侠客行请输入 <134>#session mud mud.pkuxkx.net 8080<099>};
+#echo {<129>连接清华西游记请输入 <134>#session mud xyj.thu.cn 8666<099>};

+ 88 - 3
mud/pkuxkx/plugins/basic/login.tin

@@ -50,12 +50,38 @@
 
         #config {charset} {UTF-8};
 
-        xtt.Answer {$login[user][id]};
+        #if { "$login[user][id]" != "" } {
+            xtt.Answer {$login[user][id]};
+        };
+        #else {
+            #line oneshot #macro {\n} {
+                #cursor get {login[user][id]};
+                #cursor clear;
+                #if { "$login[user][id]" == "#%*" } {
+                    #var login[user][id] {};
+                };
+                #if { "$login[user][id]" != "" } {
+                    xtt.Answer {$login[user][id]};
+                };
+            };
+        };
     };
 
     #line oneshot #action {^此ID档案已存在,请输入密码:$} {
-        xtt.Answer {$login[user][passwd]};
-        #delay {login.check} {look} 1;
+        #if { "$login[user][passwd]" != "" } {
+            xtt.Answer {$login[user][passwd]};
+            #delay {login.check} {look} 1;
+        };
+        #else {
+            #cursor flag echo on;
+            #line oneshot #macro {\n} {
+                #cursor get {login[user][passwd]};
+                #cursor clear;
+                #if { "$login[user][passwd]" != "" } {
+                    xtt.Answer {$login[user][passwd]};
+                };
+            };
+        };
     };
 
     #line oneshot #action {^您要将另一个连线中的相同人物赶出去,取而代之吗?(y/n)$} {
@@ -94,6 +120,12 @@
         #local type {%%1};
 
         #showme 登录成功。;
+
+        #if { @isTrue{$login[user][manual]} } {
+            login.write-id-file;
+            login.init-game;
+        };
+
         #local handler $login[autoexec];
         #class login.auto-login kill;
         #undelay login.auto-login.success;
@@ -109,3 +141,56 @@
 
     #class login.auto-login close;
 };
+
+#alias {login.init-game} {
+    #if { "$login[user][id]" == "" || "$user[id]" != "" } {
+        #return;
+    };
+
+    #var user[id]           {$login[user][id]};
+    #var user[passwd]       {$login[user][passwd]};
+    #gts #var user[id]      {$login[user][id]};
+    #gts #var user[passwd]  {$login[user][passwd]};
+
+    #local path {$user[id]};
+    #if { "$session[log_path]" != "" } {
+        #local path {$session[log_path]};
+    };
+
+    #if { !@InitLog{$path} } {
+        #echo {<119>创建日志目录 $gLog[PATH]/$path 时遇到错误。<299>};
+        #echo {<139>请检查你的安装环境,或者参考使用手册重新安装本软件。<299>};
+        #return;
+    };
+
+    log.Open;
+    #screen set title GAME-$user[id];
+
+    NOTE 启动配置文件已生成,下次你可以直接 start $login[user][id] 进入游戏。;
+};
+
+#alias {login.write-id-file} {
+    #if { "$login[user][id]" == "" || "$user[id]" != "" } {
+        #return;
+    };
+
+    #local id-file {ids/$login[user][id]};
+
+    #local output {};
+    #script output {test -d var/ids && echo true || echo false};
+    #if { "$output[1]" == "true" } {
+        #local id-file {var/$id-file};
+    };
+
+    #if { @existsFile{$id-file} } {
+        #return;
+    };
+
+    #script output {cp ids/pkuxkx $id-file};
+    #script output {sed -i.bak 's/^#var user\[id\]       {.*};$/#var user[id]       {$login[user][id]};/' $id-file};
+    #script output {sed -i.bak 's/^#var user\[name\]     {.*};$/#var user[name]     {};/' $id-file};
+    #script output {sed -i.bak 's/^#var user\[passwd\]   {.*};$/#var user[passwd]   {$login[user][passwd]};/' $id-file};
+    #script output {sed -i.bak '/^#nop 上面三处修改完毕之后,请删除下面这行文字:;$/d' $id-file};
+    #script output {sed -i.bak '/^#var user\[manual\]   {true};$/d' $id-file};
+    #script output {rm ${id-file}.bak};
+};

+ 133 - 40
mud/thuxyj/plugins/basic/login.tin

@@ -1,8 +1,5 @@
 #nop vim: filetype=tt
 
-#class login kill;
-#class login open;
-
 #var login[session]     {};
 #var login[user]        {};
 #var login[autoexec]    {};
@@ -15,56 +12,152 @@
 };
 
 #event {SESSION CONNECTED} {
-    #if { "%0" == "$login[session][name]" } {
-        #class auto-login kill;
-        #class auto-login open;
-
-        #nop 如果角色设置了 GMCP 支持,则积极回应服务器的 GMCP 协商请求。;
-        #if { "$user[GMCP]" == "true" } {
-            load-lib gmcp;
-            gmcp.Enable;
-        };
+    #if { "%0" !== "$login[session][name]" } {
+        #return;
+    };
+
+    login.auto-login;
+};
+
+#alias {login.auto-login} {
+    #class login.auto-login open;
+
+    #config {IAC GA} {OFF};
 
-        #if { "$session[UTF8]" == "true" } {
-            #config {charset} {UTF-8};
+    #nop 如果角色设置了 GMCP 支持,则积极回应服务器的 GMCP 协商请求。;
+    #if { "$user[GMCP]" == "true" } {
+        load-lib gmcp;
+        gmcp.Enable;
+    };
+
+    #if { "$session[UTF8]" == "true" } {
+        #config {charset} {UTF-8};
+    };
+    #else {
+        #config {charset} {GBK1TOUTF8};
+    };
+
+    #line oneshot #action {^%sWelcome to Xi You Ji! Select GB or BIG5 (gb/big5):$} {
+        #line oneshot #event {CATCH VT100 ERASE SCREEN ALL} {#0;#buffer end};
+        xtt.Answer gb;
+    };
+
+    #line oneshot #action {^您是否是中小学学生或年龄更小?(yes/no)$} {
+        #delay 0 #send no;
+    };
+
+    #line oneshot #action {^您的英文名字:(新玩家请键入 new 注册)$} {
+        #if { "$login[user][id]" != "" } {
+            xtt.Answer {$login[user][id]};
         };
         #else {
-            #config {charset} {GBK1TOUTF8};
+            #line oneshot #macro {\n} {
+                #cursor get {login[user][id]};
+                #cursor clear;
+                #if { "$login[user][id]" == "#%*" } {
+                    #var login[user][id] {};
+                };
+                #if { "$login[user][id]" != "" } {
+                    xtt.Answer {$login[user][id]};
+                };
+            };
         };
+    };
 
-        #line oneshot #action {^%sWelcome to Xi You Ji! Select GB or BIG5 (gb/big5):$} {
-            #line oneshot #event {CATCH VT100 ERASE SCREEN ALL} {#0};
-            xtt.Answer gb;
+    #action {^请输入相应密码:$} {
+        #if { "$login[user][passwd]" != "" } {
+            xtt.Answer {$login[user][passwd]};
+            #delay {login.check} {look} 1;
         };
-
-        #line oneshot #action {^您是否是中小学学生或年龄更小?(yes/no)$} {
-            #delay 0 #send no;
+        #else {
+            #cursor flag echo on;
+            #line oneshot #macro {\n} {
+                #cursor get {login[user][passwd]};
+                #cursor clear;
+                #if { "$login[user][passwd]" != "" } {
+                    xtt.Answer {$login[user][passwd]};
+                };
+            };
         };
+    };
 
-        #line oneshot #action {^您的英文名字:(新玩家请键入 new 注册)$} {
-            xtt.Answer $login[user][id];
-        };
+    #line oneshot #action {^您要将另一个连线中的相同人物赶出去,取而代之吗?(y/n)$} {
+        xtt.Answer y;
+    };
 
-        #action {^请输入相应密码:$} {
-            xtt.Answer {$login[user][passwd]};
-        };
+    #line oneshot #action {^重新连线完毕。$} {
+        #delay {login.auto-login.success} {login.auto-login.success 断线重连} 0;
+    };
 
-        #line oneshot #action {^您要将另一个连线中的相同人物赶出去,取而代之吗?(y/n)$} {
-            xtt.Answer y;
-        };
+    #alias {login.auto-login.success} {
+        #local type {%%1};
 
-        #line oneshot #action {^重新连线完毕。$} {
-            #delay 0 {
-                #showme 登录成功。;
-                #local handler $login[autoexec];
-                #class auto-login kill;
-                #class login kill;
-                $handler;
-            };
+        #if { @isTrue{$login[user][manual]} } {
+            login.write-id-file;
+            login.init-game;
         };
 
-        #class auto-login close;
+        #showme 登录成功。;
+
+        #local handler $login[autoexec];
+        #class login.auto-login kill;
+        #undelay login.auto-login.success;
+        kill-module login;
+        $handler;
     };
+
+    #class login.auto-login close;
 };
 
-#class login close;
+#alias {login.init-game} {
+    #if { "$login[user][id]" == "" || "$user[id]" != "" } {
+        #return;
+    };
+
+    #var user[id]           {$login[user][id]};
+    #var user[passwd]       {$login[user][passwd]};
+    #gts #var user[id]      {$login[user][id]};
+    #gts #var user[passwd]  {$login[user][passwd]};
+
+    #local path {$user[id]};
+    #if { "$session[log_path]" != "" } {
+        #local path {$session[log_path]};
+    };
+
+    #if { !@InitLog{$path} } {
+        #echo {<119>创建日志目录 $gLog[PATH]/$path 时遇到错误。<299>};
+        #echo {<139>请检查你的安装环境,或者参考使用手册重新安装本软件。<299>};
+        #return;
+    };
+
+    log.Open;
+    #screen set title GAME-$user[id];
+
+    NOTE 启动配置文件已生成,下次你可以直接 start $login[user][id] 进入游戏。;
+};
+
+#alias {login.write-id-file} {
+    #if { "$login[user][id]" == "" || "$user[id]" != "" } {
+        #return;
+    };
+
+    #local id-file {ids/$login[user][id]};
+
+    #local output {};
+    #script output {test -d var/ids && echo true || echo false};
+    #if { "$output[1]" == "true" } {
+        #local id-file {var/$id-file};
+    };
+
+    #if { @existsFile{$id-file} } {
+        #return;
+    };
+
+    #script output {cp ids/thuxyj $id-file};
+    #script output {sed -i.bak 's/^#var user\[id\]       {.*};$/#var user[id]       {$login[user][id]};/' $id-file};
+    #script output {sed -i.bak 's/^#var user\[name\]     {.*};$/#var user[name]     {};/' $id-file};
+    #script output {sed -i.bak 's/^#var user\[passwd\]   {.*};$/#var user[passwd]   {$login[user][passwd]};/' $id-file};
+    #script output {sed -i.bak '/^#nop 上面三处修改完毕之后,请删除下面这行文字:;$/d' $id-file};
+    #script output {sed -i.bak '/^#var user\[manual\]   {true};$/d' $id-file};
+    #script output {rm ${id-file}.bak};
+};