跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 世界
  • 用户
  • 群组
皮肤
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Cerulean)
  • 不使用皮肤
折叠
品牌标识

PyMUD官方论坛

Global Moderators

Forum wide moderators

私有

帖子


  • 如何加载不同模块(.py)?
    N newstart

    @shanghua 在 如何加载不同模块(.py)? 中说:

    https://www.pkuxkx.net/forum/thread-50002-1-1.html

    跟这帖子不一样吗?

    一样的,就是这个🤣

    PyMUD讨论区

  • 如何加载不同模块(.py)?
    N newstart

    很好,就是需要有探索精神😂🤣

    PyMUD讨论区

  • 如何加载不同模块(.py)?
    N newstart

    你可以试试看,我不太确定行不行,main.py不知道放什么的话,不用也没关系

    PyMUD讨论区

  • 如何加载不同模块(.py)?
    N newstart

    步骤一:先把目录结构改成这样的

    > 
    > |-----mud_main.py              # 主入口
    > |-----pymud.cfg                # 配置文件,设置default_script": [" mud_main"]
    > |-----xkx/                     # 此处增加一个目录,作为package管理所有的下级模块
    >       |----- __init__.py       # 此处增加一个空文件,文件名必须为 __init__.py 用来指示 xkx 这个目录是一个 package。下级每一个子目录都要增加一个 __init__.py 的空文件
    >       |----- main.py           # 建议增加一个包内的最终管理文件,通用的配置都放在这里,mud_main.py仅保留入口检查功能
    >       |----- triggers/
    >             |----- __init__.py                   # 空文件,指示为package
    >             |----- common_triggers.py            # 通用trigger
    >       |----- commands/
    >             |----- __init__.py                   # 空文件,指示为package
    >             |----- fight.py                      # fight 模块
    
    

    步骤二: mud_main.py 的内容写成这样的

    import os
    from pymud import IConfig, Session
    
    class EntryConfig(IConfig):
        def __init__(self, session: Session, *args, **kwargs):
            reload = kwargs.get("reload", False)    # 处理参数里的 reload, 用于支持 #reload mud_main 就可以重新加载所有脚本
            self.session = session
            
            # 脚本加载顺序
            mods = list()
            current_dir = os.path.dirname(__file__)        # 获取当前文件所在的目录
            root_dir = os.path.join(current_dir, "xkx")    # 当前目录下的xkx目录
    
            dir = os.path.join(root_dir, "triggers")           # 处理triggers子目录下的所有文件
            if os.path.exits(dir):
                for file in os.listdir(dir):
                    if file.endswith(".py") and (not file.startswith("__")):     #获取目录下的所有.py文件,并排除 __init__.py
                        mods.append(f"xkx.triggers.{file[:-3]}")
    
            dir = os.path.join(root_dir, "commands")     # 处理 commands目录下的所有文件,原理同上
            if os.path.exists(dir):
                for file in os.listdir(dir):
                    if file.endswith(".py") and (not file.startswith("__")):     #获取目录下的所有.py文件,并排除 __init__.py
                        mods.append(f"xkx.commands.{file[:-3]}")
    
            mods.append("xkx.main")                           # 通用的main文件可能会调用其他模块内容,放在最后
    
            session.load_module(mods)
    
            if reload:                     # 处理 reload
                session.reload_module(mods)
    
            self.mods = mods     # 保存mods供unload使用
    
        def __unload__(self):
            # 卸载时按照加载的反向顺序逐个卸载
            for mod in reversed(self.mods):
                self.session.unload_module(mod)
    
    

    后续要往子目录里增加文件,直接加 xxx.py 就可以了,在子目录下的文件会被自动获取并加载。

    PyMUD讨论区

  • 新版功能测试中
    N newstart
    • 可以进行内存占用分析了(不过分析自身很占资源)
      内存占用分析.png

    • #var命令可以处理嵌套命令了!
      #var获取嵌套变量对象.png

    本版本还在测试中,尽请期待 🙂

    PyMUD讨论区

  • 关于多行Trigger的讨论
    N newstart

    很多时候都是这么实现的,比如抓房间描述不确定多少行时,用房间名做首行触发,用出口描述做结束触发,中间再判断是什么。

    PyMUD讨论区

  • 关于多行Trigger的讨论
    N newstart

    或者可以自己定义多个触发器来配合实现总行数不确定的情况,比如第一个触发器tri1仅触发首行,第二个tri2仅触发尾行,第三个触发器tri3用 .* 作为全部匹配。当第一个触发器触发时,打开第三个触发器,然后对每一个进行判断;当第二个触发器触发时,关闭第三个触发器,这样就能全部手动处理了。

    PyMUD讨论区

  • 关于多行Trigger的讨论
    N newstart

    PyMUD的多行触发是以开头第一行作为标志的,所以patterns的第一行必须要是一个有明显特征的行。只要首行不会匹配到其他内容,那么后续N行的出发匹配都OK。

    PyMUD讨论区

  • RFC #854 TELNET 协议规范
    N newstart

    TELNET RFC文档概述

    RFC #854 TELNET 协议规范

    0. 基本信息

    WEB页面:https://www.rfc-editor.org/rfc/rfc854.html
    发布日期:1983-05
    本RFC为ARPA互联网社区指定了一个标准。ARPA互联网上的主机预计将采用并实施本标准。
    

    1. 引言

    TELNET协议的目的是提供一种相当通用的、双向的、面向八位字节的通信设施。它的主要目标是允许一种将终端设备和面向终端的过程相互连接的标准方法。可以设想,该协议也可以用于终端通信(“链接”)和过程过程通信(分布式计算)。
    

    2. 一般考虑

    TELNET连接是一种传输控制协议(TCP)连接,用于传输带有穿插TELNET控制信息的数据。
    TELNET协议建立在三个主要思想之上:第一,“网络虚拟终端”(Network Virtual Terminal, NVT)的概念;第二,协商选择权原则;第三,终端和过程的对称视图。
    
    1. 当首次建立TELNET连接时,假设每一端都在“网络虚拟终端”(NVT)发起和终止。NVT是一种假想的设备,它提供规范终端的标准、网络范围的中间表示。这就不需要“服务器”和“用户”主机来保存有关彼此终端特性和终端处理约定的信息。所有主机,包括用户和服务器,都映射其本地设备特性和约定,以便看起来是在处理网络上的NVT,并且每个主机都可以由另一方进行类似的映射。NVT旨在在过度限制(没有为主机提供足够丰富的词汇表来映射到其本地字符集)和过度包容(惩罚使用普通终端的用户)之间取得平衡。
      注:“用户”主机是物理终端通常连接到的主机,“服务器”主机是通常提供某些服务的主机。作为另一种观点,即使在终端到终端或过程到过程通信中也适用,“用户”主机是发起通信的主机。
    2. 协商选项的原则考虑到这样一个事实,即许多主机将希望提供超过NVT内可用服务的额外服务,并且许多用户将拥有复杂的终端,并且希望拥有优雅的服务,而不是最低限度的服务。独立于TELNET协议,但在TELNET协议中结构化的是各种“选项”,这些选项将被批准,并可与“DO,DON’T,WILL,WON’T”结构(如下所述)一起使用,以允许用户和服务器同意为其TELNET连接使用一组更详细(或可能只是不同)的约定。这些选项可能包括更改字符集、回声模式等。
      设置选项使用的基本策略是让任何一方(或双方)发起请求,要求某些选项生效。然后,另一方可以接受或拒绝该请求。如果请求被接受,该选项将立即生效;如果被拒绝,则连接的相关方面保持为针对NVT所指定的。显然,一方可能总是拒绝启用某个选项的请求,并且决不能拒绝禁用某个选项,因为所有各方都必须准备好支持NVT。
      选项协商的语法已经设置好,如果双方同时请求一个选项,双方都会将对方的请求视为对自己的肯定确认。
    3. 协商语法的对称性可能会导致非终止确认循环——各方将传入的命令视为必须确认的新请求,而不是确认。为防止此类循环,以以下规则为准:
    • a. 缔约方只能要求更改选项状态;也就是说,一方不能仅仅为了宣布其处于何种模式而发出“请求”。
    • b. 如果一方收到似乎是进入其已经处于的某种模式的请求,则不应确认该请求。这种不回应对于防止谈判中无休止的循环至关重要。即使模式没有更改,也需要对更改模式的请求发送响应。
    • c. 当一方向第二方发送选项命令时,无论是作为请求还是确认,并且该选项的使用将对从第一方发送到第二方的数据的处理产生任何影响,则该命令必须在希望其生效的点插入数据流中。(需要注意的是,从发送请求到收到确认之间会经过一段时间,这可能是否定的。因此,主机可能希望在请求选项后缓冲数据,直到它知道请求是被接受还是被拒绝,以向用户隐藏“不确定期”。)
      当TELNET连接首次建立时,选项请求可能会来回奔波,因为各方都试图从另一方获得尽可能好的服务。然而,除此之外,还可以使用选项来动态修改连接的特性,以适应不断变化的本地条件。例如,正如稍后将要解释的那样,NVT使用的传输规程非常适合许多“一次一行”的应用程序,如BASIC,但不太适合许多“每次一个字符”的应用,如NLS。当“一次一个字符”规则适合本地进程并协商合适的选项时,服务器可能会选择投入该规则所需的额外处理器开销。然而,当不再需要详细控制时,它可以切换(即协商)回NVT,而不是永久地承受额外的处理开销。
      如果进程仅通过重新请求选项来响应拒绝,则进程发起的请求可能会激发非终止请求循环。为了防止这种循环的发生,被拒绝的请求不应该重复,直到发生变化。在操作上,这可能意味着进程正在运行不同的程序,或者用户已经给出了另一个命令,或者在给定进程和给定选项的上下文中有意义的任何东西。一个很好的经验法则是,重新请求只应作为来自连接另一端的后续信息的结果或当本地人工干预要求时发生。
      选项设计者不应感到受到可用于选项谈判的有限语法的约束。简单语法的目的是让选择变得容易——因为相应地,人们很容易声称对它们一无所知。如果某个特定选项需要比“DO,DON’T,WILL,WON’T”更丰富的谈判结构,那么正确的策略是使用“DO,DO’T,WILL,WON”来确定双方都理解该选项,一旦完成,就可以自由使用更奇特的语法。例如,一方可能会发送更改(建立)线路长度的请求。如果它被接受,那么可以使用不同的语法来实际协商线路长度——这样的“子协商”可能包括最小允许、最大允许和所需线路长度的字段。重要的概念是,在之前的一些(标准)谈判已经确定双方都能够解析扩展的语法之前,这种扩展的谈判永远不应该开始。
      总之,任何一方发送WILL XXX,以表明该方希望(要约)开始执行选项XXX,DO XXX和DOT XXX是其肯定和否定的确认;类似地,发送DO XXX以指示希望(请求)另一方(即DO的接收方)开始执行选项XXX,WILL XXX和WON’T XXX作为肯定和否定的确认。由于NVT是在没有启用选项的情况下剩下的,因此“DON'T”和“WON'T”响应保证使连接处于两端都可以处理的状态。因此,所有主机都可以在完全不知道不支持的选项的情况下实现其TELNET进程,只需对无法理解的任何选项请求返回拒绝(即拒绝)即可。
      TELNET协议已经尽可能地实现了服务器-用户对称,因此它可以轻松自然地涵盖用户-用户(链接)和服务器-服务器(协作进程)的情况。人们希望,但并非绝对需要,各种选择将进一步推动这一意图。无论如何,人们明确承认对称是一种操作原理,而不是一条铁律。
      应查阅配套文件“TELNET选项规范”,以获取有关建立新选项的程序的信息。

    3. 网络虚拟终端(Network Virtual Terminal, NVT)

    网络虚拟终端(NVT)是一种双向字符设备。NVT有一台打印机和一个键盘。打印机响应输入数据,键盘产生输出数据,通过TELNET连接发送,如果需要“回声”,也发送到NVT的打印机。“回声”将不会穿过网络(尽管存在启用“远程”回声操作模式的选项,但不需要主机来实现此选项)。代码集是八位字段中的七位USASCII,此处修改的除外。任何代码转换和时序考虑都是局部问题,不会影响NVT。
    

    3.1 传输数据

    尽管通过网络的TELNET连接本质上是全双工的,但NVT应被视为在线路缓冲模式下运行的半双工设备。也就是说,除非协商了相反的选项,否则以下默认条件适用于通过TELNET连接传输数据:
    
    1. 只要本地缓冲区空间的可用性允许,数据应该在生成数据的主机中累积,直到完整的数据线准备好传输,或者直到出现一些本地定义的要传输的显式信号。该信号可以由过程产生,也可以由人类用户产生。
      这条规则的动机是,对一些主机来说,处理网络输入中断的成本很高,再加上默认的NVT规范,即“回声”不会穿过网络。因此,在其源处缓冲一定数量的数据是合理的。许多系统在每条输入线的末端进行一些处理操作(即使是行式打印机或打卡器也经常以这种方式工作),因此传输应该在线的末端触发。另一方面,用户或过程有时可能会发现有必要或希望提供不终止于线路末端的数据;因此,提醒实施者提供本地发信号通知所有缓冲数据应立即传输的方法。

    2. 当进程已完成向NVT打印机发送数据,并且没有来自NVT键盘的排队输入以供进一步处理时(即,当TELNET连接一端的进程在没有另一端输入的情况下无法继续进行时),该进程必须发送TELNET Go Ahead(GA)命令。
      此规则并不要求从每行末尾的终端发送TELNET GA命令,因为服务器主机通常不需要特殊信号(除了行末尾或其他本地定义的字符)来开始处理。相反,TELNET GA旨在帮助用户的本地主机操作物理上的半双工终端,该终端具有“可锁定”键盘,如IBM 2741。对这种类型的终端的描述可能有助于解释GA命令的正确使用。
      终端计算机连接始终处于用户或计算机的控制之下。双方都不能单方面从对方手中夺取控制权;相反,控制端必须明确地重新隐藏其控制。在终端,硬件的构造是为了在每次“线路”终止时(即,当用户键入“新行”键时)放弃控制。当这种情况发生时,连接的(本地)计算机处理输入数据,决定是否应该生成输出,如果不应该,则将控制权返回给终端。如果应该生成输出,则计算机将保留控制权,直到所有输出都已传输。
      通过网络使用这种类型的终端的困难应该是显而易见的。“本地”计算机在看到线路末端信号后不再能够决定是否保留控制;这个决定只能由处理数据的“远程”计算机做出。因此,TELNET GA命令提供了一种机制,“远程”(服务器)计算机可以向“本地”(用户)计算机发出信号,表示是时候将控制权交给终端用户了。它应该在这些时间发送,并且只有在用户应该被赋予终端控制权时才发送。请注意,GA命令的过早传输可能会导致输出阻塞,因为用户可能会认为传输系统已经暂停,因此他将无法手动扭转线路。

      当然,上述内容不适用于用户到服务器的通信方向。在这个方向上,GA可以在任何时候发送,但不需要发送。此外,如果TELNET连接用于进程到进程的通信,则无需向任何方向发送GA。最后,对于终端到终端的通信,可能在任一方向、一个方向或两个方向上都不需要GA。如果主机计划支持终端到终端的通信,则建议主机向用户提供手动发信号通知通过TELNET连接发送GA的时间到了的方式;然而,这并不是TELNET流程实现者的要求。
      请注意,TELNET模型的对称性要求TELNET连接的每一端都有一个NVT,至少在概念上是这样。

    3.2 控制功能的标准表示

    如本文件导言所述,TELNET协议的主要目标是通过网络提供终端设备和面向终端的进程的标准接口。这种类型的互连的早期经验表明,某些功能是由大多数服务器实现的,但调用这些功能的方法差异很大。对于与多个服务器系统交互的人类用户来说,这些差异非常令人沮丧。因此,TELNET为其中五个函数定义了一个标准表示,如下所述。这些标准表示具有标准但非必需的含义(使用TELNET的其他协议可能需要中断处理(IP)功能除外);也就是说,不向本地用户提供功能的系统不需要向网络用户提供功能,并且可以将功能的标准表示视为“否”操作。另一方面,向本地用户提供功能的系统必须向发送该功能的标准表示的网络用户提供相同的功能。
    
    3.2.1 中断过程 Interrupt Process (IP)
    许多系统提供暂停、中断、中止或终止用户进程操作的功能。当用户认为自己的进程处于无休止的循环中,或者无意中激活了不需要的进程时,经常使用此功能。IP是调用此函数的标准表示形式。实施人员应注意,使用TELNET的其他协议可能需要IP,因此,如果要支持这些其他协议,则应实施IP。
    
    3.2.2 中止输出 Abort Output (AO)
    许多系统提供了一种功能,该功能允许正在生成输出的进程运行到完成(或达到与运行到完成时相同的停止点),但不将输出发送到用户的终端。此外,该功能通常清除已经产生但尚未实际打印(或显示)在用户终端上的任何输出。AO是调用此函数的标准表示。例如,一些子系统通常可以接受用户的命令,向用户的终端发送一个长文本字符串作为响应,最后通过向用户的端子发送一个“提示”字符(前面有<CR><LF>)来表示准备接受下一个命令。如果在传输文本字符串的过程中接收到AO,则合理的实现方式是抑制文本字符串的剩余部分,但传输提示字符和前面的<CR><LF>。(这可能与接收到IP时可能采取的操作不同;IP可能会导致文本字符串被抑制并退出子系统。)
    应该注意的是,通过提供该功能的服务器系统,可能存在系统外部的缓冲区(在网络和用户的本地主机中),这些缓冲区应该被清除;实现这一点的适当方法是向用户系统发送“Synch”信号(如下所述)。
    
    3.3.3 你在吗 Are You There (AYT)
    许多系统提供一种功能,该功能向用户提供一些可见(例如,可打印)的证据,表明系统仍在运行。当系统出乎意料地长时间“静默”时,用户可能会调用此函数,因为计算的长度出乎意料(用户),系统负载异常重等。AYT是调用此函数的标准表示。
    
    3.3.4 删除字符 Erase Character (EC)
    许多系统提供了一种功能,可以从用户提供的数据流中删除最后一个在前未删除的字符或“打印位置”*。此功能通常用于在出现键入错误时编辑键盘输入。EC是调用此函数的标准表示。
    注意:“打印位置”可能包含几个字符,这些字符是重击的结果,或是<char1>BS<char2>等序列的结果。。。
    
    3.3.5 删除行 Erase Line (EL)
    许多系统提供删除当前输入“行”中所有数据的功能。此功能通常用于编辑键盘输入。EL是调用此函数的标准表示。
    
    个人博客区

  • PyMUD运行的好伙伴 - uv包管理器
    N newstart

    因为PyMUD开发需要经常在多个Python版本下测试是否有效,以前使用传统的pyenv来创建虚拟环境解决问题,后来发现操作起来实在太过于繁琐,因此找到了一款新的基于命令行的包管理工具, uv,完整替代了我所有的需求,包括不同Python版本的管理、虚拟环境、依赖管理等等,而且 uv 是通过 rust 开发,支持并发操作,碰到新环境搭建需要 pip 拉取一堆依赖项时,速度极快,已经是我正常开发和运行过程中不可缺少的工具了,现在推荐给大家。

    相关链接
    • 代码 https://github.com/astral-sh/uv
    • 文档 https://docs.astral.sh/uv/
    官宣的我觉得很有用的特点
    • 🚀 用一个工具替代 pip,pip-tools,pipx,poetry,pyenv,twine,virtualenv 等等
    • ⚡️ 比标准pip快10~100倍。
    • 🐍 可用于安装和管理 Python 版本。
    • 🛠️ 管理pypi发布的 Python 包。
    • ⏬ 可以通过curl或者pip安装,而无需安装 Rust 或 Python。
    • 🖥️ 跨平台,支持 macOS、Linux 和 Windows。

    详细信息可参见官方文档 😊

    个人博客区

成员列表

N newstart
  • 登录

  • 没有帐号? 注册

  • 登录或注册以进行搜索。
Powered by NodeBB Contributors
  • 第一个帖子
    最后一个帖子
0
  • 版块
  • 最新
  • 标签
  • 热门
  • 世界
  • 用户
  • 群组