会话


Evennia的一个会话代表玩家与服务器建立的一个连接。它可以让一个人连接多次,比如他在多个窗口中使用不同的客户端连接。每一个这样的连接通过一个会话对象来表示。

会话对象拥有自己的命令集,通常是“未连接状态”的命令集。它们用来显示登录界面并处理新建帐号的命令,或让虚空中的玩家读取初始的帮助以及使用现有帐户登录到游戏。

会话对象可以处于也可以不处于“已登录状态”。已登陆表示该用户已通过了验证,处于这种状态时,会话会和一个玩家对象关联(玩家对象负责和账户中心相关的东西)。之后,玩家可以操纵任意数量的物体或角色。玩家可以同时连接的会话数量及工作方式由 MULTISESSION_MODE 设定:
  • MULTISESSION_MODE=0:每个玩家一个会话。当新会话接入,旧的会话会断开。这是默认模式,模仿了许多经典MUD代码的处理方式。
  • MULTISESSION_MODE=1:每个玩家可以有多个会话,对每个会话输入都一样对待。这就是说,你可以使用任意数量的不同客户端输入,但所有客户端都会看到相同的返回结果。
  • MULTISESSION_MODE=2:每个玩家可以有多个会话,每个都是独立的输入。这是完全的多玩家模式,通过同一个玩家帐号,每个会话都可以单独操纵自己的物体或角色而不会影响其他会话。


返回数据到会话

当你想使用 msg() 将数据返回给用户,要注意在什么对象上调用 msg() 。同时也要注意 MULTISESSION_MODE 的值,特别是 MULTISESSION_MODE=2 。

举个例子,如果你用 Player.msg("你好") ,Evennia无法知道该向哪个会话发送这句问候,因此会向所有会话发送。如果你想向一个特定的会话发送,你需要向 msg 提供会话的id(sessid)。

另一方面,如果你在被操纵的对象上调用 msg() 消息,比如 Character.msg("你好") ,Character已经知道了操纵它的会话的sessid —— 它会很聪明地为你自动加上(如果你想专门发送数据到另一个会话,你可以指定不同的sessid)。

最后,在所有 Command 类中都封装了 msg() :Command.msg()。它会自动检测触发该命令的会话(如果有的话),并重定向到该会话(这通常是你想要的)。如果你在重定向到某个会话时遇到了麻烦,Command.msg() 通常是最安全选择。

你可以用多种方式得到的sessid。
  • 会话将 sessid 保存在属性 sessid 中。
  • 玩家的 sessions 属性中保存了连接到这个玩家的所有会话。
  • 被操纵物体(通常是角色)保存了当前操纵它的会话的 sessid 属性。
  • 命令会保存触发它们的会话的 sessid (如果没有涉及会话,该值则为 None ,比如小怪或脚本触发了命令)。


自定义会话对象

什么时候会想要自定义会话对象呢?考虑下面的例子:一个角色创建系统。你可能会想让它一直处于没有角色的状态,在选择了一系列菜单后才最后创建出角色,之后再将实际角色的命令集交给用户。如果你没有设置 MULTISESSION_MODE=2 ,这会工作得很好。如果设置了,切换到用户命令集的操作会影响到你连接的所有会话。在这种情况下,你需要在会话级别上设置角色创建命令集 —— 尽管你在某个会话上创建了新的角色,其它会话仍然继续正常工作。

默认情况下,当用户初次建立连接时,会话对象会按照 settings.CMDSET_UNLOGGEDIN 的定义获取命令集。而在会话通过验证后,它就没有默认设置了。想要给会话添加“已登录状态”的命令集,需要在 settings.CMDSET_SESSION 中设置命令集的路径。玩家一登录,这项设置就会生效。

如果想要进一步定制,你可以用自己的子类完全覆盖会话。这些对象不是普通的类型类实体,通常你不需要这么做。如果你确定要这么做,你需要更改 settings.SERVER_SESSION_CLASS 指向你的自定义会话。如果你要重载会话,一定要留意原来的代码,小心谨慎地作修改。


服务器和接入程序的会话

通常我们处理的“会话”都是服务器级别的会话。在代码中,它们都是 ServerSession 类的。所有 ServerSession 的实例都自带有 PortalSession 。ServerSession处理游戏状态,PortalSession处理的连接协议本身的细节。这两者也可用作备份关键数据,比如在服务器重新启动时。参见接入程序和服务器获得更多信息。


(原文:https://github.com/Evennia/evennia/wiki/Sessions    翻译:卢铱俊)