Add AstronDatabaseInterface, which can generate objects into an Astron DB.
This commit is contained in:
parent
1ca02ae9e1
commit
f74dc9b35d
|
|
@ -0,0 +1,79 @@
|
|||
from pandac.PandaModules import *
|
||||
from MsgTypes import *
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from ConnectionRepository import ConnectionRepository
|
||||
from PyDatagram import PyDatagram
|
||||
from PyDatagramIterator import PyDatagramIterator
|
||||
|
||||
class AstronDatabaseInterface:
|
||||
"""
|
||||
This class is part of Panda3D's new MMO networking framework.
|
||||
It interfaces with Astron database(s) to manage objects directly, rather than
|
||||
via DB-StateServers.
|
||||
|
||||
Do not create this class directly; instead, use AstronInternalRepository's
|
||||
dbInterface attribute.
|
||||
"""
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("AstronDatabaseInterface")
|
||||
|
||||
def __init__(self, air):
|
||||
self.air = air
|
||||
|
||||
self._callbacks = {}
|
||||
|
||||
def createObject(self, databaseId, dclass, fields={}, callback=None):
|
||||
"""
|
||||
Create an object in the specified database.
|
||||
|
||||
databaseId specifies the control channel of the target database.
|
||||
dclass specifies the class of the object to be created.
|
||||
fields is a dict with any fields that should be stored in the object on creation.
|
||||
callback will be called with callback(doId) if specified. On failure, doId is 0.
|
||||
"""
|
||||
|
||||
# Save the callback:
|
||||
ctx = self.air.contextAllocator.allocate()
|
||||
self._callbacks[ctx] = callback
|
||||
|
||||
# Pack up/count valid fields.
|
||||
fieldPacker = DCPacker()
|
||||
fieldCount = 0
|
||||
for k,v in fields.items():
|
||||
field = dclass.getFieldByName(k)
|
||||
if not field:
|
||||
self.notify.warning('Creation request for %s object contains '
|
||||
'invalid field named %s' % (dclass.getName(), k))
|
||||
continue
|
||||
|
||||
fieldPacker.rawPackUint16(field.getNumber())
|
||||
fieldPacker.beginPack(field)
|
||||
field.packArgs(fieldPacker, v)
|
||||
fieldPacker.endPack()
|
||||
fieldCount += 1
|
||||
|
||||
# Now generate and send the datagram:
|
||||
dg = PyDatagram()
|
||||
dg.addServerHeader(databaseId, self.air.ourChannel, DBSERVER_OBJECT_CREATE)
|
||||
dg.addUint32(ctx)
|
||||
dg.addUint16(dclass.getNumber())
|
||||
dg.addUint16(fieldCount)
|
||||
dg.appendData(fieldPacker.getString())
|
||||
self.air.send(dg)
|
||||
|
||||
def handleCreateObjectResp(self, di):
|
||||
ctx = di.getUint32()
|
||||
doId = di.getUint32()
|
||||
|
||||
if ctx not in self._callbacks:
|
||||
self.notify.warning('Received unexpected DBSERVER_OBJECT_CREATE_RESP'
|
||||
' (ctx %d, doId %d)' % (ctx, doId))
|
||||
return
|
||||
|
||||
self._callbacks[ctx](doId)
|
||||
|
||||
del self._callbacks[ctx]
|
||||
self.air.contextAllocator.free(ctx)
|
||||
|
||||
def handleDatagram(self, msgType, di):
|
||||
if msgType == DBSERVER_OBJECT_CREATE_RESP:
|
||||
self.handleCreateObjectResp(di)
|
||||
|
|
@ -4,6 +4,7 @@ from direct.directnotify import DirectNotifyGlobal
|
|||
from ConnectionRepository import ConnectionRepository
|
||||
from PyDatagram import PyDatagram
|
||||
from PyDatagramIterator import PyDatagramIterator
|
||||
from AstronDatabaseInterface import AstronDatabaseInterface
|
||||
|
||||
class AstronInternalRepository(ConnectionRepository):
|
||||
"""
|
||||
|
|
@ -40,6 +41,10 @@ class AstronInternalRepository(ConnectionRepository):
|
|||
self.channelAllocator = UniqueIdAllocator(baseChannel, baseChannel+maxChannels-1)
|
||||
self._registeredChannels = set()
|
||||
|
||||
self.contextAllocator = UniqueIdAllocator(0, 100)
|
||||
|
||||
self.dbInterface = AstronDatabaseInterface(self)
|
||||
|
||||
self.ourChannel = self.allocateChannel()
|
||||
|
||||
self.eventLogId = self.config.GetString('eventlog-id', 'AIR:%d' % self.ourChannel)
|
||||
|
|
@ -137,7 +142,8 @@ class AstronInternalRepository(ConnectionRepository):
|
|||
self.handleObjEntry(di)
|
||||
elif msgType == STATESERVER_OBJECT_LEAVING_AI_INTEREST:
|
||||
self.handleObjExit(di)
|
||||
|
||||
elif msgType in (DBSERVER_OBJECT_CREATE_RESP,):
|
||||
self.dbInterface.handleDatagram(msgType, di)
|
||||
|
||||
def handleObjEntry(self, di):
|
||||
parentId = di.getUint32()
|
||||
|
|
|
|||
Loading…
Reference in New Issue