编码工具

Evennia 提供了许多实用工具来帮助完成常见的编码任务。大多数工具可以直接从扁平 API 访问,其他工具可以在 evennia/utils/ 文件夹中找到。

这里只是 evennia/utils 中工具的小部分选择。浏览 该目录 尤其是 evennia/utils/utils.py 的内容,以发现更多有用的工具,值得一看。

搜索

常见的操作是搜索对象。最简单的方法是使用定义在所有对象上的 search 方法。该方法会在相同位置和自己对象中搜索对象:

     obj = self.search(objname)

通常需要这样做的时间是在命令体内。obj = self.caller.search(objname) 将在调用者(通常是输入命令的角色)的 .contents(他们的“背包”)和 .location(他们的“房间”)中进行搜索。

给出关键字 global_search=True 以扩展搜索至整个数据库。别名也将通过此搜索匹配。您可以在默认命令集中找到多个此功能的示例。

如果您需要在代码模块中搜索对象,可以使用 evennia.utils.search 中的函数。您可以像短路一样访问这些函数 evennia.search_*

     from evennia import search_object
     obj = search_object(objname)

请注意,这些方法将始终返回一个结果的 list,即使该列表只有一个或零个条目。

创建

除了游戏内的构建命令(如 @create 等),您还可以直接在代码中构建所有 Evennia 的游戏实体(例如在定义新创建命令时)。

   import evennia

   myobj = evennia.create_objects("game.gamesrc.objects.myobj.MyObj", key="MyObj")

这些创建函数都具有大量参数,以进一步自定义创建的实体。有关更多信息,请参见 evennia/utils/create.py

日志记录

通常,您可以使用 Python 的 print 语句查看终端/日志中的输出。print 语句应仅用于调试。对于生产输出,请使用 logger,它将创建适当的日志记录到终端或文件。

     from evennia import logger
     #
     logger.log_err("这是一个错误!")
     logger.log_warn("这是一个警告!")
     logger.log_info("这是正常信息")
     logger.log_dep("此功能已弃用")

有一种特殊的日志消息类型 log_trace(),旨在从回溯内部调用 - 这对于将回溯消息传递回日志而不使服务器崩溃非常有用。

     try:
       # [可能失败的代码...]
     except Exception:
       logger.log_trace("这段文字将显示在回溯本身之下。")

最后,log_file logger 是一个非常有用的 logger 用于输出任意日志消息。这是一个经过优化的异步日志机制,使用 线程 来避免开销。您应该可以使用它进行非常重的自定义日志记录,而不必担心磁盘写入延迟。

 logger.log_file(message, filename="mylog.log")

如果没有给出绝对路径,则日志文件将出现在 mygame/server/logs/ 目录中。如果文件已经存在,则将其附加到该文件中。与普通 Evennia 日志相同格式的时间戳将自动添加到每个条目中。如果没有指定文件名,则输出将写入文件 game/logs/game.log

有关查找难以捉摸的错误的帮助,请参见 调试 文档。

时间工具

游戏时间

Evennia 跟踪当前服务器时间。您可以通过 evennia.gametime 快捷方式访问此时间:

from evennia import gametime

# 以下所有函数均以秒为单位返回时间。

# 服务器的总运行时间
runtime = gametime.runtime()
# 自上次硬重启以来的时间(不包括重载)
uptime = gametime.uptime()
# 服务器纪元(开始时间)
server_epoch = gametime.server_epoch()

# 进行中的纪元(可由 `settings.TIME_GAME_EPOCH` 设置)。
# 如果没有设置,则使用服务器纪元。
game_epoch = gametime.game_epoch()
# 自时间开始运行以来的游戏内时间
gametime = gametime.gametime()
# 当前游戏内时间戳(即当前游戏时间),加上游戏纪元
gametime = gametime.gametime(absolute=True)
# 重置游戏时间(回到游戏纪元)
gametime.reset_gametime()

设置 TIME_FACTOR 确定游戏内时间相对于现实世界的快慢。设置 TIME_GAME_EPOCH 设置开始的游戏纪元(以秒为单位)。来自 gametime 模块的函数都以秒为单位返回它们的时间。您可以将其转换为您希望在游戏中使用的任何时间单位。您可以使用 @time 命令查看服务器时间信息。

您还可以使用 gametime.schedule 函数安排在特定游戏内时间发生的事件:

import evennia

def church_clock():
    limbo = evennia.search_object(key="Limbo")
    limbo.msg_contents("教堂的钟声敲响了两点。")

gametime.schedule(church_clock, hour=2)

utils.time_format()

此函数以秒为输入(例如来自上面的 gametime 模块),并将其转换为一个美观的文本输出,显示天数、小时等。这在您想要显示某个事物的年龄时非常有用。使用 style 关键字可以转换为四种不同样式的输出:

  • style 0 - 5d:45m:12s(标准冒号输出)

  • style 1 - 5d(仅显示最长时间单位)

  • style 2 - 5 days, 45 minutes(完整格式,忽略秒)

  • style 3 - 5 days, 45 minutes, 12 seconds(完整格式,包含秒)

utils.delay()

该函数允许进行延迟调用。

from evennia import utils

def _callback(obj, text):
    obj.msg(text)

# 等待 10 秒后向 obj(假定已定义)发送“Echo!”
utils.delay(10, _callback, obj, "Echo!", persistent=False)

# 这里的代码将立即运行,而不会等待延迟触发!

有关更多信息,请参见 异步过程

查找类

utils.inherits_from()

这个有用的函数接受两个参数 - 一个要检查的对象和一个父类。如果对象在任何距离上都继承自父类,则返回 True(与 Python 内置的 isinstance() 仅捕获直接依赖的功能相对)。该函数还接受任何组合的类、实例或指向类的 Python 路径作为输入。

请注意,Python 代码通常应该使用 鸭子类型。但在 Evennia 的情况下,有时检查对象是否继承自给定 Typeclass 作为识别方式是有用的。例如,假设我们有一个类型类 Animal。这个类有一个子类 Felines,而 Felines 又有一个子类 HouseCat。也许还有其他一些动物类型,比如马和狗。使用 inherits_from,您可以一次检查所有动物:

     from evennia import utils
     if utils.inherits_from(obj, "typeclasses.objects.animals.Animal"):
        obj.msg("保安拦住你说:‘不允许会说话的动物。’")

文本工具

在文本游戏中,自然会进行大量的文本来回操作。这里是 evennia/utils/utils.py 中的一个 非完整 选择的文本工具(快捷方式为 evennia.utils)。如果没有其他选择,在开始开发自己的解决方案之前查看这里也是不错的主意。

utils.fill()

此函数将文本填充到给定宽度(调整单词以使每一行均匀宽)。它还会根据需要缩进。

     outtxt = fill(intxt, width=78, indent=4)

utils.crop()

此函数将剪裁一行非常长的文本,添加后缀以显示该行实际上是继续的。这在显示多个行可能搞乱的情况下特别有用。

     intxt = "这是一个我们想要剪裁的长文本。"
     outtxt = crop(intxt, width=19, suffix="[...]")
     # outtxt 现在是 "这是一个我们想要剪裁的长文本[...]"

utils.dedent()

此函数解决了在文本中看似微不足道的问题 - 删除缩进。它用于将整个段落向左移动,而不会干扰任何进一步的格式。一个常见的例子是使用 Python 三重引号字符串时 - 它们将在代码中保留任何缩进,并且为了使源代码易于阅读,通常不希望将字符串移至左边缘。

    #python 代码在给定缩进时输入
          intxt = """
          这是一个示例文本,将以大量的空白结束
          在左侧。
                    它也有自己的缩进。"""
          outtxt = dedent(intxt)
          # outtxt 现在将保留所有内部缩进
          # 但被移到最左边。

通常,您在显示代码中进行缩进(例如帮助系统如何标准化帮助条目)。

to_str() 和 to_bytes()

Evennia 提供了两个实用函数,用于将文本转换为正确的编码。to_str()to_bytes()。除非您正在添加自定义协议并需要将字节数据发送到网络,否则 to_str 是您唯一需要的。

Evennia 的这些函数与 Python 内置的 str()bytes() 运算符的不同之处在于,Evennia 的函数利用了 ENCODINGS 设置,并将非常努力地避免引发回溯,而是通过日志记录回显错误。有关更多信息,请参见 这里