KBEngine |
KBEngine模块
KBEngine模块提供了Python脚本访问实体的部分,特别是它提供了定时器的注册与移除, 以及实体的创建。类
Entity |
成员函数
def addSpaceGeometryMapping( spaceID, mapper, path, shouldLoadOnServer, params ): |
def addWatcher( path, dataType, getFunction ): |
def address( ): |
def MemoryStream( ): |
def createEntity( entityType, spaceID, position, direction, params ): |
def debugTracing( ): |
def delSpaceData( spaceID, key ): |
def delWatcher( path ): |
def deregisterReadFileDescriptor( fileDescriptor ): |
def deregisterWriteFileDescriptor( fileDescriptor ): |
def executeRawDatabaseCommand( command, callback, threadID, dbInterfaceName ): |
def genUUID64( ): |
def getResFullPath( res ): |
def getSpaceData( spaceID, key ): |
def getSpaceGeometryMapping( spaceID ): |
def getWatcher( path ): |
def getWatcherDir( path ): |
def getAppFlags( ): |
def hasRes( res ): |
def isShuttingDown( ): |
def listPathRes( path, extension ): |
def matchPath( res ): |
def open( res, mode ): |
def publish( ): |
def registerReadFileDescriptor( fileDescriptor, callback ): |
def registerWriteFileDescriptor( fileDescriptor, callback ): |
def raycast( spaceID, layer, src, dst ): |
def reloadScript( fullReload ): |
def scriptLogType( logType ): |
def setAppFlags( flags ): |
def setSpaceData( spaceID, key, value ): |
def time( ): |
回调函数
def onCellAppData( key, value ): |
def onCellAppDataDel( key ): |
def onGlobalData( key, value ): |
def onGlobalDataDel( key ): |
def onInit( isReload ): |
def onSpaceData( spaceID, key, value ): |
def onSpaceGeometryLoaded( spaceID, mapping ): |
def onAllSpaceGeometryLoaded( spaceID, isBootstrap, mapping ): |
属性
LOG_TYPE_DBG | |
LOG_TYPE_ERR | |
LOG_TYPE_INFO | |
LOG_TYPE_NORMAL | |
LOG_TYPE_WAR | |
NEXT_ONLY | |
cellAppData | |
component | 只读 string |
entities | Entities |
globalData | GlobalDataClient |
成员函数文档
def addSpaceGeometryMapping( spaceID, mapper, path, shouldLoadOnServer, params ):
关联一个给定空间的几何映射,函数调用之后服务端和客户端都会加载相应的几何体数据。
在服务端上,从给定目录里加载所有的几何数据到指定的空间。这些数据可能被分成很多区块,不同区块是异步加载的,当所有的几何数据加载 完成的时候下面的通知方法会被调用:
def onAllSpaceGeometryLoaded( self, spaceID, mappingName ):
服务端仅加载场景的几何数据提供给导航和碰撞功能使用,客户端除了几何数据外还会加载纹理等数据。
3D场景当前默认使用的是recastnavigation插件所导出的数据,2D场景当前默认使用的是MapEditor编辑器导出的数据。
有一种可能会导致onAllSpaceGeometryLoaded()不被调用,就是如果在某一个 时刻多个CellApp同时调用这个方法来添加几何到相同的空间的时候CellAppMgr崩溃了。
参数:
spaceID | uint32,空间的ID,指定在哪个空间操作 |
mapper | 目前填None |
path | 包含几何数据的目录路径 |
shouldLoadOnServer | 可选的boolean参数,指定是否在服务端上加载几何。默认为True |
params |
可选的PyDict参数,指定不同layer所使用的navmesh,例如: KBEngine.addSpaceGeometryMapping(self.spaceID, None, resPath, True, {0 : "srv_xinshoucun_1.navmesh", 1 : "srv_xinshoucun.navmesh"}) |
def addWatcher( path, dataType, getFunction ):
与调试监视系统交互,允许用户向监视系统注册一个监视变量。
例:
>>> def countPlayers( ): >>> i = 0 >>> for e in KBEngine.entities.values(): >>> if e.__class__.__name__ == "Avatar": >>> i += 1 >>> return i >>> >>> KBEngine.addWatcher( "players", "UINT32", countPlayers )
这个函数添加一个监视变量在"scripts/players"监视路径之下。函数countPlayers在观察者观察时被调用。
参数:
path | 创建监视的路径。 |
dataType | 监视变量的值类型。参考: 基本类型 |
getFunction | 这个函数当观察者检索该变量时调用。 这个函数不带参数返回一个代表监视变量的值。 |
def address( ):
返回内部网络接口的地址。
def MemoryStream( ):
返回一个新的MemoryStream对象。
MemoryStream对象存储的是二进制信息,提供这个类型是为了让用户能够方便的序列化与反序列化Python基本类型同时能与KBEngine底层序列化规则相同。
例如:你可以使用这个对象构造一个KBEngine能解析的网络数据包。
用法:
>>> s = KBEngine.MemoryStream() >>> s >>> b'' >>> s.append("UINT32", 1) >>> s.pop("UINT32") >>> 1
目前MemoryStream能够支持的类型仅为基本数据类型。参考: 基本类型
def createEntity( entityType, spaceID, position, direction, params ):
createEntity在当前进程指定space中创建一个新的实体。
这个函数需要指定要创建的实体的类别,位置和方向,还可以选择性地设置实体的任意属性(属性在实体的.def文件里描述)。
例子:
# 创建一个打开的门的实体与"thing"实体的位置一样 direction = ( 0, 0, thing.yaw ) properties = { "open":1 } KBEngine.createEntity( "Door", thing.space, thing.position, direction, properties )
参数:
entityType |
string,要创建的实体名称,在 |
spaceID | int32,要放置实体的空间的ID。 |
position | 由3个float组成的序列,指定新实体的出生点,在世界中的坐标。 |
direction | 由3个float组成的序列,指定新实体的初始朝向(roll, pitch, yaw),相对于世界坐标系。 |
params | 可选参数, 一个Python字典对象。 如果一个指定的键是一个Entity属性,他的值会用来初始化这个Entity实体的属性。 |
返回:
新实体。 |
def debugTracing( ):
输出当前KBEngine追踪的Python扩展对象计数器。
扩展对象包括:固定字典、固定数组、Entity、Mailbox...
在服务端正常关闭时如果计数器不为零,此时说明泄露已存在,日志将会输出错误信息。
ERROR cellapp [0x0000cd64] [2014-11-12 00:38:07,300] - PyGC::debugTracing(): FixedArray : leaked(128)
ERROR cellapp [0x0000cd64] [2014-11-12 00:38:07,300] - PyGC::debugTracing(): EntityMailbox : leaked(8)
def delSpaceData( spaceID, key ):
参数:
spaceID | int32,空间的ID。 |
key | string,一个字符串关键字。 |
def delWatcher( path ):
与调试监视系统交互,允许用户在脚本删除监视的变量。
参数:
path | 要删除的变量的路径。 |
def deregisterReadFileDescriptor( fileDescriptor ):
注销已经通过KBEngine.registerReadFileDescriptor注册的回调。
例子:
http://www.kbengine.org/assets/other/py/Poller.py
参数:
fileDescriptor | socket描述符/文件描述符。 |
def deregisterWriteFileDescriptor( fileDescriptor ):
注销已经通过KBEngine.registerWriteFileDescriptor注册的回调。
例子:
http://www.kbengine.org/assets/other/py/Poller.py
参数:
fileDescriptor | socket描述符/文件描述符。 |
def executeRawDatabaseCommand( command, callback, threadID, dbInterfaceName ):
这个脚本函数在数据库上执行原始数据库命令,该命令将直接由相关数据库进行解析。
请注意使用该函数修改实体数据可能不生效,因为如果实体已经检出,被修改过的实体数据将仍会被实体存档而导致覆盖。
强烈不推荐这个函数用于读取或修改实体数据。
参数:
command | 这个数据库命令将会因为不同数据库配置方案而不同。对于方案为MySQL数据库它是一个SQL查询语句。 |
callback | 可选参数,带有命令执行结果的回调对象(比如说是一个函数)。这个回调带有4个参数:结果集合,影响的行数,自増长值,错误信息。 insertid对应的是“自増长值”,类似于实体的databaseID,当成功的向一张带有自増长类型字段的表中插入数据时,它返回该数据在插入时自増长字段所被赋于的值。 |
threadID |
int32,可选参数,指定一个线程来处理本条命令。用户可以通过这个参数控制某一类命令的执行先后顺序(dbmgr是多线程处理的),默认是不指定,如果threadID是实体的ID, 那么将加入到该实体的存档队列中由线程逐条写入。 |
dbInterfaceName | string,可选参数,指定由某个数据库接口来完成, 默认使用"default"接口。数据库接口由kbengine_defaults.xml->dbmgr->databaseInterfaces中定义。 |
def genUUID64( ):
该函数生成一个64位的唯一ID。
注意:这个函数依赖于Cellapps服务进程启动参数gus,请正确设置启动参数保持唯一性。
另外如果gus超过65535则该函数只能在当前进程上保持唯一性。
用途:
多个服务进程上产生唯一物品ID并且在合服时不会产生冲突。
多个服务进程上产生一个房间ID,不需要进行唯一性校验。
返回:
返回一个64位的integer。 |
def getResFullPath( res ):
参数:
res | string,如果存在返回资源的绝对路径,否则返回空。 |
返回:
string,资源的绝对路径。 |
def getSpaceData( spaceID, key ):
参数:
spaceID | int32,空间的ID。 |
key | string,一个字符串关键字。 |
返回:
string,指定key的字符串数据。 |
def getSpaceGeometryMapping( spaceID ):
返回一个指定空间的几何映射名称。
参数:
spaceID | 要查询的空间的id。 |
返回:
string,几何映射名称。 |
def getWatcher( path ):
从KBEngine调试系统中获取一个监视变量的值。
例子:在baseapp1的Python命令行输入:
>>>KBEngine.getWatcher("/root/stats/runningTime")
12673648533
>>>KBEngine.getWatcher("/root/scripts/players")
32133
参数:
path | string,该变量的绝对路径包括变量名(可以在GUIConsole的watcher页查看)。 |
返回:
该变量的值。 |
def getWatcherDir( path ):
从KBEngine调试系统中获取一个监视目录下的元素列表(目录、变量名)。
例子:在baseapp1的Python命令行输入:
>>>KBEngine.getWatcher("/root")
('stats', 'objectPools', 'network', 'syspaths', 'ThreadPool', 'cprofiles', 'scripts', 'numProxices', 'componentID', 'componentType', 'uid', 'numClients', 'globalOrder', 'username', 'load', 'gametime', 'entitiesSize', 'groupOrder')
参数:
path | string,该变量的绝对路径(可以在GUIConsole的watcher页查看)。 |
返回:
监视目录下的元素列表(目录、变量名)。 |
def getAppFlags( ):
返回:
KBEngine.APP_FLAGS_*。 |
def hasRes( res ):
使用这个接口可以判断一个相对路径的资源是否存在。
注意:资源必须在KBE_RES_PATH之下才可以访问到。
例子:
>>>KBEngine.hasRes("scripts/entities.xml")
True
参数:
res | string,资源的相对路径。 |
返回:
BOOL, 存在返回True,否则返回False。 |
def isShuttingDown( ):
返回服务端是否正在关闭中。在onBaseAppShuttingDown回调函数被调用后,这个函数返回True。
返回:
系统正在关闭返回True,否则返回False。 |
def listPathRes( path, extension ):
获得一个资源目录下的资源列表。
注意:资源必须在KBE_RES_PATH之下才可以访问到。
例子:
>>>KBEngine.listPathRes("scripts/cell/interfaces")
('/home/kbe/kbengine/demo/res/scripts/cell/interfaces/AI.py', '/home/kbe/kbengine/demo/res/scripts/cell/interfaces/新建文本文档.txt')
>>>KBEngine.listPathRes("scripts/cell/interfaces", "txt")
('/home/kbe/kbengine/demo/res/scripts/cell/interfaces/新建文本文档.txt')
>>>KBEngine.listPathRes("scripts/cell/interfaces", "txt|py")
('/home/kbe/kbengine/demo/res/scripts/cell/interfaces/AI.py', '/home/kbe/kbengine/demo/res/scripts/cell/interfaces/新建文本文档.txt')
>>>KBEngine.listPathRes("scripts/cell/interfaces", ("txt", "py"))
('/home/kbe/kbengine/demo/res/scripts/cell/interfaces/AI.py', '/home/kbe/kbengine/demo/res/scripts/cell/interfaces/新建文本文档.txt')
参数:
res | string,资源的相对路径。 |
extension | string,可选参数,扩展名。 |
返回:
Tuple, 资源列表。 |
def matchPath( res ):
使用相对路径的资源获得资源的绝对路径。
注意:资源必须在KBE_RES_PATH之下才可以访问到。
例子:
>>>KBEngine.matchPath("scripts/entities.xml")
'/home/kbe/kbengine/demo/res/scripts/entities.xml'
参数:
res | string,资源的相对路径(包括资源名称)。 |
返回:
string, 资源的绝对路径。 |
def open( res, mode ):
参数:
res | string,资源的相对路径。 |
mode |
string,文件操作模式: w 以写方式打开, a 以追加模式打开 (从 EOF 开始, 必要时创建新文件) r+ 以读写模式打开 w+ 以读写模式打开 (参见 w ) a+ 以读写模式打开 (参见 a ) rb 以二进制读模式打开 wb 以二进制写模式打开 (参见 w ) ab 以二进制追加模式打开 (参见 a ) rb+ 以二进制读写模式打开 (参见 r+ ) wb+ 以二进制读写模式打开 (参见 w+ ) ab+ 以二进制读写模式打开 (参见 a+ ) |
def publish( ):
这个接口返回当前服务端发行模式。
返回:
int8,0:debug,1:release,其它可自定义。 |
def raycast( spaceID, layer, src, dst ):
在指定的space中指定的layer中由源坐标向目的坐标射出一道射线,返回碰撞到的坐标点。
注意:space必须使用addSpaceGeometryMapping加载过几何数据。
下面是一个例子:
>>> KBEngine.raycast( spaceID, entity.layer, (0, 10, 0), (0,-10,0) ) ((0.0000, 0.0000, 0.0000), ( (0.0000, 0.0000, 0.0000), (4.0000, 0.0000, 0.0000), (4.0000, 0.0000, 4.0000)), 0)
参数:
spaceID | int32, space的id。 |
layer | int8,几何层。一个space可以同时加载多个navmesh数据,不同的navmesh在不同的layer中,不同的layer可被抽象成地面、水面等等。 |
返回:
list, 碰撞到的坐标点列表。 |
def registerReadFileDescriptor( fileDescriptor, callback ):
参数:
fileDescriptor | socket描述符/文件描述符。 |
callback | 一个回调函数,socket描述符/文件描述符作为它的唯一参数。 |
def registerWriteFileDescriptor( fileDescriptor, callback ):
参数:
fileDescriptor | socket描述符/文件描述符。 |
callback | 一个回调函数,socket描述符/文件描述符作为它的唯一参数。 |
def reloadScript( fullReload ):
重新加载与实体和自定义数据类型相关的Python模块。当前实体类会设置为新加载的类。 这个方法应该只用于开发模式,对于产品模式不合适。下面几点应该注意:
1)重载脚本仅仅能在Cellapp上执行, 用户应该确保所有的服务端组件加载完成。
2)自定义类型在脚本重载后应该确保内存中已经实例化的对象也被更新,下面是一个例子:
for e in KBEngine.entities.values(): if type( e ) is Avatar.Avatar: e.customData.__class__ = CustomClass当这个方法完成时 KBEngine.onInit( True ) 被调用。
参数:
fullReload | 可选的boolean参数,指定是否同时重新加载实体定义。如果这个参数为False,则实体定义不会被重新加载。默认为True。 |
返回:
重新加载成功返回True,否则返回False。 |
def scriptLogType( logType ):
设置当前Python.print输出的信息类型(参考: KBEngine.LOG_TYPE_*)。
def setAppFlags( flags ):
设置当前引擎APP的标记。
KBEngine.APP_FLAGS_NONE // 默认的(未设置标记)
KBEngine.APP_FLAGS_NOT_PARTCIPATING_LOAD_BALANCING //不参与负载均衡
例如:
KBEngine.setAppFlags(KBEngine.APP_FLAGS_NOT_PARTCIPATING_LOAD_BALANCING | KBEngine.APP_FLAGS_*)
def setSpaceData( spaceID, key, value ):
参数:
spaceID | int32,空间的ID。 |
key | string,一个字符串关键字。 |
value | string,字符串值。 |
def time( ):
这个方法返回当前游戏的时间(周期数)。
返回:
uint32,当前游戏的时间,这里指周期数,周期受频率影响,频率由配置文件kbengine.xml或者kbengine_defaults.xml->gameUpdateHertz决定。 |
回调函数文档
def onCellAppData( key, value ):
参数:
key | 被改变数据的键。 |
value | 被改变数据的值。 |
def onCellAppDataDel( key ):
参数:
key | 被删除数据的键。 |
def onGlobalData( key, value ):
参数:
key | 被改变数据的键。 |
value | 被改变数据的值。 |
def onGlobalDataDel( key ):
参数:
key | 被删除数据的键。 |
def onInit( isReload ):
参数:
isReload | bool,是否是被重写加载脚本后触发的。 |
def onSpaceData( spaceID, key, value ):
参数:
spaceID | 空间的ID。 |
key | 被改变数据的键。 |
value | 被改变数据的值。 |
def onSpaceGeometryLoaded( spaceID, mapping ):
参数:
spaceID | 空间的ID。 |
mapping | 网格碰撞数据的映射值。 |
def onAllSpaceGeometryLoaded( spaceID, isBootstrap, mapping ):
参数:
spaceID | 空间的ID。 |
isBootstrap | 如果一个空间被分割由多个cell共同负载,那么isBootstrap描述的是是否为加载请求的发起cell。 |
mapping | 网格碰撞数据的映射值。 |
属性文档
LOG_TYPE_DBG
LOG_TYPE_ERR
LOG_TYPE_INFO
LOG_TYPE_NORMAL
LOG_TYPE_WAR
NEXT_ONLY
这个常量目前在Cellapp未被使用。
cellAppData
这个属性包含一个类字典的对象,这个对象会在所有的CellApps之间自动同步。 当字典的一个值被修改,这个修改会广播到所有的CellApps。
例子:
KBEngine.cellAppData[ "hello" ] = "there"
其余CellApp可以访问下面的:
print KBEngine.cellAppData[ "hello" ]
键和值可以是任意类型,但这些类型必须在所有目标组件上能够被封装和被拆封。
当一个值被改变或被删除,一个回调函数会在所有组件被调用。 参看:KBEngine.onCellAppData和KBEngine.onDelCellAppData。
注意:只有顶层的值才会被广播,如果你有一个值(比如一个列表),它改变了内部的值(比如只是改变一个数),这个信息不会被广播。
不要进行下面的操作:
KBEngine.cellAppData[ "list" ] = [1, 2, 3] KBEngine.cellAppData[ "list" ][1] = 7这样,本地访问是[1, 7, 3],远程访问是[1, 2, 3]。
component
这是正运行在当前Python环境的组件。(至今为止)可能值有'cell', 'base', 'client', 'database', 'bot' 和 'editor'。
entities
entities是一个字典对象,包含当前进程上所有的实体,包括ghost实体。
调试泄露的实体(调用过destroy却没有释放内存的实体,通常是由于被引用导致无法释放):
>>> KBEngine.entities.garbages.items() [(1025, Avatar object at 0x7f92431ceae8.)]
>>> e = _[0][1] >>> import gc >>> gc.get_referents(e) [{'spacesIsOk': True, 'bootstrapIdx': 1},]
调试泄露的KBEngine封装的Python对象:
KBEngine.debugTracing
类型:
Entities |
globalData
这个属性包含一个类字典的对象,这个对象会在所有的BaseApps和CellApps之间自动复制。 当字典的一个值被修改,这个修改会广播到所有的BaseApps和CellApps。CellAppMgr解决竞争条件,保证信息复制的权威性。
例子:
KBEngine.globalData[ "hello" ] = "there"
其余Cellapp或者Baseapp可以访问下面的:
print KBEngine.globalData[ "hello" ]
键和值可以是任意类型,但这些类型必须在所有目标组件上能够被封装和被拆封。
当一个值被改变或被删除,一个回调函数会在所有组件被调用。 参看:KBEngine.onGlobalData和KBEngine.onGlobalDataDel。
注意:只有顶层的值才会被广播,如果你有一个易变的值(比如一个列表),它改变了内部的值(比如只是改变一个数),这个信息不会被广播。
不要进行下面的操作:
KBEngine.globalData[ "list" ] = [1, 2, 3] KBEngine.globalData[ "list" ][1] = 7这样,本地访问是[1, 7, 3],远程访问是[1, 2, 3]。