物体


Evennia游戏中的所有物体,无论是角色、椅子、怪物、房间或手榴弹都是Evennia物体。物体构成了Evennia的核心,你的大部分工作都会花在它身上。物体是类型类的实例。


如何创建自己的物体类型

根据定义,Evennia中的物体是一个Python类,其父类中包括了 src.objects.objects.Object (如果你了解类型类工作的工作方式,就会知道这是与 ObjectDB 数据库模型相连的类型类)。在你的代码中,可以用 ev.Object 简单代替它。

以下是如何用代码定义一个新的物体类型类:
    from ev import Object

    class Rose(Object):
        """
        创建一个简单的玫瑰花物体        
        """    
        def at_object_creation(self):
            "这只会在物体初次创建时被调用"
            # 给这个物体添加持久属性”desc“
            # (这是个很简单的例子)。
            self.db.desc = "这是一朵带刺的漂亮玫瑰。"  
将你的类保存在 game/gamesrc/objects 下的模块中,比如 flowers.py。现在,你只要用 @create 命令指向 Rose 类就可以创建一朵新的玫瑰了:
 @create/drop MyRose:flowers.Rose
@create 命令实际所做的事就是调用 ev.create_object(src.utils.create.create_object() 的快捷方式)。你可以在你自己的代码中做同样的事:
    from ev import create_object
    new_rose = create_object("game.gamesrc.objects.flowers.Rose", key="MyRose")
(@create命令会自动添加指向类型类的最可能的路径,如果你手动调用命令就必须给出类的完整路径。create.create_object 功能强大,在用代码创建物体时都应该用它(所以在定义你自己的建造命令时也应该用它)。查阅 ev.create_* 函数,看看如何创建其它实例,如脚本)。

这个 Rose 类实际并没有做什么事,它只是确保预先设置了 desc 属性(这是 look 命令所需要的属性),这其实没多大意义,因为通常你会在建造的时候修改这个属性(使用 @desc 命令或使用 Spawner)。物体的类型类还提供了更加丰富的钩子函数,请参阅下一节内容。

如果你定义了新的物体类(从基类继承的),而且希望默认创建命令(@Create)能够默认创建它,可以设置 settings.py 中的 BASE_OBJECT_TYPECLASS 指向你的新类。


物体的属性和函数

除了所有类型类对象都具备的属性(请参阅类型类的文档),物体还具有以下的自定义属性:
  • aliases —— 添加或删除别名的处理程序。用 aliases.add() 添加别名,用 aliases.remove() 删除别名。
  • location —— 指向当前包含该物体的物体。
  • home —— 这是后备地点,主要是为了在物体所在地点被销毁时,让物体有一个安全地点可去。出于安全考虑,通常所有物体都应该有一个后备地点。
  • destination —— 指向该物体以某种方式连接的另一个物体。它主要用于出口,其它物体基本不用。
  • nicks —— 与别名不同,这里的昵称能替代真实名字、单词或序列,而且只适用于该对象。它主要对游戏角色起作用,它可以保存缩写,比如游戏命令的缩写或其它角色名字。用 nicks.add(别名, 真实名) 来添加。
  • player —— 它指向控制该物体的相关玩家(如果有的话)。请注意,即使控制它的玩家当前不在线这个属性也会被设置,如果要检测玩家是否在线,请使用 has_player 属性。
  • sessions —— 如果 player 属性已设置并且玩家在线,这会保存连接的所有活动会话(服务器连接)的列表(如果在 settings 中允许多重连接,可能有不止一个会话)。
  • has_player —— 检查当前是否有在线玩家连接到这个物体。
  • contents —— 这是该物体所“包含”的所有物体的列表(也就是将该物体设为 location 的物体的列表)。
  • exits —— 这会返回该物体中所有出口的列表,也就是所有设置了 destination 的物体。
最后两个属性比较特殊:
  • cmdset —— 这是个处理程序,存储了添加在该物体上的所有命令集(如果有的话)。
  • scripts —— 这是个处理程序,用于管理添加在该物体上的脚本(如果有的话)。
物体还带有许多有用的函数。查阅 src/objects/objects.py 中的函数头可以了解函数参数和更多细节。
  • msg() —— 这个函数用于从服务器向连接到该物体的玩家发送消息。
  • msg_contents() —— 对该物体所包含的所有物体调用 msg 函数。
  • search() —— 这是在指定位置或全局搜索特定物体的方法。它主要用于定义命令(比如执行的命令为 caller,可以执行 caller.search() 来查找房间中可以操作的物体)。
  • execute_cmd() —— 让物体执行指定的字符串,如同在命令行上执行一样。
  • move_to —— 将物体完全移动到新的位置。这是主要的移动方式,会调用所有相关的钩子、执行所有检查等。
  • clear_exits() —— 删除所有进出该物体的出口。
  • clear_contents() —— 这不会删除任何东西,而是将其包含的所有物体(除了出口)移到 home 指定的位置。
  • delete() —— 删除该物体,会首先调用 clear_exits() 和 clear_contents()。
除了 at_object_creation,物体类型类还定义很多钩子方法。Evennia会在各种时候调用它们。你在实现自定义物体时可以从父类继承它们,然后用自己的代码重载这些钩子函数。在 src.objects.objects 中有所有可用钩子函数的最新列表。


物体类的子类

在默认的Evennia中,物体类有三个特殊的子类 —— 角色、房间和出口。它们被分离出来是因为这几个类型的物体都很基础,你会一直用到它们,而且在某些情况下游戏引擎需要把它们特定地识别出来(不过你仍然可以重新定义它们)。实际上它们和基类都很相似。

角色
角色是由玩家控制的物体。当新玩家第一次登录到Evennia时会创建一个新的角色对象,并把玩家对象赋给它的 player 属性。角色对象在创建时必须带有默认的命令集,否则玩家无法发出任何命令!如果你只是从 ev.Character 继承自己的类而且没有阻止父类方法的运行,你就不必操心这些。你可以设置 settings 中的 BASE_CHARACTER_TYPECLASS 来更改默认分配给新玩家的类型类。

房间
房间是所有其它物体的基础容器。房间与其它物体的真正不同点在于,它们没有自己的位置,并且由默认命令 @dig 创建。如果你想给房间扩展出更多功能,可以从 ev.Room 继承类。设置 BASE_ROOM_TYPECLASS 可以修改 @dig 默认使用的类。

出口
出口是连接其它物体(通常是房间)的物体。名为“北”、“进入”,以及“门”、“入口”、“跳出窗子”等的物体都可能是出口。出口与其它物体有两方面不同。首先,它们设置了 destination 属性,并指向一个有效的物体。通过这点可以方便快速地在数据库中找到出口。其次,在创建出口时在它们上面定义一个特殊的传输命令,这个命令的名字和出口对象的名字一样,在调用时会将角色移动到出口的目标地点,这可以让你只需输入出口名字就能到处移动,就像你期望的一样。

出口的功能全都定义在出口类型类上,所以原则上你可以完全改变游戏中出口的工作方式(不过不建议你这样做,除非你完全明白你在做什么)。出口使用 traverse 属性保存访问类型,可以控制访问权限,而且使用了几个钩子函数,会在穿越失败时回调。查阅 ev.Exit 可以获取更多的信息。如果你想自定义出口类型,也应该从它继承。设置 settings 中的 BASE_EXIT_TYPECLASS 可以更改如 @dig 和 @open 命令默认使用的类。


其它注意事项

在 game/gamesrc/objects/examples/red_button.py 中有关于自定义物体类的更高级的例子。


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