当出口不存在时返回自定义错误信息¶
在 MUD 游戏中,Evennia 允许出口拥有任何名称。命令 “kitchen” 是一个有效的出口名称,“jump out the window” 或 “north” 也是如此。出口实际上由两个部分组成:一个 Exit Object 和存储在该出口对象上的一个 Exit Command。命令与出口对象具有相同的键和别名,这就是为什么你可以在房间中看到出口并只需输入其名称即可穿越。
因此,如果你尝试输入一个不存在的出口名称,Evennia 会将其视为尝试使用不存在的命令:
> jump out the window
Command 'jump out the window' is not available. Type "help" for help.
许多游戏不需要这种自由度。它们仅将基本方向定义为有效的出口名称(Evennia 的 tunnel
命令也提供此功能)。在这种情况下,错误消息开始显得不太合理:
> west
Command 'west' is not available. Maybe you meant "set" or "reset"?
由于我们在特定游戏中知道西是一个出口方向,因此如果错误消息直接告诉我们无法向西移动会更好。
> west
You cannot move west.
实现这一点的方法是为 Evennia 提供一个 替代 命令,当在房间中找不到出口命令时使用。有关向 Evennia 添加新命令的过程的更多信息,请参见 Adding Commands。
在这个例子中,我们只会回显一条错误消息,但你可以做任何事情(比如如果撞到墙会失去生命值)。
# 例如在文件 mygame/commands/movecommands.py 中
from evennia import default_cmds, CmdSet
class CmdExitError(default_cmds.MuxCommand):
"""所有出口错误的父类。"""
locks = "cmd:all()"
arg_regex = r"\s|$"
auto_help = False
def func(self):
"""根据键返回错误"""
self.caller.msg(f"You cannot move {self.key}.")
class CmdExitErrorNorth(CmdExitError):
key = "north"
aliases = ["n"]
class CmdExitErrorEast(CmdExitError):
key = "east"
aliases = ["e"]
class CmdExitErrorSouth(CmdExitError):
key = "south"
aliases = ["s"]
class CmdExitErrorWest(CmdExitError):
key = "west"
aliases = ["w"]
# 你可以将每个命令单独添加到默认命令集中,
# 但在此处将它们全部放入一个命令集允许你
# 仅添加此命令集,并使将来扩展更多出口错误更容易。
class MovementFailCmdSet(CmdSet):
def at_cmdset_creation(self):
self.add(CmdExitErrorNorth())
self.add(CmdExitErrorEast())
self.add(CmdExitErrorWest())
self.add(CmdExitErrorSouth())
我们将命令打包到一个新的小命令集中;如果我们将其添加到 CharacterCmdSet
,以后可以轻松地向 MovementFailCmdSet
添加更多错误,而无需在两个地方更改代码。
# 在 mygame/commands/default_cmdsets.py 中
from commands import movecommands
# [...]
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# [...]
def at_cmdset_creation(self):
# [...]
# 这会一次性添加所有命令
self.add(movecommands.MovementFailCmdSet)
reload
服务器。此后发生的情况是,如果你在一个有出口对象的房间中(假设是 “north”),适当的出口命令将 覆盖 你的错误命令(也命名为 “north”)。但是如果你输入一个没有匹配出口的方向,你将回退到默认的错误命令:
> east
You cannot move east.
通过修改 Exit typeclass,可以进一步扩展出口系统(包括操作出口命令本身的创建方式)。
为什么不使用单个命令?¶
那么,为什么我们不创建一个单一的错误命令呢?比如这样:
class CmdExitError(default_cmds.MuxCommand):
"处理所有出口错误。"
key = "error_cmd"
aliases = ["north", "n",
"east", "e",
"south", "s",
"west", "w"]
#[...]
这将不会按我们想要的方式工作。理解原因很重要。
Evennia 的 命令系统通过键和/或别名比较命令。如果 任何 键或别名匹配,这两个命令被视为 相同。当命令集合并时,优先级将决定这些“相同”命令中的哪个替换哪个。
因此,上面的例子在房间中 完全没有出口 的情况下工作得很好。但是当我们进入一个有出口 “north” 的房间时,其出口命令(具有更高优先级)将覆盖具有别名 “north” 的单个 CmdExitError
。因此 CmdExitError
将消失,而 “north” 将正常工作,但对于其他方向,我们将再次收到正常的“命令未识别”错误。