跳转至内容

世界

本论坛之外的主题。此处表达的观点和意见可能不代表本论坛及其成员的立场。

海量内容尽在指尖 …

不妨将此视为您专属的全球发现信息流。它汇集了来自互联网各处及其他社区的有趣讨论,一应俱全。

虽然您可以浏览当前的热门内容,但使用该信息流的最佳方式是将其个性化。通过注册账号,您可以关注特定的创作者和主题,从而过滤掉无关信息,只查看对您真正重要的内容。

准备好开始了吗?注册一个账号,即可关注他人、在收到回复时获得通知,并收藏您喜欢的内容。

注册 登录
  • N

    对PyMUD的脚本调试设置其实很简单,以下是以vscode为例的设置步骤。
    按下图,先将1处,python脚本环境设置为你的venv所在的环境,uv的、venv直接创建的、或者原始的环境都可以,目的是让调试环境找得到python运行程序以及pymud包文件。然后单击2处,切换到调试界面,从3处点击下拉框,见第二张图。
    debug-00.png
    单击上图3处的下拉框。
    屏幕截图 2026-05-21 201807.png
    从这里选择添加配置,自动切换到json编辑配置环境,将新增的配置内容修改为如下即可:

            {
                "name": "PyMUD 调试程序: 脚本",
                "type": "debugpy",
                "request": "launch",
                "module": "pymud",
                "justMyCode": false,
                "console": "integratedTerminal",
            },
    

    关键点1:要将原来调试配置中的 “program: ${file}” 这一行删掉,修改为: "module": "pymud"
    关键点2: 将 "justMyCode" 设置为 false,可以在pymud包中的代码出打断点和监控
    关键点3: console默认为 integratedTerminal,是vscode自己集成的终端中运行,这个也可以修改为externalTerminal,即使用外部终端

    上述设置好之后,给这个调试配置去一个名字,比如我上面就叫 "PyMUD 调试程序: 脚本"。
    然后,重新从图1中3处下拉框选择该调试配置,即可对脚本(以及pymud模块)进行正常调试了。


    实测有效. trae里鼠标支持有问题.vscode正常.
  • 用AI也没有检查出来。不知道咋查。


    tmux.conf配置设置缓存上限?
  • T

    写了删除变量的cmd,@newstart 麻烦过过目,看看有没有问题

    import traceback, re, asyncio
    from pymud import Command, IConfig
    
    class CmdDelVar(Command, IConfig):
        _help = """
        通过命令行删除废弃变量的命令:
            正常指令      含义
            delvar xxx:    删除变量名为'xxx'的变量
            delvar :      删除所有变量
        """
        def __init__(self, session, *args, **kwargs):
            # delvar命令后,删除所有变量
            pattern = r"^(\bdelvar\b)(?:\s+([a-zA-Z_][a-zA-Z0-9_]*))?$"
            kwargs.setdefault("id", "cmd_delvar")
            super().__init__(session, patterns = pattern, *args, **kwargs)
        def __unload__(self):
            super().__unload__()
    
        async def execute(self, cmd, *args, **kwargs):
            """
            执行delvar命令,删除所有变量或指定变量
            """
            try:
                m = re.match(self.patterns, cmd)
                if m:
                    para = list()
                    for i in range(1, 3):
                        if m[i] != None:
                            para.append(m[i])
                    if (len(para) == 2):
                        self.session.delVariable(para[1])
                        self.session.info(f"变量 {para[1]} 已删除")
                    else:
                        var_list = list()
                        for var in self.session.vars.keys():
                            var_list.append(var)
                        for var in var_list:
                            self.session.delVariable(var)
                        self.session.info("所有变量已删除")
            except Exception as e:
                self.error(f"异步执行中遇到异常, {e}, 类型为 {type(e)}")
                self.error(f"异常追踪为: {traceback.format_exc()}")
    

    为啥不直接把.mud删掉完事呢?
  • N

    PYMUD支持使用socks5代理或者本机的特定网络接口进行网络访问,这本来是没问题的,但是对应北侠fullme的时候,原来提供的websocket插件会无法显示图片。使用浏览器打开时,会提示同一个IP为其他IP的角色显示过fullme图片,因此不能正确显示。此时,就需要让websocket插件通过与会话角色对应的代理或者网络设置来进行显示了。修改原 websocket.py 中的 loadAndSenfFullme 的函数代码,改为如下内容,可以使用与会话相同的网络配置来进行图片获取和下载,再使用websocket传送到web端页面上用于显示。只需要修改此处一个函数即可。

    修改后的代码片段如下:

    async def loadAndSendFullme(sender, text_msg: str, fullme_url: str, times: int = 3, combine: bool = False):
        fmadress = fullme_url.split("robot.php?filename=")[-1]
        url = f"http://fullme.pkuxkx.net/robot.php?filename={fmadress}"
        images = []
    
        # 使用与会话相同的网络配置进行图片抓取
        conn = None
        pymudapp = app.pymud
        if isinstance(pymudapp, PyMudApp):
            session = pymudapp.sessions.get(sender)
    
            if isinstance(session, Session):
                if session.proxy:
                    conn = ProxyConnector.from_url(session.proxy)
                elif session.local_address:
                    conn = TCPConnector(local_addr=(session.local_address, 0))
    
        async with ClientSession(connector=conn) as client:
            for i in range(0, times):
                async with client.get(url) as response:
                    if response.status != 200:
                        continue
    
                    text = await response.text()
                    matches = re.search(r'src="\.([^"]+\.jpg)"', text)
                    if not matches:
                        continue
    
                    img_url = "http://fullme.pkuxkx.net" + matches.group(1)
    
                    # 解析URL获取文件名
                    parsed_url = urlparse(img_url)
                    filename = os.path.basename(unquote(parsed_url.path))
                    # 创建fullme目录
                    fullme_dir = os.path.join(os.path.dirname(__file__), 'fullme')#cl
                    os.makedirs(fullme_dir, exist_ok=True)
                    # 本地文件路径
                    local_img_path = os.path.join(fullme_dir, filename)
                    # 下载图片
                    #async with ClientSession(connector=conn) as session:
                    async with client.get(img_url) as img_response:
                        if img_response.status == 200:
                            with open(local_img_path, 'wb') as f:
                                f.write(await img_response.read())
                            # 使用本地路径调用
                            if not combine:
                                await send_message_to_clients(sender, text_msg, local_img_path)
                            else:
                                images.append(local_img_path)
                        else:
                            asyncio.create_task(send_message_to_clients(sender, f"{text_msg} (图片下载失败: HTTP {img_response.status})", ""))
    
                await asyncio.sleep(0.5)
    
        if combine:
            await send_message_to_clients(sender, text_msg, images)
    

    以下是我使用本地IP连接了5个账号,同时使用代理后,利用远端云服务器连接了2个账号时,websocket插件的显示部分。
    QQ_1777790361323.png


    要像上图一样同时监控多个账号的状态,参考以下方法: 使用本帖附带的 websocket 插件 在某一个角色都加载的脚本中,构建一个 overview 函数,并通过调用插件的 sendOverview 方法注册到插件中。示例如下: from pymud import IConfig class AExampleOfOverview(IConfig): def __init__(self, session, *args, **kwargs): ws = self.session.getGlobal("ws") if ws and hasattr(ws, "sendOverview"): ws.sendOverview(self.session, self.overview) # 此函数为关键,返回一个dict,key会作为websocket显示状态的表头,内容在下面 def overview(self): data = dict() data["角色"] = ( f"{self.session.getVariable('name', 'none')}({self.session.getVariable('id', 'id')})" ) # fullme time fullme = int(self.session.getVariable("%fullme", 0)) delta = time.time() - fullme data["FM"] = int(delta // 60) data["发呆"] = int(self.session.idletime // 60) data["位置"] = ( f"{self.session.getVariable('city', '未知地域')}{self.session.getVariable('room', '未知房间')}" ) data["任务"] = self.session.cmds["jobmanager"].currentJob data["状态"] = self.session.cmds["jobmanager"].currentStatus data["忙闲"] = "忙" if self.session.getVariable("is_busy", False) else "闲" data["战斗"] = self.session.getVariable("is_fighting", False) return data 以下是插件最新版本 websocket.2.0.5.zip
  • N

    欢迎补充

    def get_search_place(self, city, room):
            station = ["大车行", "车马商行", "马车行", "车马行", "大车店", "车行", "马车店"]
            if city == "扬州":
                if room == "鹿鼎公长大的地方":
                    room = "丽春院"
                elif room == "衙门里面北院":
                    room = "内宅"
    
            elif city == "衢州":
                if room == "小酒铺":
                    room = "酒铺"
                elif room == "大米店":
                    room = "米铺"
                elif room == "大南门":
                    room = "礼贤门"
                elif room == "大西门":
                    room = "航运门"
                elif room == "铁衢门":
                    room = "迎和门"
                elif room == "府衙正厅":
                    room = "大堂"
                elif room == "余五婆的家":
                    room = "民居"
                elif room == "北门":
                    room = "永清门"
    
            elif city == "潮州":
                if room == "邢捕头常在的地方":
                    room = "中央广场"
                elif room == "青楼":
                    room = "翠红阁"
                elif room in station:
                    room = "潮州车行"
    
            elif city == "代州":
                if room in station:
                    room = "靖边大车店"
    
            elif city == "中原":
                if room in station:
                    room = "中原马车总行"
    
            elif city == "南阳":
                if room in station:
                    room = "南阳车行"
    
            elif city == "上饶":
                if room == "镖局":
                    room = "龙虎镖局"
                elif room == "塔山":
                    room = "武安山"
                elif room in ("试剑处", "葛玄试剑处"):
                    room = "试剑石"
                elif room == "广场":
                    room = "中央广场"
                elif room == "酒铺":
                    room = "酒馆"
    
            elif city == "绍兴府":
                if room in station:
                    room = "绍兴马车行"
                elif room == "府衙":
                    room = "绍兴府衙"
                elif room == "双龙洞内":
                    room = "洞内"
                elif room in ("铁匠铺子", "打铁铺"):
                    room = "铁匠铺"
                elif room == "西施浣纱处":
                    room = "浣纱溪边"
                elif room == "金华火腿店":
                    room = "火腿店"
                elif room == "游龙帮总坛":
                    room = "游龙帮"
    
            elif city == "武当山":
                if room in station:
                    room = "中原马车行"
                elif room == "张三丰闭关处":
                    room = "小屋"
    
            elif city == "临安府":
                if room in station:
                    room = "计氏马车分行"
                elif room == "青楼":
                    room = "怡红馆"
                elif room == "府级官员办公处":
                    room = "临安府大堂"
                elif room in ("韩世忠府大门", "韩世忠府邸门口"):
                    room = "韩王府大门"
    
            elif city == "湖州":
                if room in station:
                    room = "车马行"
    
            elif city == "大同":
                if room in station:
                    room = "大同车行"
    
            elif city == "建康府南城":
                if room == "官府所在":
                    room = "建康府"
                elif room == "青楼":
                    room = "绛云楼"
                elif room in ("宠物商店", "宠物商铺"):
                    room = "建康府南城宠物店"
    
            elif city == "威海卫":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "建康府北城":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "镇江":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "嘉兴":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "处州府":
                if room == "官府所在":
                    room = "大厅"
                elif room in station:
                    room = "马车行"
    
            elif city == "天台山":
                if room == "官府所在":
                    room = "大堂"
    
            elif city == "台州":
                if room == "官府所在":
                    room = "府衙大堂"
    
            elif city == "建宁府":
                if room in station:
                    room = "建宁马车行"
                elif room == "官府所在":
                    room = "府衙"
    
            elif city == "归云庄":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "苏州":
                if room in station:
                    room = "计氏马车分行"
    
            elif city == "无锡":
                if room in station:
                    room = "无锡车马行"
    
            elif city == "南昌":
                if room in station:
                    room = "计氏马车总行"
    
            return "{}{}".format(city, room)
    

    收到,好东西,谢谢分享
  • N

    0.22.5 (2026-05-02)

    • 功能新增: 为Session类型增加 invalidate 方法,调用该方法时,只有本会话是当前会话时,该方法才会调用 PyMudApp.invalidate() 进行刷新。
    • 注意事项: 对于在个人脚本中调用的 session.application.invalidate() 方法,建议改成 session.invalidate()。因为会话的刷新会判断前台,而application的刷新会强制刷新。
    • 功能新增: 增加 lazy 模式,当设置为 lazymode 模式时,即使 PyMudApp.invalidate() 的调用也不会进行显示刷新,系统仅保留在切换会话、以及定时1s材记性刷新。该模式可以通过快捷键F4切换。在lazy模式下,最底下状态栏右侧会显示"LAZY"提示。该模式可以用于在后台挂机运行时,降低CPU占用率。
    • 功能新增: 增加 verbatim 模式,当设置为 verbatim 模式时,所有命令行输入的命令,都不会进行解析,直接发送到服务器。该模式可以通过快捷键F3切换。在 verbatim 模式下,最底下状态栏右侧会显示"VERB"提示。
    • 功能新增: 增加一个非解析提示符"/",当在命令行行首使用该提示符时,所有后续命令不进行任何解析,直接发送到服务器。该提示符可以通过 pymud.cfg 中的 noparser 进行覆盖。此提示符相当于临时使用 verbatim 模式。
    • 功能新增: 增加设置 "cmd_prefix",当配置该参数后,在窗口中的命令回显或者log记录中,输入的命令会带有该前缀。改配置默认为空白,可以通过 pymud.cfg 中的 cmd_prefix 进行覆盖。同步调整了命令的显示样式,与info默认值相同。
    • 功能调整:在#var等命令执行之后,会调用del删除创建的临时列表,以加快内存释放。
    • 功能调整: 在会话被关闭时,会调用del对会话中的相关对象同步进行清除,并使用代码调用执行垃圾回收(但我测试了,并没有啥用处,内存占没什么变化)。
    • 问题修复: 修复了在使用网络配置(包括指定IP和使用socks5代理)连接服务器后,当断开后,再重新执行 #con 不会再次调用网络配置,而是直接使用默认配置的问题。

    English update history is translated by TRAE (GLM5)

    0.22.5 (2026-05-02)

    • New Feature: Added invalidate method to Session class. When called, it only triggers PyMudApp.invalidate() for refresh if the current session is the active session.
    • Note: For session.application.invalidate() calls in personal scripts, it is recommended to change to session.invalidate(). Because session refresh checks for foreground status, while application refresh forces a refresh.
    • New Feature: Added lazy mode. When lazy mode is enabled, even PyMudApp.invalidate() calls will not trigger display refresh. The system only refreshes when switching sessions or on a 1-second timer. This mode can be toggled with the F4 hotkey. In lazy mode, "LAZY" is displayed on the right side of the bottom status bar. This mode can be used to reduce CPU usage when running in the background.
    • New Feature: Added verbatim mode. When verbatim mode is enabled, all commands entered in the command line are sent directly to the server without any parsing. This mode can be toggled with the F3 hotkey. In verbatim mode, "VERB" is displayed on the right side of the bottom status bar.
    • New Feature: Added a non-parsing prefix "/". When this prefix is used at the beginning of a command line, all subsequent commands are sent directly to the server without any parsing. This prefix can be overridden via noparser in pymud.cfg. This prefix is equivalent to temporarily using verbatim mode.
    • New Feature: Added "cmd_prefix" setting. When configured, command echo in the window or log records will display commands with this prefix. Default is empty, can be overridden via cmd_prefix in pymud.cfg. Also adjusted command display style to match the default info style.
    • Improvement: After executing commands like #var, temporary lists created are deleted using del to speed up memory release.
    • Improvement: When a session is closed, related objects in the session are cleared synchronously using del, and garbage collection is triggered programmatically (however, testing showed no significant effect on memory usage).
    • Bug Fix: Fixed the issue where after disconnecting, when you using #con, the default network configuration is used instead of the one you specified.

  • N

    0.22.4 (2026-02-24)

    • 功能新增: 当一台设备拥有多个网卡和IP时,可以指定使用哪个IP进行连接。
    • 功能新增: 支持直接使用socks5代理进行连接。可以支持无需认证的代理(如ssh -D创建的socks5代理),和用户名密码认证的代理。
    • 功能新增: 上述两功能,通过新增的 network 配置字典来实现,也可以在#session, #connect命令中直接指定。使用方式见下方。
    • 问题修复: 修复了提示错误代码时不正确显示函数名、文件名和行数的情况
    • 问题修复: 修复了内存监控启动代码BUG导致无法正常监控的问题
    • 其他变更: 完善修复了所有涉及 basedpyright 提示不符合编码标准的内容,改为更符合编码标准的写法
    • 其他变更: 默认的 remain_last_input 现在设置为 True 了
    • 其他变更: 新版的 SessionBuffer 确认可以正常运行,删除了原来的 SessionBuffer 实现
    • 其他变更: 移除了所有不需要的 import 内容
    • 其他变更: 当所有会话都被关闭后,底下的状态窗口将会清空

    多IP网络/Socks5代理连接使用方法:

    • 首先在pymud.cfg中增加配置字段 network,内容如下(如果复制使用,请删除注释内容):

      {
          // 放在根节点内部即可
          "network" : {
              "ipv6": false,              // 是否启用ipv6,可接受 true|false,默认为false。该设置仅会影响 auto 模式模式,即设置 auto 模式是否会自动获取IPv6地址
              "local_addr": "auto",       // 本地绑定的IP地址,可接受 auto|preset,默认auto,即自动获取本地所有网络设备的IP,当配置为 preset 时,会使用ip_list中的IP
              "ip_list": [                // 当local_addr设置为 preset 时,需要配置该字段,用于指定使用哪个IP进行连接。
                  "192.168.1.100",
                  "192.168.2.100",
              ],
              "proxy": true,              // 是否启用代理,可接受 true|false,默认为false。
              "proxies": {                // Socks5代理列表,可配置多个,即可以使用无密码的代理,也可以使用用户名密码认证的代理。
                  "proxy1": "socks5://192.168.6.66:1080",                         // 使用proxy1标识该无密码代理
                  "proxy2": "socks5://user:password@yoursock5proxy.site:1080",    // 使用proxy2标识该用户名密码认证代理
              }
          }
      }
      
    • 当配置完成后,启动pymud时, 世界菜单中,每一个角色的都会添加一个下级菜单,将IP和代理列表中的代理都添加为子菜单。此时,角色自身菜单,以及下级子菜单都可以单机连接到服务器。

    • 当依然单机角色菜单时,会使用系统当前默认网络设备进行连接。

    • 当点击角色下级菜单中的IP时,会指定绑定该IP进行连接。例如,一台设备有2个网卡,一个连接到电信网络,一个连接到联通网络,即使系统设置默认连接是网卡1电信网络,通过IP绑定也可以使用联通网络连接到服务器。

    • 当点击角色下级菜单中的代理时,会指定使用该代理进行连接。例如,在配置中增加了一个代理 proxy1,当点击角色下级菜单中的 proxy1 时,会使用该代理进行连接。

    • 也可以在#session/#connect命令中指定IP或代理。二者语法相同,都是在最后面增加了 >> 来指定IP或代理。注意,>>之后的IP或者代理之间没有空格。例如:

      • #session pkuxkx.newstart >>#2 # 指定使用ip_list中(当local_addr设置为 preset 时)或自动获取的ip列表(也会显示在菜单上)的第2个(序号从1开始)IP进行连接
      • #session pkuxkx.newstart >>@proxy1 @ 指定使用proxies中配置的proxy1代理进行连接
      • #con >>>#1 # 会话断开后(比如使用#dis命令),可以使用 #con 重新指定以第1个IP连接。
      • #con >>socks5://192.168.6.67:1080 # 也可以在命令直接指定新的socks5代理。(IP只能使用序号指定,不接收手动填入)
    • #con命令也可以使用三个大于号 >>> 来连接。这二者区别在于,当使用 >> 时,该配置会变成本会话的默认配置,下次直接 #con 就是使用该配置;而使用 >>> 时,只是临时指定该配置,下次 #con 还是会使用原先的配置。


  • T

    抛砖引玉,我现在是不会啊,等大佬现身说法


    以下为过程中的一些心得: 1 . 探索地图和使用已经被证明是正确的地图是完全两回事,探索过程中进入任何房间即使所有信息一致,也得证明它是新房间还是已经探明的房间。 2. 房间之间的连接不全都是互逆的,有些出口是单向的。 3. 房间允许看向四周获得信息,这些信息对辅助定位非常重要。把这些可以获得的信息整合到一起,用特定顺序组织后转换为哈希码,作为该房间的身份签名(signature),这个签名有不同的等级,可分为房间名、房间描述+出口、周围房间名+出口、周围房间名+描述+出口,房间签名用于比对两个房间是不是同一个房间。 4. 有些房间并非一成不变的,它可以自己随机变化,比如:骰子房,房间描述随着骰子的变化在不停的变化;有些房间描述会因为玩家的互动而变化。 5. 有些地图中的结构完全对称,即有些房间不但自身签名完全一致而且它周围房间的签名也完全一致,要探索很远才能确定它是哪一个。 6. 有些房间进入需要特定条件或被npc拦截,不过这个基于pymud的命令很好解决。 7. 迷宫内的房间和常规房间完全不同的逻辑,要提前提取迷宫入口特征,把对应的入口识别出来在代码中封住。 8. 深度优先排重需要角色可以回到备选房间,如果附近有单向出口,导致回溯失败会从而测绘出错。 9. 探索过程中对于可通过的连接,必须保证100%可以执行成功,这是探索地图的基石。 10. 如果对游戏了解,知道某些房间是独一无二的,即一旦进入就知道自己的位置,需要提前写进列表中,作为探索地图的锚点。 11. 原则上只相信通过移动而获得的连接,但为提高效率,把那些移动后彼此通过look可以确认互逆方向的房间签名匹配的连接直接写进数据库,而无需实际移动
  • N

    更新方式

    • 请使用 pip install --upgrade pymud 安装更新
    • 由于刚发布,国内镜像站点不一定完成镜像,可以通过 -i https://pypi.org/simple 指定使用pypi官方源

    更新内容

    0.22.2 (2026-01-11)

    • 功能新增: 可以通过.cfg文件指定 "auto_chars" 来定义启动pymud时自动打开的会话。
    • 问题修复: 修复GMCPTrigger类型enabled属性不生效问题。
    • 问题修复: 原本enabled的定时器,修复了在会话断开重连后不会生效的问题。
    • 问题修复: 修复添加/删除系统时钟回调时,可能会导致的异常问题。
    • 问题修复: 修复在增加系统时钟回调时,如果回调函数代码错误产生异常,会导致系统时钟停顿的问题。
    • 功能优化: 优化了SessionBuffer的实现方式,改为环形缓冲+缓存缓冲双缓冲形式,减少运行中内存分配和清除的次数。
    • 功能新增: #var增加了对嵌套变量的显示支持,可以支持list、dict等嵌套类型的变量,详细请查看论坛信息。
    • 功能新增: 增加了#mem/#memory命令以支持内存监控,增加了启动时的-m参数在启动时直接打开内存监控,详细请#help memory或者查看论坛信息。
    • 其他变更: F1快捷键指向的帮助网站修改为官方网站的文档页面 https://www.pymud.cn/doc/

    pymud.cfg文件中配置auto_chars参考用法

    auto_chars是用来控制pymud在运行时自动加载某些角色的。一种使用的场景是,远程挂机的服务器重启后,自动运行pymud,然后自动登录某几个角色。其中,自动运行pymud需要使用操作系统实现,比如使用 .bashrc 指定。

    下面一个pymud.cfg文件示例可以自动登录char1, char3两个角色,需要注意两点:

    • 一是自动登录角色需要 pymud.cfg 中配置菜单中包含这些角色。如下例子在chars中定义了char1,char2,char3三个角色,才可以自动加载char1, char3。

    • 二是自动登录autologin必须要配置好,确保可以自动输入用户名密码。 比如北侠应该配置为 "{0};{1}"

      {
        "sessions": {
          "pkuxkx": {
            "host": "mud.pkuxkx.net",
            "port": "8081",
            "encoding": "utf8",
            "autologin": "{0};{1}",
            "default_script": ["my_entry"],
            "chars": {
              "char1", ["myid1", "mypass1"],
              "char2", ["myid2", "mypass2"],
              "char3", ["myid3", "mypass3"]
            }
          }
        },
        "auto_chars": ["pkuxkx.char1", "pkuxkx.char3"]
      }
      

    内存监控参考用法

    要使用内存监控必须先启用监控。可以通过在运行pymud时指定-m参数,即 "pymud -m" (使用uv时可以用 "uv run pymud -m") 在启动时刻即启用内存监控。也可以在会话中使用 #mem on 命令启动监控。只有在启用后的内存变化才会被系统所捕获。在运行时通过 -m 启动可以捕获更为完整的内存初始情况,但由于内存监控具有一定的性能开销,因此要平衡好监控需求和实际运行。
    当内存监控启用后,可以通过 #mem 命令查看监控到的当前内存的使用情况,可以使用 #mem diff 命令查看此时与上一次的内存使用的变化情况(仅显示top5)。
    内存监控的总数可以按照文件统计,也可以按照代码行位置统计,当未配置时,默认按照文件统计。可以通过 #mem lineno / #mem filename 切换两种统计方式。
    当不需要使用内存监控的时候,可以使用 #mem off 来关闭内存监控。

    以下是几种不同方式下, #mem 和 #mem diff的显示示例:

    #mem命令按filename的显示,从左到右分别为,内存分配块数,占用的内存,文件是属于库(lib)还是自己的脚本(app),文件名的相对路径。
    〔MEMORY〕内存占用最大的5处为:
    〔MEMORY〕   207  0.2 MiB [lib] layout/mouse_handlers.py
    〔MEMORY〕  3453  0.2 MiB [lib] layout/controls.py
    〔MEMORY〕   496  0.2 MiB [lib] layout/screen.py
    〔MEMORY〕  1558  0.1 MiB [lib] layout/containers.py
    〔MEMORY〕  1553  0.1 MiB [lib] pymud/extras.py
    
    #mem diff命令按filename的显示,从左到右的定义与#mem一致,括号中的内容是表示与上一次相比的变化量。
    〔MEMORY〕与上次内存占用对比,变化最大的5处为:
    〔MEMORY〕  3233( +1632)  1.4MiB(  +0.6MiB) [lib] layout/screen.py
    〔MEMORY〕  8361( +3497)  0.7MiB(  +0.3MiB) [lib] pymud/extras.py
    〔MEMORY〕  4735( +1560)  0.6MiB(  +0.2MiB) [lib] layout/containers.py
    〔MEMORY〕  1130(  +753)  0.1MiB(  +0.0MiB) [lib] widgets/menus.py
    〔MEMORY〕   667(  +535)  0.1MiB(  +0.0MiB) [app] script/map/map.py
    
    执行#mem lineno之后,#mem按lineno显示内容,从左到右的定义与前面一致,最末尾增加了行号
    〔MEMORY〕内存占用最大的5处为: 
    〔MEMORY〕   361  1.6 MiB [lib] layout/screen.py, Line 305
    〔MEMORY〕     2  1.3 MiB [lib] prompt_toolkit/cache.py, Line 101
    〔MEMORY〕    67  0.3 MiB [lib] layout/containers.py, Line 2045
    〔MEMORY〕  1501  0.2 MiB [lib] pymud/extras.py, Line 827
    〔MEMORY〕  3865  0.2 MiB [lib] pymud/extras.py, Line 209
    
    #mem diff命令按lineno显示
    〔MEMORY〕与上次内存占用对比,变化最大的5处为:
    〔MEMORY〕   872(  +597)  3.8MiB(  +2.6MiB) [lib] layout/screen.py, Line 305
    〔MEMORY〕     2(    +1)  1.3MiB(  +1.3MiB) [lib] prompt_toolkit/cache.py, Line 101
    〔MEMORY〕 15167(+11210)  1.0MiB(  +0.8MiB) [lib] layout/containers.py, Line 2075
    〔MEMORY〕   140(   +96)  0.6MiB(  +0.4MiB) [lib] layout/containers.py, Line 2045
    〔MEMORY〕  3410( +1890)  0.3MiB(  +0.2MiB) [lib] layout/screen.py, Line 167
    

    #var对嵌套变量的用法

    假设我有一个名为skills的变量,用于保存自己的各项武功,结构是一个dict,内部的每一个key为武功的id,其value为一个tuple,分别表示了当前技能等级、最大技能等级、技能中文名,那么可以使用#var的不同方式及其返回值如下:

    # 假设skills值为如下的复合对象,#var skills会直接会显示该值
    
    'skills' = {
                divination      : (19.0, 1093.0, '占卜之术'),
                evocation       : (14.0, 1093.0, '招魂术'),
                dodge           : (1087.0, 1093.0, '基本轻功'),
                finger          : (1087.0, 1093.0, '基本指法'),
                force           : (981.01, 1093.0, '基本内功'),
                parry           : (1087.0, 1093.0, '基本招架'),
                sword           : (1061.0, 1077.0, '基本剑法'),
                unarmed         : (1087.0, 1093.0, '基本拳脚'),
                beiming-shengong: (980.74, 1093.0, '北冥神功'),
                kurong-changong : (980.0, 1093.0, '枯荣禅功'),
                longxiang-hubu  : (1087.0, 1093.0, '龙骧虎步'),
               }
    
    # 如果使用 #var skills[force],或者 #var skills["force"] (有无引号不影响),则显示为
    
           skills[force] = (981.01, 1093.0, '基本内功')
    
    # 还可以继续嵌套到下一级,比如仅取force的当前等级,可以 #var skills[force][0],则显示为
    
          'skills[force][0]' = 981.01              
    

    不知道为什么现在又可以了 这个功能挺好~~~~
  • N
    usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]
               [-c cipher_spec] [-D [bind_address:]port] [-E log_file]
               [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]
               [-J destination] [-L address] [-l login_name] [-m mac_spec]
               [-O ctl_cmd] [-o option] [-P tag] [-p port] [-Q query_option]
               [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]
               destination [command [argument ...]]
    

    ssh 命令是 Linux/Unix 系统中用于安全远程登录的核心工具,其参数众多,功能强大。

    为了更清晰地理解,我将这些参数按照功能逻辑分为了 连接与身份端口转发认证与密钥会话与调试 以及 版本与配置 五大类进行详细解释。

    1. 连接、目标与身份

    这些参数用于指定你要连接到哪里,以及以谁的身份登录。

    参数 全称/含义 详细解释
    destination 目标主机 核心参数,指定要连接的远程主机。格式通常为 [user@]hostname
    [command] 执行命令 如果指定,将在远程主机上执行该命令后退出,而不是启动交互式 shell。
    -p port 端口 指定远程 SSH 服务监听的端口号(默认是 22)。
    -l login_name 登录名 指定登录远程主机的用户名(例如 ssh -l root host)。
    -4 仅 IPv4 强制 SSH 仅使用 IPv4 地址进行连接。
    -6 仅 IPv6 强制 SSH 仅使用 IPv6 地址进行连接。
    -J destination 跳板/代理跳转 通过一个或多个跳板机(Jump Host)连接到最终目标(例如 ssh -J user@gateway user@final)。

    2. 端口转发与隧道

    SSH 不仅仅是登录,还可以作为安全隧道传输其他数据。

    参数 全称/含义 详细解释
    -L 本地端口转发 将本地的某个端口流量通过 SSH 隧道转发到远程主机的某个地址和端口(例如 -L 8080:localhost:80,本地访问 8080 即访问远程的 80 端口)。
    -R 远程端口转发 将远程主机的某个端口流量通过 SSH 隧道转发回本地(例如 -R 9000:localhost:80,远程访问 9000 即访问本地的 80 端口)。
    -D 动态端口转发 开启 SOCKS 代理服务器。指定本地一个端口,所有发往该端口的流量都会通过 SSH 隧道动态转发。
    -g 网关端口 允许远程主机连接到本地转发的端口(默认情况下,端口转发仅绑定到 localhost,使用此参数可让其他机器连接)。
    -w TUN/TAP 隧道 用于转发网络层(Layer 3)或链路层(Layer 2)的数据包,常用于构建 VPN。

    3. 认证、密钥与代理

    这些参数控制如何证明你的身份。

    参数 全称/含义 详细解释
    -i identity_file 身份文件 指定用于公钥认证的私钥文件(默认是 ~/.ssh/id_rsa 等)。
    -A 启用代理转发 允许将本地的 SSH 代理(ssh-agent)连接转发到远程主机。注意: 这有安全风险,因为远程用户可能利用你的本地密钥进行跳板攻击。
    -a 禁用代理转发 禁止转发认证代理的连接(默认行为)。
    -K GSSAPI 委托 启用基于 GSSAPI(如 Kerberos)的身份验证和凭据转发。
    -k 禁用 GSSAPI 禁用向服务器转发 GSSAPI 凭据。
    -I pkcs11 智能卡/PKCS#11 指定用于与智能卡通信的 PKCS#11 共享库,用于硬件密钥认证。

    4. 会话、控制与调试

    控制终端行为、连接管理和故障排查。

    参数 全称/含义 详细解释
    -t 强制伪终端 强制分配一个伪终端(PTY)。当你需要在远程运行基于屏幕的程序(如 topvim 或菜单脚本)时非常有用。
    -T 禁止分配终端 禁止分配伪终端。适用于执行自动化脚本或传输文件时,防止远程系统分配不必要的资源。
    -f 后台运行 请求 SSH 在执行命令前转入后台运行(通常与 -n 配合使用)。
    -n 重定向 stdin 将标准输入重定向到 /dev/null。通常用于后台运行,防止 SSH 从标准输入读取数据。
    -N 不执行命令 不在远程执行任何命令。通常仅用于端口转发(-L/-R)时,只建立隧道而不打开 shell。
    -v 冗详模式 显示详细的调试信息。-v 显示一级信息,-vvv 显示最详细信息,用于排查连接失败原因。
    -q 安静模式 抑制大部分警告和诊断信息,让输出更干净。
    -e escape_char 转义字符 设置用于退出 SSH 会话的控制字符(默认是 ~)。例如 -e none 会使会话完全透明,禁用转义功能。
    -C 压缩数据 启用压缩(类似 gzip),在慢速网络下可以加速传输,但会增加 CPU 负担。
    -S ctl_path 控制套接字 指定用于连接共享(Connection Multiplexing)的控制套接字路径,允许复用同一个 TCP 连接以加快后续连接速度。

    5. 配置与加密

    指定配置文件和加密算法。

    参数 全称/含义 详细解释
    -F configfile 配置文件 指定一个替代的用户级配置文件(默认是 ~/.ssh/config),而不是使用系统默认配置。
    -o option 配置选项 Key=Value 的形式传递配置指令(例如 ssh -o "StrictHostKeyChecking=no" host),用于设置没有单独命令行开关的选项。
    -c cipher_spec 加密算法 指定会话加密的密码算法(如 aes256-ctr)。OpenSSH 会自动协商,通常无需手动指定。
    -m mac_spec MAC 算法 指定消息认证码(Message Authentication Code)算法,用于确保数据完整性。
    -B bind_interface 绑定接口 在多网卡机器上,指定从哪个本地网络接口发出连接。
    -b bind_address 绑定地址 在多 IP 地址的机器上,指定连接的源 IP 地址。
    -E log_file 日志文件 将调试日志追加到指定文件中,而不是输出到标准错误 stderr。

    💡 补充说明

    • 大小写敏感:注意 -v(小写)是详细模式,而 -V(大写)是显示版本信息并退出。
    • 参数优先级:命令行参数的优先级最高,其次是用户配置文件 (~/.ssh/config),最后是系统配置文件 (/etc/ssh/ssh_config)。
    • 安全性:使用 -A(代理转发)时要非常小心,因为它可能让远程服务器上的恶意用户利用你的本地私钥访问其他服务器。

    按字母顺序排列的详解速查: SSH 客户端参数详解 ssh (Secure Shell) 是一个用于安全远程登录和执行命令的工具。以下参数基于 OpenSSH 客户端。 常用参数概览 ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address] [-c cipher_spec] [-D [bind_address:]port] [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file] [-J destination] [-L address] [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-P tag] [-p port] [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] destination [command [argument ...]] ssh [-Q query_option] 参数详细说明 参数 说明 -4 强制使用 IPv4 地址。 -6 强制使用 IPv6 地址。 -A 启用认证代理转发。允许远程主机通过本地 SSH 代理进行认证。 -a 禁止认证代理转发。 -C 启用压缩。所有数据在传输前都会被压缩。 -f 后台运行。SSH 会在执行命令前转入后台,通常与 -n 配合使用。 -g 允许远程主机连接本地转发的端口。如果不使用此选项,端口转发仅绑定到本地回环地址。 -i identity_file 指定用于公钥认证的私钥文件路径(例如 ~/.ssh/id_rsa)。 -l login_name 指定登录远程主机的用户名。 -N 不执行远程命令。仅用于端口转发。 -n 将标准输入重定向到 /dev/null。通常用于后台运行 SSH。 -p port 指定远程 SSH 服务监听的端口号(默认为 22)。 -q 静默模式。抑制所有警告和诊断信息。 -t 强制分配伪终端。对于运行全屏程序(如 top 或文本菜单)非常有用。 -v 详细模式。打印调试信息。可使用多个 -v(如 -vvv)以增加详细程度。 -X 启用可信的 X11 转发。 -x 禁用 X11 转发。 -Y 启用可信的 X11 转发(比 -X 更宽松的信任级别)。 -y 启用信任的 X11 转发(与 -Y 类似,具体行为可能依赖于实现)。 -B bind_interface 指定 SSH 客户端发送数据包的网络接口。 -b bind_address 在本地主机上绑定指定的源地址(源 IP)发出连接。 -c cipher_spec 指定用于加密会话的加密算法。 -D [bind_address:]port 指定本地动态应用程序级端口转发。SSH 将充当 SOCKS 代理服务器。 -E log_file 将调试日志追加到指定的文件中。 -e escape_char 设置转义字符(默认为 ~)。 -F configfile 指定一个替代的配置文件(默认为 ~/.ssh/config)。 -I pkcs11 指定 PKCS#11 共享库的路径,用于硬件安全密钥。 -J destination 指定跳转主机(Jump Host)。格式为 [user@]host[:port],可指定多个。 -L address 指定本地端口转发。将本地端口映射到远程主机的某个端口。 -m mac_spec 指定用于数据完整性校验的消息认证码(MAC)算法。 -O ctl_cmd 控制一个正在运行的 SSH 多路复用主进程(如 check, exit, stop)。 -o option 以 选项=值 的形式指定配置选项(如 -o StrictHostKeyChecking=no)。 -P tag 与 -Q 一起使用,用于查询特定的配置参数。 -R address 指定远程端口转发。将远程主机的端口映射到本地主机的某个端口。 -S ctl_path 指定用于连接共享的控制套接字路径。 -W host:port 将本地标准输入输出直接连接到远程主机的指定端口。 -w local_tun[:remote_tun] 请求 TUN/TAP 接口转发,用于创建虚拟专用网络(VPN)。 -Q query_option 查询可用的加密算法、MAC 等信息(如 ssh -Q cipher)。 使用示例 基本连接: ssh user@hostname 指定端口: ssh -p 2222 user@hostname 本地端口转发: ssh -L 8080:localhost:80 user@hostname (将本地 8080 转发到远程的 80) 动态端口转发(SOCKS 代理): ssh -D 1080 user@hostname 后台运行并静默: ssh -f -N -L 8080:localhost:80 user@hostname
  • T

    如题,麻烦各位大佬解答


    多谢群主大人~~~~~~
  • N

    大家有谁知道的,贴一下地址
    我现在只知道北大侠客行了 www.pkuxkx.net


    风云五 106.12.197.143:5555
  • H
    from pymud import Session, Command, exception, IConfig, Trigger
    
    class cha_rbz(Command, IConfig):
        def __init__(self, session, *args, **kwargs):
            kwargs.setdefault("id", "cmd_id")
            kwargs.setdefault("group", "cmd")
            super().__init__(session, r"^id( here)?$", *args, **kwargs)
    
            self._items = []
            options = {"enabled": False, "group": "cmd.id", "keepEval": True}
            self._tris = {
                "id_here"     : Trigger(self.session, r"^[> ]*你身上携带物品的别称如下|^[> ]*在这个房间中, 生物及物品的\(英文\)名称如下.*", onSuccess = self.id_here, **options),
                "id_item"     : Trigger(self.session, r"^[> ]*([\u4e00-\u9fa5 ]+)\s+ = (.+)$", onSuccess = self.id_item, **options),
                "stop"        : Trigger(self.session, r"^[> ]*系统回馈:id_is_over = 1", onSuccess = self.stop, **options),
            }
            #[╰└]+  [╯┘]+
        @exception
        async def execute(self, cmd, *args, **kwargs):
            self.reset()
            self._items = []
            #指定的触发器使能,也可以是GROUP使能
            self._tris["id_here"].enabled = True
            self._tris["stop"].enabled = True
            self.session.writeline(f"{cmd}")
            #此处插入一个等待,仅为演示脚本的等待,实际使用中无需等待
            await asyncio.sleep(1)
            self.session.writeline(f"response id_is_over 1")
            #等待触发被触发,可以使用任何可等待的对象
            await self._tris["stop"].triggered()
            #command的返回值
            return self._items
    
        def id_here(self, name, line, wildcards):
            #没有在CMD开始就使能整组触发器,防止因为网络卡顿的原因造成误触发
            self._tris["id_item"].enabled = True
        def id_item(self, name, line, wildcards):
            data = list(wildcards)
            data[0] = data[0].strip()
            data[1] = data[1].split(", ")
    
            if not data[0] == self.session.vars.Status["name"]:
                #避免捕获自己的信息,Status为自定义字典
                self._items.append(data)
        def __unload__(self):
            self.session.delObjects(self._tris)
            super().__unload__()
        def reset(self):
            super().reset()
            self.session.enableGroup("cmd.id", False, False, [Trigger])
    
        def start(self, name, line, wildcards):
            self.session.enableGroup("cmd.id", True, False, [Trigger])
    
        def stop(self, name=None, line=None, wildcards=None):
            #cmd流程结束,关闭触发组
            self.session.enableGroup("cmd.id", False, False, [Trigger])
    

    command还可以返回值,所以可以把一个大任务分解成若干具有返回值的command,根据返回值判断下一步操作
  • N

    GPT-5.2连肝7天,300万行代码造出Chrome级浏览器 - 今日头条https://m.toutiao.com/is/LsGLJLLSstg/?share_token=08390665-5724-4b5e-aa16-d60e786852e6


    结果很快就被打脸了 https://m.toutiao.com/article/7596878729889071651/?app=news_article&timestamp=1768895064&use_new_style=1&req_id=2026012015442459992E389CA4B86EA3F6&group_id=7596878729889071651&req_id_new=2026012015442459992E389CA4B86EA3F6&chn_id=-3&share_did=MS4wLjACAAAAlmN2N2xl45m9DDeD3nvO8q6O3z7rT3nl__fkiK7DyVN8qDpvraWOQtfNac-DtgDZ&share_uid=MS4wLjABAAAAnPLB9vmFy-HOkJvCwwnpOsLW9ionGSGMcG7SBIjSexDXabGKsm-Jq9qVVWGHoLz8
  • A

    a57ff56b-39ab-4459-aed0-0cf78d548c0b-image.png
    #help close 没有-f的说明


    0.22.3版已增加
  • N

    0.22.3post1

    • 问题修复: 修复了代码中使用#wa等异步功能被改失效的问题。

    0.22.3 (2026-01-18)

    • 问题修复: 删除了各代码文件中不需要的引用,经测试,Python 3.8 版可以正常运行。
    • 问题修复: 修复了getVariable方法中,如果有非字母字符时会导致获取变量值为None的情况。
    • 问题修复: 修复了#var对嵌套变量的支持中的BUG,原先如果使用数字作为dict的key时,会被识别为list然后返回None。
    • 功能优化: #mem diff现在是与首次启动时的内存进行对比,而不是与上一次执行时的内存进行对比。
    • 其他变更: #close的帮助中增加了对参数的描述,支持 -f 参数和 session_name 参数。之前只有改功能,帮助中未说明。
    • 其他变更: 修改了多处语法不规范、代码弃用替代的情况。

    0.22.3 (2026-01-18) Bug Fixes: Removed unnecessary imports from various code files. Verified to work normally with Python 3.8. Fixed an issue in the getVariable method where non-alphabetic characters would cause the variable value to return None. Fixed a bug in #var nested variable support. Previously, if a digit was used as a dictionary key, it would be incorrectly identified as a list and return None. Feature Improvements: Updated #mem diff to compare against the memory usage at initial startup, rather than against the previous execution. Other Changes: Updated the help documentation for #close to include a description of its parameters, specifically support for the -f and session_name arguments (previously supported but undocumented). Refactored multiple instances of non-standard syntax and replaced deprecated code. (Translation by Quark)
  • S

    e336d346-9eab-4364-9769-cd1423b0b78a-image.png 38571575-131f-4a56-8e5e-1c1df04b3ac5-image.png

    签到、师承字段没有。没匹配上,还是有字段限制 ?


    @newstart 在 cmdScore.py数据问题 中说: @shanghua 在 cmdScore.py数据问题 中说: @terry 在 cmdScore.py数据问题 中说: @shanghua 你不能插入代码块么?别总贴图 │上线:扬州客店 签到:暂无 │师承:宋远桥 @trigger(r'^.* │\s * 师承:(\S+)\s +│', group = "cmd.score") def masterinfo(self, name, line, wildcards): # self.profile["签到"] = wildcards[0].rstrip() self.profile["师承"] = wildcards[0].rstrip() 来来来,你要的代码 明显是正则不对,师承前面的\s和*之间不能有空格 这空格是粘贴的时候自己带上的,代码里没有
  • S

    d9500b76-82ba-465d-b1a5-76991198e0c0-image.png
    75e9d52d-b8d1-4e0a-a15f-93dbba0cf38e-image.png
    直接从群里下载的,代码没动过。


    @terry 在 cmdScore.py加载报错 中说: @shanghua 你的IDE对于不能识别的关键字不会提示么? 用的pycharm,只要不是语法错误,它都不提示
  • T

    我写了一个skills命令,意图查看自身或者师父的技能。
    现在是第一步,先实现自身的技能查询,并保存到变量中。

    你目前所掌握的技能:(十四项)
    
    ┏━  普通知识  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃  读书识字 (literate)                      - 学贯古今    192/ 22225   ┃
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
    ┏━  基本技能  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃  基本弓箭 (archery)                       - 初窥堂奥    171/ 2729    ┃
    ┃  基本轻功 (dodge)                         - 凌空渡虚    502/ 49830   ┃
    ┃  内功心法 (force)                         - 深不可测    503/ 239011  ┃
    ┃  拆招卸力之法 (parry)                     - 一代宗师    502/ 41364   ┃
    ┃  法术 (spells)                            - 变换莫测    503/ 8800    ┃
    ┃  基本剑术 (sword)                         - 一代宗师    502/ 8384    ┃
    ┃  扑击格斗之技 (unarmed)                   - 一代宗师    502/ 4228    ┃
    ┠─  特殊技能  ────────────────────────────┨
    ┃□百花掌 (baihua-zhang)                    - 一代宗师    502/ 32618   ┃
    ┃□枯骨刀 (kugu-blade)                      - 一代宗师    502/ 21322   ┃
    ┃□冷月凝香舞 (moondance)                   - 一代宗师    502/ 43960   ┃
    ┃□圆月心法 (moonforce)                     - 一代宗师    503/ 7155    ┃
    ┃□月宫仙法 (moonshentong)                  - 一代宗师    502/ 351011  ┃
    ┃□风回雪舞剑法 (snowsword)                 - 一代宗师    502/ 29453   ┃
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
    

    这是输入skills命令后的显示结果,我想通过'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛'来触发命令结束,但这个在整个技能中出现了不止一次,所以我想结合技能的数量判断是否已经结束,即技能的获取数量和掌握技能的总数(十四项),可以判断技能查询结束了,如何把这个条件也加到异步判断中呢?
    下面是我暂时写的代码:

    from pymud import Command, Trigger, IConfig, DotDict,trigger,async_exception
    import traceback
    import re, cn2an
    
    class CmdSkills(Command, IConfig):
        _help = """
        通过命令行查看技能的命令:
            正常指令      含义
            skills:         查看角色所有技能
            skills xxx:    查看npc'xxx'的所有技能
        """
        def __init__(self, session, *args, **kwargs):
            pattern = r"^(?:skills|sk)\s*(.*)$"
            
            kwargs.setdefault("id", "cmd_skills")
            super().__init__(session, patterns = pattern, *args, **kwargs)
            self.session.setVariable('skills',[])    
            self.category = ''
            self.skill_count = 0
            self.skill_order = 0
        def __unload__(self):
            super().__unload__()
    
        @trigger(id = "cmd.skiills.start", patterns = r"^你目前所掌握的技能:((.*?)项)", group = "cmd.skills",enabled = False)
        def start(self, name, line, wildcards):    
            self.session.info('Start to parse skill on')
            self.skill_count = cn2an.cn2an(wildcards[0],'normal')
            self.session.enableGroup(group = "cmd.skills", enabled = True, subgroup = True)  
        
        @trigger(id = "cmd.skills.end", patterns = r'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛', group = "cmd.skills",enabled = False)
        def end(self, name, line, wildcards):    
            self.session.info(f'End to parse skills')
            self.session.enableGroup(group = "cmd.skills", enabled = False, subgroup = True)  
            
        
        @trigger(id = "cmd.skills.item", patterns = r'^\s*┃\s*([□ ]?)\s*([^()]+)\s*\(([^)]+)\)\s*-\s*([^ ]+)\s+(\d+)/\s*(\d+)\s*┃\s*$', group = "cmd.skills",enabled = False)
        def item(self, name, line, wildcards):    
            skill = {}
            skill['category'] = self.category
            skill['enabled'] = '□' in wildcards[0].strip()
            skill['cn_name'] = wildcards[1].strip()
            skill['en_name'] = wildcards[2].strip()
            skill['title'] = wildcards[3].strip()
            skill['level'] = int(wildcards[4].strip())
            skill['experience'] = int(wildcards[5].strip())
            self.session.getVariable('skills').append(skill)
            self.skill_order += 1
        
        @trigger(id = "cmd.skills.category", patterns = r'^[┏┠][━─]\s{2}([\u4e00-\u9fa5]+)\s{2}[━─]+.*[┓┨]\s*$', group = "cmd.skills",enabled = False)
        def item_end(self, name, line, wildcards):
            self.category = wildcards[0].strip()    
            self.session.info(f'Skill category: {self.category}')
    
        async def execute(self, cmd = "skills", *args, **kwargs):        
            try:
                self.reset()
                self.session.tris["cmd.skiills.start"].enabled = True 
                await self.session.waitfor(cmd, self.session.tris["cmd.skills.end"].triggered())
                self.session.enableGroup(group = "cmd.skills", enabled = False, subgroup = True)  
                return self.SUCCESS
            except Exception as e:
                self.error(f"异步执行中遇到异常, {e}, 类型为 {type(e)}")
                self.error(f"异常追踪为: {traceback.format_exc()}")
    

    谢谢各位大佬。 我在skill item的触发中计数,当计数和总技能数相等的时候开启end触发,算是绕过去了。 from pymud import Command, Trigger, IConfig, DotDict,trigger,async_exception import traceback import re, cn2an class CmdSkills(Command, IConfig): _help = """ 通过命令行查看技能的命令: 正常指令 含义 skills: 查看角色所有技能 skills xxx: 查看npc'xxx'的所有技能 """ def __init__(self, session, *args, **kwargs): pattern = r"^(?:skills|sk)\s*(.*)$" kwargs.setdefault("id", "cmd_skills") super().__init__(session, patterns = pattern, *args, **kwargs) self.session.setVariable('skills',[]) self.category = '' self.skill_count = 0 def __unload__(self): super().__unload__() @trigger(id = "cmd.skills.start", patterns = r"^你目前所掌握的技能:((.*?)项)", group = "cmd.skills",enabled = False) def start(self, name, line, wildcards): self.skills = [] self.skill_order = 0 self.session.info('Start to parse skill on') self.skill_count = cn2an.cn2an(wildcards[0],'normal') self.session.enableGroup(group = "cmd.skills", enabled = True, subgroup = True) @trigger(id = "cmd.skills.end", patterns = r'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛', group = "cmd.skills",enabled = False) def end(self, name, line, wildcards): self.session.info(f'End to parse skills') self.session.enableGroup(group = "cmd.skills", enabled = False, subgroup = True) @trigger(id = "cmd.skills.item", patterns = r'^\s*┃\s*([□ ]?)\s*([^()]+)\s*\(([^)]+)\)\s*-\s*([^ ]+)\s+(\d+)/\s*(\d+)\s*┃\s*$', group = "cmd.skills",enabled = False) def item(self, name, line, wildcards): skill = {} skill['category'] = self.category skill['enabled'] = '□' in wildcards[0].strip() skill['cn_name'] = wildcards[1].strip() skill['en_name'] = wildcards[2].strip() skill['title'] = wildcards[3].strip() skill['level'] = int(wildcards[4].strip()) skill['experience'] = int(wildcards[5].strip()) self.skills.append(skill) self.skill_order += 1 if self.skill_order == self.skill_count: self.session.tris["cmd.skills.end"].enabled = True @trigger(id = "cmd.skills.category", patterns = r'^[┏┠][━─]\s{2}([\u4e00-\u9fa5]+)\s{2}[━─]+.*[┓┨]\s*$', group = "cmd.skills",enabled = False) def category(self, name, line, wildcards): self.category = wildcards[0].strip() self.session.info(f'Skill category: {self.category}') async def execute(self, cmd = "skills", *args, **kwargs): try: self.reset() self.session.tris["cmd.skills.start"].enabled = True await self.session.waitfor(cmd, self.session.tris["cmd.skills.end"].triggered()) self.session.enableGroup(group = "cmd.skills", enabled = False, subgroup = True) self.session.setVariable('skills',self.skills) return self.SUCCESS except Exception as e: self.error(f"异步执行中遇到异常, {e}, 类型为 {type(e)}") self.error(f"异常追踪为: {traceback.format_exc()}")
  • T

    默认的分页符位置太偏上了,如何修改呢?


    @newstart Nice. 在pymud.cfg中设置成0.85了。