pymud 0.20.0a2__py3-none-any.whl → 0.20.0a3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymud/__init__.py +2 -1
- pymud/__main__.py +2 -131
- pymud/logger.py +1 -1
- pymud/main.py +141 -0
- pymud/pymud.py +71 -49
- pymud/session.py +227 -55
- pymud/settings.py +1 -1
- {pymud-0.20.0a2.dist-info → pymud-0.20.0a3.dist-info}/METADATA +14 -1
- pymud-0.20.0a3.dist-info/RECORD +18 -0
- {pymud-0.20.0a2.dist-info → pymud-0.20.0a3.dist-info}/WHEEL +1 -1
- pymud-0.20.0a2.dist-info/RECORD +0 -17
- {pymud-0.20.0a2.dist-info → pymud-0.20.0a3.dist-info}/LICENSE.txt +0 -0
- {pymud-0.20.0a2.dist-info → pymud-0.20.0a3.dist-info}/entry_points.txt +0 -0
- {pymud-0.20.0a2.dist-info → pymud-0.20.0a3.dist-info}/top_level.txt +0 -0
pymud/__init__.py
CHANGED
@@ -4,7 +4,8 @@ from .objects import CodeBlock, Alias, SimpleAlias, Trigger, SimpleTrigger, Comm
|
|
4
4
|
from .extras import DotDict
|
5
5
|
from .session import Session
|
6
6
|
from .logger import Logger
|
7
|
+
from .main import main
|
7
8
|
|
8
9
|
__all__ = [
|
9
|
-
"PyMudApp", "Settings", "CodeBlock", "Alias", "SimpleAlias", "Trigger", "SimpleTrigger", "Command", "SimpleCommand", "Timer", "SimpleTimer", "GMCPTrigger", "Session", "PyMudApp", "DotDict", "Logger"
|
10
|
+
"PyMudApp", "Settings", "CodeBlock", "Alias", "SimpleAlias", "Trigger", "SimpleTrigger", "Command", "SimpleCommand", "Timer", "SimpleTimer", "GMCPTrigger", "Session", "PyMudApp", "DotDict", "Logger", "main"
|
10
11
|
]
|
pymud/__main__.py
CHANGED
@@ -1,133 +1,4 @@
|
|
1
|
-
|
2
|
-
from pathlib import Path
|
3
|
-
from .pymud import main
|
4
|
-
from .settings import Settings
|
5
|
-
|
6
|
-
CFG_TEMPLATE = {
|
7
|
-
"client": {
|
8
|
-
"buffer_lines" : 5000, # 保留缓冲行数
|
9
|
-
|
10
|
-
"interval" : 10, # 在自动执行中,两次命令输入中的间隔时间(ms)
|
11
|
-
"auto_connect" : True, # 创建会话后,是否自动连接
|
12
|
-
"auto_reconnect" : False, # 在会话异常断开之后,是否自动重连
|
13
|
-
"var_autosave" : True, # 断开时自动保存会话变量
|
14
|
-
"var_autoload" : True, # 初始化时自动加载会话变量
|
15
|
-
|
16
|
-
"echo_input" : False,
|
17
|
-
"beautify" : True, # 专门为解决控制台下PKUXKX字符画对不齐的问题
|
18
|
-
|
19
|
-
"status_display" : 1, # 状态窗口显示情况设置,0-不显示,1-显示在下方,2-显示在右侧
|
20
|
-
"status_height" : 4, # 下侧状态栏的高度
|
21
|
-
"status_width" : 30, # 右侧状态栏的宽度
|
22
|
-
|
23
|
-
},
|
24
|
-
"sessions" : {
|
25
|
-
"pkuxkx" : {
|
26
|
-
"host" : "mud.pkuxkx.net",
|
27
|
-
"port" : "8081",
|
28
|
-
"encoding" : "utf8",
|
29
|
-
"autologin" : "{0};{1}",
|
30
|
-
"default_script": "examples",
|
31
|
-
"chars" : {
|
32
|
-
"display_title" : ["yourid", "yourpassword", ""],
|
33
|
-
}
|
34
|
-
}
|
35
|
-
},
|
36
|
-
"keys" : {
|
37
|
-
"f3" : "#ig",
|
38
|
-
"f4" : "#clear",
|
39
|
-
"f11" : "#close",
|
40
|
-
"f12" : "#exit",
|
41
|
-
}
|
42
|
-
}
|
43
|
-
|
44
|
-
def init_pymud_env(args):
|
45
|
-
print(f"欢迎使用PyMUD, 版本{Settings.__version__}. 使用PyMUD时, 建议建立一个新目录(任意位置),并将自己的脚本以及配置文件放到该目录下.")
|
46
|
-
print("即将开始为首次运行初始化环境...")
|
47
|
-
|
48
|
-
dir = args.dir
|
49
|
-
if dir:
|
50
|
-
print(f"你已经指定了创建脚本的目录为 {args.dir}")
|
51
|
-
dir = Path(dir)
|
52
|
-
else:
|
53
|
-
dir = Path.home().joinpath('pkuxkx')
|
54
|
-
|
55
|
-
system = platform.system().lower()
|
56
|
-
dir_enter = input(f"检测到当前系统为 {system}, 请指定游戏脚本的目录(若目录不存在会自动创建),直接回车表示使用默认值 [{dir}]:")
|
57
|
-
if dir_enter:
|
58
|
-
dir = Path(dir_enter)
|
59
|
-
|
60
|
-
if dir.exists() and dir.is_dir():
|
61
|
-
print(f'检测到给定目录 {dir} 已存在,切换至此目录...')
|
62
|
-
else:
|
63
|
-
print(f'检测到给定目录 {dir} 不存在,正在创建并切换至目录...')
|
64
|
-
dir.mkdir()
|
65
|
-
|
66
|
-
os.chdir(dir)
|
67
|
-
|
68
|
-
if os.path.exists('pymud.cfg'):
|
69
|
-
print(f'检测到脚本目录下已存在pymud.cfg文件,将直接使用此文件进入PyMUD...')
|
70
|
-
else:
|
71
|
-
print(f'检测到脚本目录下不存在pymud.cfg文件,将使用默认内容创建该配置文件...')
|
72
|
-
with open('pymud.cfg', mode = 'x') as fp:
|
73
|
-
fp.writelines(json.dumps(CFG_TEMPLATE, indent = 4))
|
74
|
-
|
75
|
-
if not os.path.exists('examples.py'):
|
76
|
-
from pymud import pkuxkx
|
77
|
-
module_dir = pkuxkx.__file__
|
78
|
-
shutil.copyfile(module_dir, 'examples.py')
|
79
|
-
print(f'已将样例脚本拷贝至脚本目录,并加入默认配置文件')
|
80
|
-
|
81
|
-
print(f"后续可自行修改 {dir} 目录下的 pymud.cfg 文件以进行配置。")
|
82
|
-
if system == "windows":
|
83
|
-
print(f"后续运行PyMUD, 请在 {dir} 目录下键入命令: python -m pymud")
|
84
|
-
else:
|
85
|
-
print(f"后续运行PyMUD, 请在 {dir} 目录下键入命令: python3 -m pymud")
|
86
|
-
|
87
|
-
input('所有内容已初始化完毕, 请按回车进入PyMUD.')
|
88
|
-
|
89
|
-
module_entry(args)
|
90
|
-
|
91
|
-
def module_entry(args):
|
92
|
-
if args.debug:
|
93
|
-
logging.basicConfig(level = logging.NOTSET,
|
94
|
-
format = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
95
|
-
datefmt = '%m-%d %H:%M',
|
96
|
-
filename = args.logfile,
|
97
|
-
filemode = 'a' if args.filemode else 'w',
|
98
|
-
encoding = "utf-8"
|
99
|
-
)
|
100
|
-
|
101
|
-
else:
|
102
|
-
logging.basicConfig(level = logging.NOTSET,
|
103
|
-
format = '%(asctime)s %(name)-12s: %(message)s',
|
104
|
-
datefmt = '%m-%d %H:%M',
|
105
|
-
handlers = [logging.NullHandler()],
|
106
|
-
)
|
107
|
-
|
108
|
-
cfg = "pymud.cfg"
|
109
|
-
if os.path.exists(cfg):
|
110
|
-
with open(cfg, "r", encoding="utf8", errors="ignore") as fp:
|
111
|
-
cfg_data = json.load(fp)
|
112
|
-
main(cfg_data)
|
113
|
-
else:
|
114
|
-
main()
|
115
|
-
|
1
|
+
from .main import main
|
116
2
|
|
117
3
|
if __name__ == "__main__":
|
118
|
-
|
119
|
-
subparsers = parser.add_subparsers(help = 'init用于初始化运行环境')
|
120
|
-
|
121
|
-
par_init = subparsers.add_parser('init', usage = "python -m pymud init [-h] [-d dir]", description = '初始化pymud运行环境, 包括建立脚本目录, 创建默认配置文件, 创建样例脚本等.')
|
122
|
-
par_init.add_argument('-d', '--dir', dest = 'dir', metavar = 'dir', type = str, default = '', help = '指定构建脚本目录的名称, 不指定时会根据操作系统选择不同默认值')
|
123
|
-
par_init.set_defaults(func = init_pymud_env)
|
124
|
-
|
125
|
-
parser.add_argument('-d', '--debug', dest = 'debug', action = 'store_true', default = False, help = '指定以调试模式进入PyMUD。此时,系统log等级将设置为logging.NOTSET, 所有log数据均会被记录。默认不启用。')
|
126
|
-
parser.add_argument('-l', '--logfile', dest = 'logfile', metavar = 'logfile', default = 'pymud.log', help = '指定调试模式下记录文件名,不指定时,默认为当前目录下的pymud.log')
|
127
|
-
parser.add_argument('-a', '--appendmode', dest = 'filemode', action = 'store_true', default = True, help = '指定log文件的访问模式是否为append尾部添加模式,默认为True。当为False时,使用w模式,即每次运行清空之前记录')
|
128
|
-
|
129
|
-
args=parser.parse_args()
|
130
|
-
if hasattr(args, 'func'):
|
131
|
-
args.func(args)
|
132
|
-
else:
|
133
|
-
module_entry(args)
|
4
|
+
main()
|
pymud/logger.py
CHANGED
@@ -15,7 +15,7 @@ class Logger:
|
|
15
15
|
:param raw: 记录带ANSI标记的原始内容,还是记录纯文本内容,默认为True,即记录带ANSI标记的原始内容。
|
16
16
|
"""
|
17
17
|
|
18
|
-
_esc_regx = re.compile("\x1b
|
18
|
+
_esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
|
19
19
|
|
20
20
|
def __init__(self, name, mode = 'a', encoding = "utf-8", errors = "ignore", raw = False):
|
21
21
|
self._name = name
|
pymud/main.py
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
import os, sys, json, platform, shutil, logging, argparse
|
2
|
+
from pathlib import Path
|
3
|
+
from .pymud import PyMudApp
|
4
|
+
from .settings import Settings
|
5
|
+
|
6
|
+
CFG_TEMPLATE = {
|
7
|
+
"client": {
|
8
|
+
"buffer_lines" : 5000, # 保留缓冲行数
|
9
|
+
|
10
|
+
"interval" : 10, # 在自动执行中,两次命令输入中的间隔时间(ms)
|
11
|
+
"auto_connect" : True, # 创建会话后,是否自动连接
|
12
|
+
"auto_reconnect" : False, # 在会话异常断开之后,是否自动重连
|
13
|
+
"var_autosave" : True, # 断开时自动保存会话变量
|
14
|
+
"var_autoload" : True, # 初始化时自动加载会话变量
|
15
|
+
|
16
|
+
"echo_input" : False,
|
17
|
+
"beautify" : True, # 专门为解决控制台下PKUXKX字符画对不齐的问题
|
18
|
+
|
19
|
+
"status_display" : 1, # 状态窗口显示情况设置,0-不显示,1-显示在下方,2-显示在右侧
|
20
|
+
"status_height" : 4, # 下侧状态栏的高度
|
21
|
+
"status_width" : 30, # 右侧状态栏的宽度
|
22
|
+
|
23
|
+
},
|
24
|
+
"sessions" : {
|
25
|
+
"pkuxkx" : {
|
26
|
+
"host" : "mud.pkuxkx.net",
|
27
|
+
"port" : "8081",
|
28
|
+
"encoding" : "utf8",
|
29
|
+
"autologin" : "{0};{1}",
|
30
|
+
"default_script": "examples",
|
31
|
+
"chars" : {
|
32
|
+
"display_title" : ["yourid", "yourpassword", ""],
|
33
|
+
}
|
34
|
+
}
|
35
|
+
},
|
36
|
+
"keys" : {
|
37
|
+
"f3" : "#ig",
|
38
|
+
"f4" : "#clear",
|
39
|
+
"f11" : "#close",
|
40
|
+
"f12" : "#exit",
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
def init_pymud_env(args):
|
45
|
+
print(f"欢迎使用PyMUD, 版本{Settings.__version__}. 使用PyMUD时, 建议建立一个新目录(任意位置),并将自己的脚本以及配置文件放到该目录下.")
|
46
|
+
print("即将开始为首次运行初始化环境...")
|
47
|
+
|
48
|
+
dir = args.dir
|
49
|
+
if dir:
|
50
|
+
print(f"你已经指定了创建脚本的目录为 {args.dir}")
|
51
|
+
dir = Path(dir)
|
52
|
+
else:
|
53
|
+
dir = Path.home().joinpath('pkuxkx')
|
54
|
+
|
55
|
+
system = platform.system().lower()
|
56
|
+
dir_enter = input(f"检测到当前系统为 {system}, 请指定游戏脚本的目录(若目录不存在会自动创建),直接回车表示使用默认值 [{dir}]:")
|
57
|
+
if dir_enter:
|
58
|
+
dir = Path(dir_enter)
|
59
|
+
|
60
|
+
if dir.exists() and dir.is_dir():
|
61
|
+
print(f'检测到给定目录 {dir} 已存在,切换至此目录...')
|
62
|
+
else:
|
63
|
+
print(f'检测到给定目录 {dir} 不存在,正在创建并切换至目录...')
|
64
|
+
dir.mkdir()
|
65
|
+
|
66
|
+
os.chdir(dir)
|
67
|
+
|
68
|
+
if os.path.exists('pymud.cfg'):
|
69
|
+
print(f'检测到脚本目录下已存在pymud.cfg文件,将直接使用此文件进入PyMUD...')
|
70
|
+
else:
|
71
|
+
print(f'检测到脚本目录下不存在pymud.cfg文件,将使用默认内容创建该配置文件...')
|
72
|
+
with open('pymud.cfg', mode = 'x') as fp:
|
73
|
+
fp.writelines(json.dumps(CFG_TEMPLATE, indent = 4))
|
74
|
+
|
75
|
+
if not os.path.exists('examples.py'):
|
76
|
+
from pymud import pkuxkx
|
77
|
+
module_dir = pkuxkx.__file__
|
78
|
+
shutil.copyfile(module_dir, 'examples.py')
|
79
|
+
print(f'已将样例脚本拷贝至脚本目录,并加入默认配置文件')
|
80
|
+
|
81
|
+
print(f"后续可自行修改 {dir} 目录下的 pymud.cfg 文件以进行配置。")
|
82
|
+
if system == "windows":
|
83
|
+
print(f"后续运行PyMUD, 请在 {dir} 目录下键入命令: python -m pymud")
|
84
|
+
else:
|
85
|
+
print(f"后续运行PyMUD, 请在 {dir} 目录下键入命令: python3 -m pymud")
|
86
|
+
|
87
|
+
input('所有内容已初始化完毕, 请按回车进入PyMUD.')
|
88
|
+
|
89
|
+
startApp(args)
|
90
|
+
|
91
|
+
def startApp(args):
|
92
|
+
if args.debug:
|
93
|
+
logging.basicConfig(level = logging.NOTSET,
|
94
|
+
format = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
|
95
|
+
datefmt = '%m-%d %H:%M',
|
96
|
+
filename = args.logfile,
|
97
|
+
filemode = 'a' if args.filemode else 'w',
|
98
|
+
encoding = "utf-8"
|
99
|
+
)
|
100
|
+
|
101
|
+
else:
|
102
|
+
logging.basicConfig(level = logging.NOTSET,
|
103
|
+
format = '%(asctime)s %(name)-12s: %(message)s',
|
104
|
+
datefmt = '%m-%d %H:%M',
|
105
|
+
handlers = [logging.NullHandler()],
|
106
|
+
)
|
107
|
+
|
108
|
+
startup_path = Path(args.startup_dir).resolve()
|
109
|
+
sys.path.append(f"{startup_path}")
|
110
|
+
os.chdir(startup_path)
|
111
|
+
cfg = startup_path.joinpath("pymud.cfg")
|
112
|
+
cfg_data = None
|
113
|
+
if os.path.exists(cfg):
|
114
|
+
with open(cfg, "r", encoding="utf8", errors="ignore") as fp:
|
115
|
+
cfg_data = json.load(fp)
|
116
|
+
|
117
|
+
app = PyMudApp(cfg_data)
|
118
|
+
app.run()
|
119
|
+
|
120
|
+
def main():
|
121
|
+
parser = argparse.ArgumentParser(prog = "pymud", description = "PyMUD命令行参数帮助")
|
122
|
+
subparsers = parser.add_subparsers(help = 'init用于初始化运行环境')
|
123
|
+
|
124
|
+
par_init = subparsers.add_parser('init', description = '初始化pymud运行环境, 包括建立脚本目录, 创建默认配置文件, 创建样例脚本等.')
|
125
|
+
par_init.add_argument('-d', '--dir', dest = 'dir', metavar = 'dir', type = str, default = '', help = '指定构建脚本目录的名称, 不指定时会根据操作系统选择不同默认值')
|
126
|
+
par_init.set_defaults(func = init_pymud_env)
|
127
|
+
|
128
|
+
parser.add_argument('-d', '--debug', dest = 'debug', action = 'store_true', default = False, help = '指定以调试模式进入PyMUD。此时,系统log等级将设置为logging.NOTSET, 所有log数据均会被记录。默认不启用。')
|
129
|
+
parser.add_argument('-l', '--logfile', dest = 'logfile', metavar = 'logfile', default = 'pymud.log', help = '指定调试模式下记录文件名,不指定时,默认为当前目录下的pymud.log')
|
130
|
+
parser.add_argument('-a', '--appendmode', dest = 'filemode', action = 'store_true', default = True, help = '指定log文件的访问模式是否为append尾部添加模式,默认为True。当为False时,使用w模式,即每次运行清空之前记录')
|
131
|
+
parser.add_argument('-s', '--startup_dir', dest = 'startup_dir', metavar = 'startup_dir', default = '.', help = '指定启动目录,默认为当前目录。使用该参数可以在任何目录下,通过指定脚本目录来启动')
|
132
|
+
|
133
|
+
args=parser.parse_args()
|
134
|
+
|
135
|
+
if hasattr(args, 'func'):
|
136
|
+
args.func(args)
|
137
|
+
else:
|
138
|
+
startApp(args)
|
139
|
+
|
140
|
+
if __name__ == "__main__":
|
141
|
+
main()
|
pymud/pymud.py
CHANGED
@@ -318,8 +318,8 @@ class PyMudApp:
|
|
318
318
|
),
|
319
319
|
|
320
320
|
MenuItem(
|
321
|
-
"", # 增加一个空名称MenuItem
|
322
|
-
|
321
|
+
"", # 增加一个空名称MenuItem,单机后焦点移动至命令行输入处,阻止右侧空白栏点击响应
|
322
|
+
handler = lambda : self.app.layout.focus(self.commandLine)
|
323
323
|
)
|
324
324
|
],
|
325
325
|
floats=[
|
@@ -340,34 +340,9 @@ class PyMudApp:
|
|
340
340
|
ss = Settings.sessions
|
341
341
|
|
342
342
|
for key, site in ss.items():
|
343
|
-
host = site["host"]
|
344
|
-
port = site["port"]
|
345
|
-
encoding = site["encoding"]
|
346
|
-
autologin = site["autologin"]
|
347
|
-
scripts = list()
|
348
|
-
default_script = site["default_script"]
|
349
|
-
|
350
|
-
def_scripts = list()
|
351
|
-
if isinstance(default_script, str):
|
352
|
-
def_scripts.extend(default_script.split(","))
|
353
|
-
elif isinstance(default_script, (list, tuple)):
|
354
|
-
def_scripts.extend(default_script)
|
355
|
-
|
356
343
|
menu = MenuItem(key)
|
357
|
-
for name
|
358
|
-
|
359
|
-
sess_scripts = list()
|
360
|
-
sess_scripts.extend(def_scripts)
|
361
|
-
|
362
|
-
if len(info) == 3:
|
363
|
-
session_script = info[2]
|
364
|
-
if session_script:
|
365
|
-
if isinstance(session_script, str):
|
366
|
-
sess_scripts.extend(session_script.split(","))
|
367
|
-
elif isinstance(session_script, (list, tuple)):
|
368
|
-
sess_scripts.extend(session_script)
|
369
|
-
|
370
|
-
sub = MenuItem(name, handler = functools.partial(self.create_session, name, host, port, encoding, after_connect, sess_scripts, info[0]))
|
344
|
+
for name in site["chars"].keys():
|
345
|
+
sub = MenuItem(name, handler = functools.partial(self._quickHandleSession, key, name))
|
371
346
|
menu.children.append(sub)
|
372
347
|
menus.append(menu)
|
373
348
|
|
@@ -506,7 +481,7 @@ class PyMudApp:
|
|
506
481
|
line = self.mudFormatProc.line_correction(b.document.current_line)
|
507
482
|
start = max(0, scol)
|
508
483
|
end = min(ecol, len(line))
|
509
|
-
line_plain = re.sub("\x1b
|
484
|
+
line_plain = re.sub(r"\x1b\[[\d;]+[abcdmz]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
|
510
485
|
#line_plain = re.sub("\x1b\\[[^mz]+[mz]", "", line).replace("\r", "").replace("\x00", "")
|
511
486
|
selection = line_plain[start:end]
|
512
487
|
self.app.clipboard.set_text(selection)
|
@@ -518,7 +493,7 @@ class PyMudApp:
|
|
518
493
|
lines = []
|
519
494
|
for row in range(srow, erow + 1):
|
520
495
|
line = b.document.lines[row]
|
521
|
-
line_plain = re.sub("\x1b
|
496
|
+
line_plain = re.sub(r"\x1b\[[\d;]+[abcdmz]", "", line, flags = re.IGNORECASE).replace("\r", "").replace("\x00", "")
|
522
497
|
lines.append(line_plain)
|
523
498
|
|
524
499
|
self.app.clipboard.set_text("\n".join(lines))
|
@@ -919,6 +894,50 @@ class PyMudApp:
|
|
919
894
|
self.status_message = msg
|
920
895
|
self.app.invalidate()
|
921
896
|
|
897
|
+
def _quickHandleSession(self, group, name):
|
898
|
+
'''
|
899
|
+
根据指定的组名和会话角色名,从Settings内容,创建一个会话
|
900
|
+
'''
|
901
|
+
handled = False
|
902
|
+
if name in self.sessions.keys():
|
903
|
+
self.activate_session(name)
|
904
|
+
handled = True
|
905
|
+
|
906
|
+
else:
|
907
|
+
site = Settings.sessions[group]
|
908
|
+
if name in site["chars"].keys():
|
909
|
+
host = site["host"]
|
910
|
+
port = site["port"]
|
911
|
+
encoding = site["encoding"]
|
912
|
+
autologin = site["autologin"]
|
913
|
+
default_script = site["default_script"]
|
914
|
+
|
915
|
+
def_scripts = list()
|
916
|
+
if isinstance(default_script, str):
|
917
|
+
def_scripts.extend(default_script.split(","))
|
918
|
+
elif isinstance(default_script, (list, tuple)):
|
919
|
+
def_scripts.extend(default_script)
|
920
|
+
|
921
|
+
charinfo = site["chars"][name]
|
922
|
+
|
923
|
+
after_connect = autologin.format(charinfo[0], charinfo[1])
|
924
|
+
sess_scripts = list()
|
925
|
+
sess_scripts.extend(def_scripts)
|
926
|
+
|
927
|
+
if len(charinfo) == 3:
|
928
|
+
session_script = charinfo[2]
|
929
|
+
if session_script:
|
930
|
+
if isinstance(session_script, str):
|
931
|
+
sess_scripts.extend(session_script.split(","))
|
932
|
+
elif isinstance(session_script, (list, tuple)):
|
933
|
+
sess_scripts.extend(session_script)
|
934
|
+
|
935
|
+
self.create_session(name, host, port, encoding, after_connect, sess_scripts, charinfo[0])
|
936
|
+
handled = True
|
937
|
+
|
938
|
+
return handled
|
939
|
+
|
940
|
+
|
922
941
|
def handle_session(self, *args):
|
923
942
|
'''
|
924
943
|
嵌入命令 #session 的执行函数,创建一个远程连接会话。
|
@@ -929,12 +948,18 @@ class PyMudApp:
|
|
929
948
|
- 当不指定 Encoding: 时, 默认使用utf-8编码
|
930
949
|
- 可以直接使用 #{名称} 切换会话和操作会话命令
|
931
950
|
|
951
|
+
- #session {group}.{name}
|
952
|
+
- 相当于直接点击菜单{group}下的{name}菜单来创建会话. 当该会话已存在时,切换到该会话
|
953
|
+
|
932
954
|
参数:
|
933
955
|
:name: 会话名称
|
934
956
|
:host: 服务器域名或IP地址
|
935
957
|
:port: 端口号
|
936
958
|
:encoding: 编码格式,不指定时默认为 utf8
|
937
959
|
|
960
|
+
:group: 组名, 即配置文件中, sessions 字段下的某个关键字
|
961
|
+
:name: 会话快捷名称, 上述 group 关键字下的 chars 字段中的某个关键字
|
962
|
+
|
938
963
|
示例:
|
939
964
|
``#session {名称} {宿主机} {端口} {编码}``
|
940
965
|
创建一个远程连接会话,使用指定编码格式连接到远程宿主机的指定端口并保存为 {名称} 。其中,编码可以省略,此时使用Settings.server["default_encoding"]的值,默认为utf8
|
@@ -947,6 +972,9 @@ class PyMudApp:
|
|
947
972
|
``#newstart give miui gold``
|
948
973
|
使名称为newstart的会话执行give miui gold指令,但不切换到该会话
|
949
974
|
|
975
|
+
``#session pkuxkx.newstart``
|
976
|
+
通过指定快捷配置创建会话,相当于点击 世界->pkuxkx->newstart 菜单创建会话。若该会话存在,则切换到该会话
|
977
|
+
|
950
978
|
相关命令:
|
951
979
|
- #close
|
952
980
|
- #exit
|
@@ -954,8 +982,17 @@ class PyMudApp:
|
|
954
982
|
'''
|
955
983
|
|
956
984
|
nothandle = True
|
985
|
+
errmsg = "错误的#session命令"
|
986
|
+
if len(args) == 1:
|
987
|
+
host_session = args[0]
|
988
|
+
if '.' in host_session:
|
989
|
+
group, name = host_session.split('.')
|
990
|
+
nothandle = not self._quickHandleSession(group, name)
|
957
991
|
|
958
|
-
|
992
|
+
else:
|
993
|
+
errmsg = f'通过单一参数快速创建会话时,要使用 group.name 形式,如 #session pkuxkx.newstart'
|
994
|
+
|
995
|
+
elif len(args) >= 3:
|
959
996
|
session_name = args[0]
|
960
997
|
session_host = args[1]
|
961
998
|
session_port = int(args[2])
|
@@ -968,7 +1005,7 @@ class PyMudApp:
|
|
968
1005
|
nothandle = False
|
969
1006
|
|
970
1007
|
if nothandle:
|
971
|
-
self.set_status(
|
1008
|
+
self.set_status(errmsg)
|
972
1009
|
|
973
1010
|
def enter_pressed(self, buffer: Buffer):
|
974
1011
|
"命令行回车按键处理"
|
@@ -1162,21 +1199,6 @@ class PyMudApp:
|
|
1162
1199
|
plugin.onSessionCreate(session)
|
1163
1200
|
|
1164
1201
|
|
1165
|
-
def
|
1202
|
+
def startApp(cfg_data = None):
|
1166
1203
|
app = PyMudApp(cfg_data)
|
1167
1204
|
app.run()
|
1168
|
-
|
1169
|
-
if __name__ == "__main__":
|
1170
|
-
|
1171
|
-
cfg = "pymud.cfg"
|
1172
|
-
import sys
|
1173
|
-
args = sys.argv
|
1174
|
-
if len(args) > 1:
|
1175
|
-
cfg = args[1]
|
1176
|
-
|
1177
|
-
if os.path.exists(cfg):
|
1178
|
-
with open(cfg, "r", encoding="utf8", errors="ignore") as fp:
|
1179
|
-
cfg_data = json.load(fp)
|
1180
|
-
main(cfg_data)
|
1181
|
-
else:
|
1182
|
-
main()
|
pymud/session.py
CHANGED
@@ -8,7 +8,7 @@ from logging.handlers import QueueHandler, QueueListener
|
|
8
8
|
from .logger import Logger
|
9
9
|
from .extras import SessionBuffer, DotDict, Plugin
|
10
10
|
from .protocol import MudClientProtocol
|
11
|
-
from .objects import Trigger, Alias, Command, Timer, SimpleAlias, SimpleTrigger, SimpleTimer, GMCPTrigger, CodeBlock, CodeLine
|
11
|
+
from .objects import BaseObject, Trigger, Alias, Command, Timer, SimpleAlias, SimpleTrigger, SimpleTimer, GMCPTrigger, CodeBlock, CodeLine
|
12
12
|
from .settings import Settings
|
13
13
|
|
14
14
|
|
@@ -29,13 +29,14 @@ class Session:
|
|
29
29
|
|
30
30
|
"""
|
31
31
|
#_esc_regx = re.compile("\x1b\\[[^mz]+[mz]")
|
32
|
-
_esc_regx = re.compile("\x1b
|
32
|
+
_esc_regx = re.compile(r"\x1b\[[\d;]+[abcdmz]", flags = re.IGNORECASE)
|
33
33
|
|
34
34
|
_sys_commands = (
|
35
35
|
"help",
|
36
36
|
"exit",
|
37
37
|
"close",
|
38
38
|
"connect", # 连接到服务器
|
39
|
+
"disconnect", # 从服务器断开连接
|
39
40
|
|
40
41
|
"info", # 输出蓝色info
|
41
42
|
"warning", # 输出黄色warning
|
@@ -89,6 +90,7 @@ class Session:
|
|
89
90
|
"var" : "variable",
|
90
91
|
"rep" : "repeat",
|
91
92
|
"con" : "connect",
|
93
|
+
"dis" : "disconnect",
|
92
94
|
"wa" : "wait",
|
93
95
|
"mess": "message",
|
94
96
|
"action": "trigger",
|
@@ -808,7 +810,7 @@ class Session:
|
|
808
810
|
示例:
|
809
811
|
.. code:: Python
|
810
812
|
|
811
|
-
session.addAlias(SimpleAlias(self.session, "^cb\s(\S+)\s(\S+)", "#3 get %1 from jinnang;#wa 250;combine gem;#wa 250;pack gem", id = "ali_combine"))
|
813
|
+
session.addAlias(SimpleAlias(self.session, r"^cb\s(\S+)\s(\S+)", "#3 get %1 from jinnang;#wa 250;combine gem;#wa 250;pack gem", id = "ali_combine"))
|
812
814
|
session.exec("cb j1a")
|
813
815
|
"""
|
814
816
|
name = name or self.name
|
@@ -1141,31 +1143,100 @@ class Session:
|
|
1141
1143
|
|
1142
1144
|
return counts
|
1143
1145
|
|
1144
|
-
def _addObjects(self, objs: dict, cls: type):
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
def
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1146
|
+
# def _addObjects(self, objs: dict, cls: type):
|
1147
|
+
# if cls == Alias:
|
1148
|
+
# self._aliases.update(objs)
|
1149
|
+
# elif cls == Command:
|
1150
|
+
# self._commands.update(objs)
|
1151
|
+
# elif cls == Trigger:
|
1152
|
+
# self._triggers.update(objs)
|
1153
|
+
# elif cls == Timer:
|
1154
|
+
# self._timers.update(objs)
|
1155
|
+
# elif cls == GMCPTrigger:
|
1156
|
+
# self._gmcp.update(objs)
|
1157
|
+
|
1158
|
+
def _addObjects(self, objs):
|
1159
|
+
if isinstance(objs, list) or isinstance(objs, tuple):
|
1160
|
+
for item in objs:
|
1161
|
+
self._addObject(item)
|
1162
|
+
|
1163
|
+
elif isinstance(objs, dict):
|
1164
|
+
for key, item in objs.items():
|
1165
|
+
if isinstance(item, BaseObject):
|
1166
|
+
if key != item.id:
|
1167
|
+
self.warning(f'对象 {item} 字典键值 {key} 与其id {item.id} 不一致,将丢弃键值,以其id添加到会话中...')
|
1168
|
+
|
1169
|
+
self._addObject(item)
|
1170
|
+
|
1171
|
+
# def _addObject(self, obj, cls: type):
|
1172
|
+
# #if type(obj) == cls:
|
1173
|
+
# if isinstance(obj, cls):
|
1174
|
+
# if cls == Alias:
|
1175
|
+
# self._aliases[obj.id] = obj
|
1176
|
+
# elif cls == Command:
|
1177
|
+
# self._commands[obj.id] = obj
|
1178
|
+
# elif cls == Trigger:
|
1179
|
+
# self._triggers[obj.id] = obj
|
1180
|
+
# elif cls == Timer:
|
1181
|
+
# self._timers[obj.id] = obj
|
1182
|
+
# elif cls == GMCPTrigger:
|
1183
|
+
# self._gmcp[obj.id] = obj
|
1184
|
+
|
1185
|
+
def _addObject(self, obj):
|
1186
|
+
if isinstance(obj, Alias):
|
1187
|
+
self._aliases[obj.id] = obj
|
1188
|
+
elif isinstance(obj, Command):
|
1189
|
+
self._commands[obj.id] = obj
|
1190
|
+
elif isinstance(obj, Trigger):
|
1191
|
+
self._triggers[obj.id] = obj
|
1192
|
+
elif isinstance(obj, Timer):
|
1193
|
+
self._timers[obj.id] = obj
|
1194
|
+
elif isinstance(obj, GMCPTrigger):
|
1195
|
+
self._gmcp[obj.id] = obj
|
1196
|
+
|
1197
|
+
def addObject(self, obj: BaseObject):
|
1198
|
+
"""
|
1199
|
+
向会话中增加单个对象,可直接添加 Alias, Trigger, GMCPTrigger, Command, Timer 或它们的子类
|
1200
|
+
|
1201
|
+
:param obj: 特定对象本身,可以为 Alias, Trigger, GMCPTrigger, Command, Timer 或其子类
|
1202
|
+
|
1203
|
+
示例:
|
1204
|
+
.. code:: Python
|
1205
|
+
|
1206
|
+
class Configuration:
|
1207
|
+
def __init__(self, session):
|
1208
|
+
self.session = session
|
1209
|
+
|
1210
|
+
self.session.addObject(SimpleAlias(session, r'^gta$', 'get all'),)
|
1211
|
+
self.session.addObject(SimpleTrigger(session, r'^[> ]*你嘻嘻地笑了起来.+', 'haha'))
|
1212
|
+
self.session.addObject(SimpleTimer(session, 'xixi', timeout = 10))
|
1213
|
+
|
1214
|
+
"""
|
1215
|
+
self._addObject(obj)
|
1216
|
+
|
1217
|
+
def addObjects(self, objs):
|
1218
|
+
"""
|
1219
|
+
向会话中增加多个对象,可直接添加 Alias, Trigger, GMCPTrigger, Command, Timer 或它们的子类的元组、列表或者字典(保持兼容性)
|
1220
|
+
|
1221
|
+
:param objs: 多个特定对象组成的元组、列表或者字典,可以为 Alias, Trigger, GMCPTrigger, Command, Timer 或其子类
|
1222
|
+
|
1223
|
+
示例:
|
1224
|
+
.. code:: Python
|
1225
|
+
|
1226
|
+
class Configuration:
|
1227
|
+
def __init__(self, session):
|
1228
|
+
self.session = session
|
1229
|
+
|
1230
|
+
self.objs = [
|
1231
|
+
SimpleAlias(session, r'^gta$', 'get all;xixi'),
|
1232
|
+
SimpleTrigger(session, r'^[> ]*你嘻嘻地笑了起来.+', 'haha'),
|
1233
|
+
SimpleTimer(session, 'xixi', timeout = 10)
|
1234
|
+
]
|
1235
|
+
|
1236
|
+
self.session.addObjects(self.objs)
|
1237
|
+
|
1238
|
+
"""
|
1239
|
+
self._addObjects(objs)
|
1169
1240
|
|
1170
1241
|
def _delObject(self, id, cls: type):
|
1171
1242
|
if cls == Alias:
|
@@ -1175,16 +1246,103 @@ class Session:
|
|
1175
1246
|
elif cls == Trigger:
|
1176
1247
|
self._triggers.pop(id, None)
|
1177
1248
|
elif cls == Timer:
|
1178
|
-
self._timers.pop(id, None)
|
1249
|
+
timer = self._timers.pop(id, None)
|
1250
|
+
if isinstance(timer, Timer):
|
1251
|
+
timer.enabled = False
|
1179
1252
|
elif cls == GMCPTrigger:
|
1180
1253
|
self._gmcp.pop(id, None)
|
1181
1254
|
|
1255
|
+
# def _delObject(self, obj):
|
1256
|
+
# if isinstance(obj, Alias):
|
1257
|
+
# self._aliases.pop(obj.id, None)
|
1258
|
+
# elif isinstance(obj, Command):
|
1259
|
+
# self._commands.pop(obj.id, None)
|
1260
|
+
# elif isinstance(obj, Trigger):
|
1261
|
+
# self._triggers.pop(obj.id, None)
|
1262
|
+
# elif isinstance(obj, Timer):
|
1263
|
+
# self._timers.pop(obj.id, None)
|
1264
|
+
# elif isinstance(obj, GMCPTrigger):
|
1265
|
+
# self._gmcp.pop(obj.id, None)
|
1266
|
+
|
1182
1267
|
def _delObjects(self, ids: Iterable, cls: type):
|
1183
1268
|
"删除多个指定元素"
|
1184
1269
|
for id in ids:
|
1185
1270
|
self._delObject(id, cls)
|
1186
1271
|
|
1187
|
-
def
|
1272
|
+
def delObject(self, obj):
|
1273
|
+
"""
|
1274
|
+
从会话中移除一个对象,可直接删除 Alias, Trigger, GMCPTrigger, Command, Timer 或它们的子类本身
|
1275
|
+
|
1276
|
+
:param obj: 要删除的多个特定对象组成的元组、列表或者字典,可以为 Alias, Trigger, GMCPTrigger, Command, Timer 或其子类
|
1277
|
+
|
1278
|
+
示例:
|
1279
|
+
.. code:: Python
|
1280
|
+
|
1281
|
+
class Configuration:
|
1282
|
+
def __init__(self, session):
|
1283
|
+
self.session = session
|
1284
|
+
|
1285
|
+
ali = Alias(session, "s", "south", id = "my_ali1")
|
1286
|
+
|
1287
|
+
# 以下几种方式均可将该别名添加到会话
|
1288
|
+
session.addObject(ali)
|
1289
|
+
session.addAlias(ali)
|
1290
|
+
|
1291
|
+
# 以下三种方式均可以删除该别名
|
1292
|
+
session.delObjec(ali)
|
1293
|
+
session.delAlias(ali)
|
1294
|
+
session.delAlias("my_ali1")
|
1295
|
+
|
1296
|
+
"""
|
1297
|
+
if isinstance(obj, Alias):
|
1298
|
+
self._aliases.pop(obj.id, None)
|
1299
|
+
elif isinstance(obj, Command):
|
1300
|
+
self._commands.pop(obj.id, None)
|
1301
|
+
elif isinstance(obj, Trigger):
|
1302
|
+
self._triggers.pop(obj.id, None)
|
1303
|
+
elif isinstance(obj, Timer):
|
1304
|
+
timer = self._timers.pop(obj.id, None)
|
1305
|
+
if isinstance(timer, Timer):
|
1306
|
+
timer.enabled = False
|
1307
|
+
elif isinstance(obj, GMCPTrigger):
|
1308
|
+
self._gmcp.pop(obj.id, None)
|
1309
|
+
|
1310
|
+
def delObjects(self, objs):
|
1311
|
+
"""
|
1312
|
+
从会话中移除一组对象,可直接删除 Alias, Trigger, GMCPTrigger, Command, Timer 或它们的子类的元组、列表或者字典(保持兼容性)
|
1313
|
+
|
1314
|
+
:param objs: 要删除的对象本身,可以为 Alias, Trigger, GMCPTrigger, Command, Timer 或它们的子类
|
1315
|
+
|
1316
|
+
示例:
|
1317
|
+
|
1318
|
+
.. code:: Python
|
1319
|
+
|
1320
|
+
class Configuration:
|
1321
|
+
def __init__(self, session):
|
1322
|
+
self.session = session
|
1323
|
+
|
1324
|
+
self.objs = [
|
1325
|
+
SimpleAlias(session, r'^gta$', 'get all;xixi'),
|
1326
|
+
SimpleTrigger(session, r'^[> ]*你嘻嘻地笑了起来.+', 'haha'),
|
1327
|
+
SimpleTimer(session, 'xixi', timeout = 10)
|
1328
|
+
]
|
1329
|
+
|
1330
|
+
self.session.addObjects(self.objs)
|
1331
|
+
|
1332
|
+
def __unload__(self):
|
1333
|
+
"卸载本模块时,删除所有本模块添加的对象"
|
1334
|
+
self.session.delObjects(self.objs)
|
1335
|
+
|
1336
|
+
"""
|
1337
|
+
if isinstance(objs, list) or isinstance(objs, tuple):
|
1338
|
+
for item in objs:
|
1339
|
+
self.delObject(item)
|
1340
|
+
|
1341
|
+
elif isinstance(objs, dict):
|
1342
|
+
for key, item in objs.items():
|
1343
|
+
self.delObject(item)
|
1344
|
+
|
1345
|
+
def addAliases(self, alis):
|
1188
1346
|
"""
|
1189
1347
|
向会话中增加多个别名
|
1190
1348
|
|
@@ -1205,55 +1363,55 @@ class Session:
|
|
1205
1363
|
self._aliases['my_ali2'] = SimpleAlias(self.session, "s", "south", id = "my_ali2")
|
1206
1364
|
self.session.addAliases(self._aliases)
|
1207
1365
|
"""
|
1208
|
-
self._addObjects(alis
|
1366
|
+
self._addObjects(alis)
|
1209
1367
|
|
1210
|
-
def addCommands(self, cmds
|
1368
|
+
def addCommands(self, cmds):
|
1211
1369
|
"""
|
1212
1370
|
向会话中增加多个命令。使用方法与 addAliases 类似。
|
1213
1371
|
|
1214
1372
|
:param cmds: 多个命令的字典。字典 key 应为每个命令的 id。
|
1215
1373
|
"""
|
1216
|
-
self._addObjects(cmds
|
1374
|
+
self._addObjects(cmds)
|
1217
1375
|
|
1218
|
-
def addTriggers(self, tris
|
1376
|
+
def addTriggers(self, tris):
|
1219
1377
|
"""
|
1220
1378
|
向会话中增加多个触发器。使用方法与 addAliases 类似。
|
1221
1379
|
|
1222
1380
|
:param tris: 多个触发器的字典。字典 key 应为每个触发器的 id。
|
1223
1381
|
"""
|
1224
|
-
self._addObjects(tris
|
1382
|
+
self._addObjects(tris)
|
1225
1383
|
|
1226
|
-
def addGMCPs(self, gmcps
|
1384
|
+
def addGMCPs(self, gmcps):
|
1227
1385
|
"""
|
1228
1386
|
向会话中增加多个GMCPTrigger。使用方法与 addAliases 类似。
|
1229
1387
|
|
1230
1388
|
:param gmcps: 多个GMCPTrigger的字典。字典 key 应为每个GMCPTrigger的 id。
|
1231
1389
|
"""
|
1232
|
-
self._addObjects(gmcps
|
1390
|
+
self._addObjects(gmcps)
|
1233
1391
|
|
1234
|
-
def addTimers(self, tis
|
1392
|
+
def addTimers(self, tis):
|
1235
1393
|
"""
|
1236
1394
|
向会话中增加多个定时器。使用方法与 addAliases 类似。
|
1237
1395
|
|
1238
1396
|
:param tis: 多个定时器的字典。字典 key 应为每个定时器的 id。
|
1239
1397
|
"""
|
1240
|
-
self._addObjects(tis
|
1398
|
+
self._addObjects(tis)
|
1241
1399
|
|
1242
|
-
def addAlias(self, ali
|
1400
|
+
def addAlias(self, ali):
|
1243
1401
|
"""
|
1244
1402
|
向会话中增加一个别名。
|
1245
1403
|
|
1246
1404
|
:param ali: 要增加的别名对象,应为 Alias 类型或其子类
|
1247
1405
|
"""
|
1248
|
-
self._addObject(ali
|
1406
|
+
self._addObject(ali)
|
1249
1407
|
|
1250
|
-
def addCommand(self, cmd
|
1408
|
+
def addCommand(self, cmd):
|
1251
1409
|
"""
|
1252
1410
|
向会话中增加一个命令。
|
1253
1411
|
|
1254
1412
|
:param cmd: 要增加的命令对象,应为 Command 类型或其子类
|
1255
1413
|
"""
|
1256
|
-
self._addObject(cmd
|
1414
|
+
self._addObject(cmd)
|
1257
1415
|
|
1258
1416
|
def addTrigger(self, tri: Trigger):
|
1259
1417
|
"""
|
@@ -1261,7 +1419,7 @@ class Session:
|
|
1261
1419
|
|
1262
1420
|
:param tri: 要增加的触发器对象,应为 Trigger 类型或其子类
|
1263
1421
|
"""
|
1264
|
-
self._addObject(tri
|
1422
|
+
self._addObject(tri)
|
1265
1423
|
|
1266
1424
|
def addTimer(self, ti: Timer):
|
1267
1425
|
"""
|
@@ -1269,7 +1427,7 @@ class Session:
|
|
1269
1427
|
|
1270
1428
|
:param ti: 要增加的定时器对象,应为 Timer 类型或其子类
|
1271
1429
|
"""
|
1272
|
-
self._addObject(ti
|
1430
|
+
self._addObject(ti)
|
1273
1431
|
|
1274
1432
|
def addGMCP(self, gmcp: GMCPTrigger):
|
1275
1433
|
"""
|
@@ -1278,7 +1436,7 @@ class Session:
|
|
1278
1436
|
:param gmcp: 要增加的GMCP触发器对象,应为 GMCPTrigger 类型或其子类
|
1279
1437
|
"""
|
1280
1438
|
|
1281
|
-
self._addObject(gmcp
|
1439
|
+
self._addObject(gmcp)
|
1282
1440
|
|
1283
1441
|
def delAlias(self, ali):
|
1284
1442
|
"""
|
@@ -1397,7 +1555,7 @@ class Session:
|
|
1397
1555
|
for ti in ti_s:
|
1398
1556
|
self.delTimer(ti)
|
1399
1557
|
|
1400
|
-
def delGMCP(self, gmcp
|
1558
|
+
def delGMCP(self, gmcp):
|
1401
1559
|
"""
|
1402
1560
|
从会话中移除一个GMCP触发器,可接受 GMCPTrigger 对象或其的id。使用方法与 delAlias 类似
|
1403
1561
|
|
@@ -1713,6 +1871,7 @@ class Session:
|
|
1713
1871
|
该函数不应该在代码中直接调用。
|
1714
1872
|
|
1715
1873
|
相关命令:
|
1874
|
+
- #disconnect
|
1716
1875
|
- #close
|
1717
1876
|
- #exit
|
1718
1877
|
'''
|
@@ -1734,6 +1893,18 @@ class Session:
|
|
1734
1893
|
|
1735
1894
|
self.info("已经与服务器连接了 {}".format(time_msg))
|
1736
1895
|
|
1896
|
+
def handle_disconnect(self, code: CodeLine = None, *args, **kwargs):
|
1897
|
+
'''
|
1898
|
+
嵌入命令 #disconnect / #dis 的执行函数,断开到远程服务器的连接(仅当远程服务器已连接时有效)。
|
1899
|
+
该函数不应该在代码中直接调用。
|
1900
|
+
|
1901
|
+
相关命令:
|
1902
|
+
- #connect
|
1903
|
+
- #close
|
1904
|
+
'''
|
1905
|
+
|
1906
|
+
self.disconnect()
|
1907
|
+
|
1737
1908
|
def handle_variable(self, code: CodeLine = None, *args, **kwargs):
|
1738
1909
|
'''
|
1739
1910
|
嵌入命令 #variable / #var 的执行函数,操作会话变量。
|
@@ -1967,7 +2138,7 @@ class Session:
|
|
1967
2138
|
self.info("创建Timer {} 成功: {}".format(ti.id, ti.__repr__()))
|
1968
2139
|
|
1969
2140
|
def handle_alias(self, code: CodeLine = None, *args, **kwargs):
|
1970
|
-
|
2141
|
+
"""
|
1971
2142
|
嵌入命令 #alias / #ali 的执行函数,操作别名。该命令可以不带参数、带一个参数或者两个参数。
|
1972
2143
|
该函数不应该在代码中直接调用。
|
1973
2144
|
|
@@ -1998,7 +2169,7 @@ class Session:
|
|
1998
2169
|
- #trigger
|
1999
2170
|
- #timer
|
2000
2171
|
- #command
|
2001
|
-
|
2172
|
+
"""
|
2002
2173
|
|
2003
2174
|
self._handle_objs("Alias", self._aliases, *code.code[2:])
|
2004
2175
|
|
@@ -2393,10 +2564,11 @@ class Session:
|
|
2393
2564
|
mod = self._modules[module_name]["module"]
|
2394
2565
|
config = self._modules[module_name]["config"]
|
2395
2566
|
if config:
|
2396
|
-
if hasattr(config, "unload"):
|
2397
|
-
unload = getattr(config, "unload", None)
|
2567
|
+
if hasattr(config, "__unload__") or hasattr(config, "unload"):
|
2568
|
+
unload = getattr(config, "__unload__", None) or getattr(config, "unload", None)
|
2398
2569
|
if callable(unload):
|
2399
|
-
unload(
|
2570
|
+
unload()
|
2571
|
+
|
2400
2572
|
del config
|
2401
2573
|
mod = importlib.reload(mod)
|
2402
2574
|
if hasattr(mod, 'Configuration'):
|
@@ -2436,10 +2608,10 @@ class Session:
|
|
2436
2608
|
mod = self._modules[module_name]["module"]
|
2437
2609
|
config = self._modules[module_name]["config"]
|
2438
2610
|
if config:
|
2439
|
-
if hasattr(config, "unload"):
|
2440
|
-
unload = getattr(config, "unload", None)
|
2611
|
+
if hasattr(config, "__unload__") or hasattr(config, "unload"):
|
2612
|
+
unload = getattr(config, "__unload__", None) or getattr(config, "unload", None)
|
2441
2613
|
if callable(unload):
|
2442
|
-
unload(
|
2614
|
+
unload()
|
2443
2615
|
|
2444
2616
|
del config
|
2445
2617
|
del mod
|
pymud/settings.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pymud
|
3
|
-
Version: 0.20.
|
3
|
+
Version: 0.20.0a3
|
4
4
|
Summary: a MUD Client written in Python
|
5
5
|
Author-email: "newstart@pkuxkx" <crapex@crapex.cc>
|
6
6
|
Maintainer-email: "newstart@pkuxkx" <crapex@crapex.cc>
|
@@ -694,6 +694,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
694
694
|
Classifier: Programming Language :: Python :: 3.9
|
695
695
|
Classifier: Programming Language :: Python :: 3.10
|
696
696
|
Classifier: Programming Language :: Python :: 3.11
|
697
|
+
Classifier: Programming Language :: Python :: 3.12
|
697
698
|
Classifier: Programming Language :: Python :: 3 :: Only
|
698
699
|
Requires-Python: >=3.7
|
699
700
|
Description-Content-Type: text/markdown
|
@@ -982,3 +983,15 @@ Requires-Dist: prompt-toolkit
|
|
982
983
|
+ 问题修复: 关闭会话时未关闭相关记录器,导致后续会话无法启动
|
983
984
|
+ 问题修复: MacOS下 python -m pymud init 创建目录报错的问题。同时,将所有系统上的默认目录均使用 ~/pkuxkx (影响windows)
|
984
985
|
+ 功能新增: Session类新增waitfor函数,用于执行一段代码后立即等待某个触发器的情况,简化原三行代码写法
|
986
|
+
|
987
|
+
### 0.20.0 (2024-08-XX)
|
988
|
+
+ 功能调整: 将模块主入口函数从__main__.py中移动到main.py中,以使可以在当前目录下,可直接使用pymud,也可使用python -m pymud启动
|
989
|
+
+ 问题修复: 修复部分正则表达式书写错误问题
|
990
|
+
+ 功能调整: Session类的addTriggers等方法接受的dict中,会将对象本身id作为会话处理id。当该id与key不一致时,会同时显示警告。
|
991
|
+
+ 功能新增: Session类新增addObject, addObjects, delObject, delObjects用于操作别名、定时器、触发器、GMCP触发器、命令等对象。
|
992
|
+
+ 功能新增: 主模块卸载现在既可以定义在__unload__方法中,也可以定义在unload方法中
|
993
|
+
+ 问题修复: 修复原unload方法不能正确卸载的问题
|
994
|
+
+ 功能新增: 命令行参数增加指定启动目录的功能,参数为 -s, --startup_dir。即可以从任意目录通过指定脚本目录方式启动PyMUD了。例如, PS C:\> pymud -s d:\prog\pkuxkx 相当于 PS D:\prog\pkuxk> pymud
|
995
|
+
+ 功能新增: 增加 #disconnect, #dis 命令,可以使当前会话从服务器断开。相当于操作菜单 会话->断开连接
|
996
|
+
+ 功能新增: #session 命令增加快捷创建会话功能,假如已有快捷菜单 世界->pkuxkx->newstart , 则可以通过 #session pkuxkx.newstart 直接创建该会话,效果等同于点击该菜单
|
997
|
+
+ 功能调整: 点击菜单创建会话时,若会话已存在,则将该会话切换为当前会话
|
@@ -0,0 +1,18 @@
|
|
1
|
+
pymud/__init__.py,sha256=hvX7Ga2xPG9J3ZpxBLrC6BvrzUo-Dj26HsRKf41Brhw,533
|
2
|
+
pymud/__main__.py,sha256=hFzZjadLlcOuoLM7D8wFiFVO8mqF7vMuo9y-9xfIhRc,64
|
3
|
+
pymud/dialogs.py,sha256=D0ZtCeoBchF5eYzXumkOi3p-maCQZu4v9-wJgxQ790o,6500
|
4
|
+
pymud/extras.py,sha256=QwWwLavVtuXfg0Qb0f_040va1_kej27P-ZB_19HB6Qk,42422
|
5
|
+
pymud/logger.py,sha256=elYfbpvmKYJfB-rnPYZWY5r8ROu9yja9t-dBi1faRGc,5358
|
6
|
+
pymud/main.py,sha256=wpL1t88qcnYDq1vyguj2NOMpD9yVgZeuAJSMWEbDeiI,6532
|
7
|
+
pymud/objects.py,sha256=0aUc-PZfVSdYPEAamY0eO6k3P9wJcw6PNxfSE8eZZeE,38072
|
8
|
+
pymud/pkuxkx.py,sha256=vWXHU6GF0HQ0eWb3LmxFVRP0cKnigffCX7Z-LJvwVtw,11496
|
9
|
+
pymud/protocol.py,sha256=QfDXjlg2OcJXmVoXf_3mAemnYotRXDUlEZNQjhkfXdA,49106
|
10
|
+
pymud/pymud.py,sha256=N9WxaHDqqsTWIBG8UJ38gdMC_pQ30wphcN2LtT66eA4,49584
|
11
|
+
pymud/session.py,sha256=Ea5pqFFMQ1NWct51g3LCWpyVzM83puFzLhdE7I4WEy4,129768
|
12
|
+
pymud/settings.py,sha256=CRNpHl4RjOuQYzAIWyUEvOo7q-f4lo01X1v_CriHWO4,7145
|
13
|
+
pymud-0.20.0a3.dist-info/LICENSE.txt,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
14
|
+
pymud-0.20.0a3.dist-info/METADATA,sha256=rXogwgamQhQ1geFAq3eH-Vyi2m521g2vevHm9XEf3Rg,70341
|
15
|
+
pymud-0.20.0a3.dist-info/WHEEL,sha256=nCVcAvsfA9TDtwGwhYaRrlPhTLV9m-Ga6mdyDtuwK18,91
|
16
|
+
pymud-0.20.0a3.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
|
17
|
+
pymud-0.20.0a3.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
|
18
|
+
pymud-0.20.0a3.dist-info/RECORD,,
|
pymud-0.20.0a2.dist-info/RECORD
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
pymud/__init__.py,sha256=Ep6JrWv2wwlLV5nI7F6BOA7Ei6yVgnxvhIRwFGPr2Oc,501
|
2
|
-
pymud/__main__.py,sha256=vE5mi5WFyiUPGLfq-1sMrEpHoD2Vxiy5XXenmoXFA1c,6230
|
3
|
-
pymud/dialogs.py,sha256=D0ZtCeoBchF5eYzXumkOi3p-maCQZu4v9-wJgxQ790o,6500
|
4
|
-
pymud/extras.py,sha256=QwWwLavVtuXfg0Qb0f_040va1_kej27P-ZB_19HB6Qk,42422
|
5
|
-
pymud/logger.py,sha256=39I_rFBU5MEiOTJyU7GAy9cY_MpYHKiXNgBhpokQrTA,5358
|
6
|
-
pymud/objects.py,sha256=0aUc-PZfVSdYPEAamY0eO6k3P9wJcw6PNxfSE8eZZeE,38072
|
7
|
-
pymud/pkuxkx.py,sha256=vWXHU6GF0HQ0eWb3LmxFVRP0cKnigffCX7Z-LJvwVtw,11496
|
8
|
-
pymud/protocol.py,sha256=QfDXjlg2OcJXmVoXf_3mAemnYotRXDUlEZNQjhkfXdA,49106
|
9
|
-
pymud/pymud.py,sha256=yAd6nz_ltM3B0fDwMGvaa-tpMlZycZEGJ5E4rZb9Nx4,48235
|
10
|
-
pymud/session.py,sha256=Q1ylk9-5tZGI4maMfDRqzq8Ca6vzG4SivzjxfrpUk84,122932
|
11
|
-
pymud/settings.py,sha256=3FDAgW97SEQfWb9HR6n2U-rQYKxclQXnfaRuo2o0ly0,7147
|
12
|
-
pymud-0.20.0a2.dist-info/LICENSE.txt,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
13
|
-
pymud-0.20.0a2.dist-info/METADATA,sha256=eFQxv8YNREut-zvVzsCf7uAfM3DAxFOi_vvX4uQITCA,68829
|
14
|
-
pymud-0.20.0a2.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
15
|
-
pymud-0.20.0a2.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
|
16
|
-
pymud-0.20.0a2.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
|
17
|
-
pymud-0.20.0a2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|