panda3d/direct/src/distributed/ClientRepository.py
2000-10-31 16:05:42 +00:00

141 lines
5.2 KiB
Python

"""ClientRepository module: contains the ClientRepository class"""
from PandaModules import *
from TaskManagerGlobal import *
from MsgTypes import *
import Task
import DirectNotifyGlobal
import ClientDistClass
# The repository must import all known types of Distributed Objects
import DistributedObject
import DistributedToon
import DirectObject
class ClientRepository(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository")
def __init__(self, dcFileName, AIClientFlag=0):
self.AIClientFlag=AIClientFlag
self.number2cdc={}
self.name2cdc={}
self.doId2do={}
self.doId2cdc={}
self.parseDcFile(dcFileName)
return None
def parseDcFile(self, dcFileName):
self.dcFile = DCFile()
self.dcFile.read(dcFileName)
return self.parseDcClasses(self.dcFile)
def parseDcClasses(self, dcFile):
numClasses = dcFile.getNumClasses()
for i in range(0, numClasses):
# Create a clientDistClass from the dcClass
dcClass = dcFile.getClass(i)
clientDistClass = ClientDistClass.ClientDistClass(dcClass)
# List the cdc in the number and name dictionaries
self.number2cdc[dcClass.getNumber()]=clientDistClass
self.name2cdc[dcClass.getName()]=clientDistClass
return None
def connect(self, serverName, serverPort):
self.qcm=QueuedConnectionManager()
self.tcpConn = self.qcm.openTCPClientConnection(
serverName, serverPort, 1000)
self.qcr=QueuedConnectionReader(self.qcm, 0)
self.qcr.addConnection(self.tcpConn)
self.cw=ConnectionWriter(self.qcm, 0)
self.startReaderPollTask()
def startReaderPollTask(self):
task = Task.Task(self.readerPollUntilEmpty)
taskMgr.spawnTaskNamed(task, "readerPollTask")
return None
def readerPollUntilEmpty(self, task):
while self.readerPollOnce():
pass
return Task.cont
def readerPollOnce(self):
availGetVal = self.qcr.dataAvailable()
if availGetVal:
print "Client: Incoming message!"
datagram = NetDatagram()
readRetVal = self.qcr.getData(datagram)
if readRetVal:
self.handleDatagram(datagram)
else:
ClientRepository.notify.warning("getData returned false")
return availGetVal
def handleDatagram(self, datagram):
# This class is meant to be pure virtual, and any classes that
# inherit from it need to make their own handleDatagram method
pass
def handleGenerateWithRequired(self, di):
# Get the class Id
classId = di.getArg(STUint16);
# Get the DO Id
doId = di.getArg(STUint32)
# Look up the cdc
cdc = self.number2cdc[classId]
# Create a new distributed object, and put it in the dictionary
distObj = self.generateWithRequiredFields(cdc,
eval(cdc.name + \
"." + \
cdc.name),
doId, di)
return None
def generateWithRequiredFields(self, cdc, constructor, doId, di):
# Someday, this function will look in a cache of old distributed
# objects to see if this object is in there, and pull it
# out if necessary. For now, we'll just check to see if
# it is in the standard dictionary, and ignore this update
# if it is there. The right thing to do would be to update
# all the required fields, but that will come later, too.
if self.doId2do.has_key(doId):
ClientRepository.notify.warning("doId: " +
str(doId) +
" was generated again")
distObj = self.doId2do[doId]
distObj.updateRequiredFields(cdc, di)
else:
# Construct a new one
distObj = constructor()
# Assign it an Id
distObj.doId = doId
# Update the required fields
distObj.updateRequiredFields(cdc, di)
# Put the new do in both dictionaries
self.doId2do[doId] = distObj
self.doId2cdc[doId] = cdc
return distObj
def handleUpdateField(self, di):
# Get the DO Id
doId = di.getArg(ST_uint32)
# Find the DO
assert(self.doId2do.has_key(doId))
do = self.doId2do(doId)
# Find the cdc
assert(self.doId2cdc.has_key(doId))
cdc = self.doId2cdc[doId]
# Let the cdc finish the job
cdc.updateField(do, di)
def sendUpdate(self, do, fieldName, args):
# Get the DO id
doId = do.doId
# Get the cdc
assert(self.doId2cdc.has_key(doId))
cdc = self.doId2cdc[doId]
# Let the cdc finish the job
cdc.sendUpdate(do, fieldName, args)