mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-01 09:23:03 -04:00
OTPServer: client gets zone changes
This commit is contained in:
parent
ec6fab321c
commit
506fe267ba
@ -22,8 +22,12 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
self.setClientDatagram(1)
|
self.setClientDatagram(1)
|
||||||
|
|
||||||
self.recorder = base.recorder
|
self.recorder = base.recorder
|
||||||
|
|
||||||
self.doId2do={}
|
# Dict of {DistributedObject ids : DistributedObjects}
|
||||||
|
self.doId2do = {}
|
||||||
|
if wantOtpServer:
|
||||||
|
# Dict of {parent DistributedObject id : {zoneIds : [child DistributedObject ids]}}
|
||||||
|
self.__doHierarchy = {}
|
||||||
self.readDCFile()
|
self.readDCFile()
|
||||||
self.cache=CRCache.CRCache()
|
self.cache=CRCache.CRCache()
|
||||||
self.serverDelta = 0
|
self.serverDelta = 0
|
||||||
@ -138,52 +142,132 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
it should be accurate plus or minus a couple of seconds.
|
it should be accurate plus or minus a couple of seconds.
|
||||||
"""
|
"""
|
||||||
return time.time() + self.serverDelta
|
return time.time() + self.serverDelta
|
||||||
|
|
||||||
def handleObjectLocation(self, di):
|
if wantOtpServer:
|
||||||
# CLEINT_OBJECT_LOCATION
|
def handleObjectLocation(self, di):
|
||||||
ThedoId = di.getUint32()
|
# CLIENT_OBJECT_LOCATION
|
||||||
TheParent = di.getUint32()
|
doId = di.getUint32()
|
||||||
TheZone = di.getUint32()
|
parentId = di.getUint32()
|
||||||
print "Object Location->Id=%s Parent=%s Zone=%s"%(ThedoId,TheParent, TheZone)
|
zoneId = di.getUint32()
|
||||||
|
obj = self.doId2do.get(doId)
|
||||||
|
if (obj != None):
|
||||||
|
self.notify.info("handleObjectLocation: doId: %s parentId: %s zoneId: %s" %
|
||||||
|
(doId, parentId, zoneId))
|
||||||
|
# Let the object finish the job
|
||||||
|
obj.setLocation(parentId, zoneId)
|
||||||
|
else:
|
||||||
|
ClientRepository.notify.warning(
|
||||||
|
"handleObjectLocation: Asked to update non-existent obj: %s" % (doId))
|
||||||
|
|
||||||
|
def storeObjectLocation(self, objId, parentId, zoneId):
|
||||||
|
# Do not store null values
|
||||||
|
if ((parentId is None) or (zoneId is None)):
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO: check current location
|
||||||
|
obj = self.doId2do.get(objId)
|
||||||
|
oldParentId, oldZoneId = obj.getLocation()
|
||||||
|
|
||||||
|
# Case 1: Same parent, new zone
|
||||||
|
if (oldParentId == parentId):
|
||||||
|
parentZoneDict = self.__doHierarchy.get(parentId)
|
||||||
|
# Remove this objId from the old zone list
|
||||||
|
oldObjList = parentZoneDict.get(oldZoneId)
|
||||||
|
oldObjList.remove(objId)
|
||||||
|
# Add it to the new zone list
|
||||||
|
objList = parentZoneDict.get(zoneId)
|
||||||
|
if objList is None:
|
||||||
|
# No existing objList for this zone, let's make a new one
|
||||||
|
parentZoneDict[zoneId] = [objId]
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# Just add this objId to the existing list
|
||||||
|
assert(objId not in objList)
|
||||||
|
objList.append(objId)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Case 2: New parent, valid old parent
|
||||||
|
# First delete the old location
|
||||||
|
if ((oldParentId is not None) and (oldZoneId is not None)):
|
||||||
|
self.deleteObjectLocation(objId, oldParentId, oldZoneId)
|
||||||
|
# Do not return because we still need to add to the new location
|
||||||
|
|
||||||
|
# Case 2: continued, already deleted from old location
|
||||||
|
# Case 3: New parent - no old parent
|
||||||
|
parentZoneDict = self.__doHierarchy.get(parentId)
|
||||||
|
if parentZoneDict is None:
|
||||||
|
# This parent is not here, just fill the whole entry in
|
||||||
|
self.__doHierarchy[parentId] = {zoneId : [objId]}
|
||||||
|
else:
|
||||||
|
objList = parentZoneDict.get(zoneId)
|
||||||
|
if objList is None:
|
||||||
|
# This parent has no objects in this zone before
|
||||||
|
# create a new entry for this zone and list this objId
|
||||||
|
parentZoneDict[zoneId] = [objId]
|
||||||
|
else:
|
||||||
|
# Just add this objId to the existing list
|
||||||
|
objList.append(objId)
|
||||||
|
|
||||||
|
def deleteObjectLocation(self, objId, parentId, zoneId):
|
||||||
|
# Do not worry about null values
|
||||||
|
if ((parentId is None) or (zoneId is None)):
|
||||||
|
return
|
||||||
|
parentZoneDict = self.__doHierarchy.get(parentId)
|
||||||
|
assert(parentZoneDict is not None, "deleteObjectLocation: parentId: %s not found" % (parentId))
|
||||||
|
objList = parentZoneDict.get(zoneId)
|
||||||
|
assert(objList is not None, "deleteObjectLocation: zoneId: %s not found" % (zoneId))
|
||||||
|
assert(objId in objList, "deleteObjectLocation: objId: %s not found" % (objId))
|
||||||
|
if len(objList) == 1:
|
||||||
|
# If this is the last obj in this zone, delete the entire entry
|
||||||
|
del parentZoneDict[zoneId]
|
||||||
|
else:
|
||||||
|
# Just remove the object
|
||||||
|
objList.remove(objId)
|
||||||
|
|
||||||
|
|
||||||
def handleGenerateWithRequired(self, di):
|
def handleGenerateWithRequired(self, di):
|
||||||
if wantOtpServer:
|
if wantOtpServer:
|
||||||
TheParent = di.getUint32()
|
parentId = di.getUint32()
|
||||||
TheZone = di.getUint32()
|
zoneId = di.getUint32()
|
||||||
# Get the class Id
|
# Get the class Id
|
||||||
classId = di.getUint16();
|
classId = di.getUint16()
|
||||||
# Get the DO Id
|
# Get the DO Id
|
||||||
doId = di.getUint32()
|
doId = di.getUint32()
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
dclass = self.dclassesByNumber[classId]
|
dclass = self.dclassesByNumber[classId]
|
||||||
dclass.startGenerate()
|
dclass.startGenerate()
|
||||||
# Create a new distributed object, and put it in the dictionary
|
# Create a new distributed object, and put it in the dictionary
|
||||||
distObj = self.generateWithRequiredFields(dclass, doId, di)
|
if wantOtpServer:
|
||||||
|
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
|
||||||
|
else:
|
||||||
|
distObj = self.generateWithRequiredFields(dclass, doId, di)
|
||||||
dclass.stopGenerate()
|
dclass.stopGenerate()
|
||||||
|
|
||||||
def handleGenerateWithRequiredOther(self, di):
|
def handleGenerateWithRequiredOther(self, di):
|
||||||
if wantOtpServer:
|
if wantOtpServer:
|
||||||
TheParent = di.getUint32()
|
parentId = di.getUint32()
|
||||||
TheZone = di.getUint32()
|
zoneId = di.getUint32()
|
||||||
# Get the class Id
|
# Get the class Id
|
||||||
classId = di.getUint16();
|
classId = di.getUint16()
|
||||||
# Get the DO Id
|
# Get the DO Id
|
||||||
doId = di.getUint32()
|
doId = di.getUint32()
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
dclass = self.dclassesByNumber[classId]
|
dclass = self.dclassesByNumber[classId]
|
||||||
dclass.startGenerate()
|
dclass.startGenerate()
|
||||||
# Create a new distributed object, and put it in the dictionary
|
# Create a new distributed object, and put it in the dictionary
|
||||||
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
|
if wantOtpServer:
|
||||||
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
|
||||||
|
else:
|
||||||
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
|
||||||
dclass.stopGenerate()
|
dclass.stopGenerate()
|
||||||
|
|
||||||
def handleQuietZoneGenerateWithRequired(self, di):
|
def handleQuietZoneGenerateWithRequired(self, di):
|
||||||
# Special handler for quiet zone generates -- we need to filter
|
# Special handler for quiet zone generates -- we need to filter
|
||||||
if wantOtpServer:
|
if wantOtpServer:
|
||||||
TheParent = di.getUint32()
|
parentId = di.getUint32()
|
||||||
TheZone = di.getUint32()
|
zoneId = di.getUint32()
|
||||||
# Get the class Id
|
# Get the class Id
|
||||||
classId = di.getUint16();
|
classId = di.getUint16()
|
||||||
# Get the DO Id
|
# Get the DO Id
|
||||||
doId = di.getUint32()
|
doId = di.getUint32()
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
@ -196,16 +280,16 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# Create a new distributed object, and put it in the dictionary
|
# Create a new distributed object, and put it in the dictionary
|
||||||
distObj = self.generateWithRequiredFields(dclass, doId, di)
|
distObj = self.generateWithRequiredFields(dclass, doId, di)
|
||||||
else:
|
else:
|
||||||
distObj = self.generateWithRequiredFields(dclass, doId, di)
|
distObj = self.generateWithRequiredFields(dclass, doId, di, parentId, zoneId)
|
||||||
dclass.stopGenerate()
|
dclass.stopGenerate()
|
||||||
|
|
||||||
def handleQuietZoneGenerateWithRequiredOther(self, di):
|
def handleQuietZoneGenerateWithRequiredOther(self, di):
|
||||||
# Special handler for quiet zone generates -- we need to filter
|
# Special handler for quiet zone generates -- we need to filter
|
||||||
if wantOtpServer:
|
if wantOtpServer:
|
||||||
TheParent = di.getUint32()
|
parentId = di.getUint32()
|
||||||
TheZone = di.getUint32()
|
zoneId = di.getUint32()
|
||||||
# Get the class Id
|
# Get the class Id
|
||||||
classId = di.getUint16();
|
classId = di.getUint16()
|
||||||
# Get the DO Id
|
# Get the DO Id
|
||||||
doId = di.getUint32()
|
doId = di.getUint32()
|
||||||
# Look up the dclass
|
# Look up the dclass
|
||||||
@ -218,15 +302,18 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# Create a new distributed object, and put it in the dictionary
|
# Create a new distributed object, and put it in the dictionary
|
||||||
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
|
||||||
else:
|
else:
|
||||||
distObj = self.generateWithRequiredOtherFields(dclass, doId, di)
|
distObj = self.generateWithRequiredOtherFields(dclass, doId, di, parentId, zoneId)
|
||||||
dclass.stopGenerate()
|
dclass.stopGenerate()
|
||||||
|
|
||||||
def generateWithRequiredFields(self, dclass, doId, di):
|
# wantOtpServer: remove the None defaults when we remove this config variable
|
||||||
|
def generateWithRequiredFields(self, dclass, doId, di, parentId = None, zoneId = None):
|
||||||
if self.doId2do.has_key(doId):
|
if self.doId2do.has_key(doId):
|
||||||
# ...it is in our dictionary.
|
# ...it is in our dictionary.
|
||||||
# Just update it.
|
# Just update it.
|
||||||
distObj = self.doId2do[doId]
|
distObj = self.doId2do[doId]
|
||||||
assert(distObj.dclass == dclass)
|
assert(distObj.dclass == dclass)
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredFields(dclass, di)
|
distObj.updateRequiredFields(dclass, di)
|
||||||
# updateRequiredFields calls announceGenerate
|
# updateRequiredFields calls announceGenerate
|
||||||
@ -238,6 +325,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# put it in the dictionary:
|
# put it in the dictionary:
|
||||||
self.doId2do[doId] = distObj
|
self.doId2do[doId] = distObj
|
||||||
# and update it.
|
# and update it.
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredFields(dclass, di)
|
distObj.updateRequiredFields(dclass, di)
|
||||||
# updateRequiredFields calls announceGenerate
|
# updateRequiredFields calls announceGenerate
|
||||||
@ -254,6 +343,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# Put the new do in the dictionary
|
# Put the new do in the dictionary
|
||||||
self.doId2do[doId] = distObj
|
self.doId2do[doId] = distObj
|
||||||
# Update the required fields
|
# Update the required fields
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generateInit() # Only called when constructed
|
distObj.generateInit() # Only called when constructed
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredFields(dclass, di)
|
distObj.updateRequiredFields(dclass, di)
|
||||||
@ -279,17 +370,24 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# Put the new do in the dictionary
|
# Put the new do in the dictionary
|
||||||
self.doId2do[doId] = distObj
|
self.doId2do[doId] = distObj
|
||||||
# Update the required fields
|
# Update the required fields
|
||||||
|
if wantOtpServer:
|
||||||
|
# TODO: ROGER: where should we get parentId and zoneId?
|
||||||
|
parentId = None
|
||||||
|
zoneId = None
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generateInit() # Only called when constructed
|
distObj.generateInit() # Only called when constructed
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
# updateRequiredFields calls announceGenerate
|
# updateRequiredFields calls announceGenerate
|
||||||
return distObj
|
return distObj
|
||||||
|
|
||||||
def generateWithRequiredOtherFields(self, dclass, doId, di):
|
def generateWithRequiredOtherFields(self, dclass, doId, di, parentId = None, zoneId = None):
|
||||||
if self.doId2do.has_key(doId):
|
if self.doId2do.has_key(doId):
|
||||||
# ...it is in our dictionary.
|
# ...it is in our dictionary.
|
||||||
# Just update it.
|
# Just update it.
|
||||||
distObj = self.doId2do[doId]
|
distObj = self.doId2do[doId]
|
||||||
assert(distObj.dclass == dclass)
|
assert(distObj.dclass == dclass)
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredOtherFields(dclass, di)
|
distObj.updateRequiredOtherFields(dclass, di)
|
||||||
# updateRequiredOtherFields calls announceGenerate
|
# updateRequiredOtherFields calls announceGenerate
|
||||||
@ -301,6 +399,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# put it in the dictionary:
|
# put it in the dictionary:
|
||||||
self.doId2do[doId] = distObj
|
self.doId2do[doId] = distObj
|
||||||
# and update it.
|
# and update it.
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredOtherFields(dclass, di)
|
distObj.updateRequiredOtherFields(dclass, di)
|
||||||
# updateRequiredOtherFields calls announceGenerate
|
# updateRequiredOtherFields calls announceGenerate
|
||||||
@ -317,6 +417,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
# Put the new do in the dictionary
|
# Put the new do in the dictionary
|
||||||
self.doId2do[doId] = distObj
|
self.doId2do[doId] = distObj
|
||||||
# Update the required fields
|
# Update the required fields
|
||||||
|
if wantOtpServer:
|
||||||
|
distObj.setLocation(parentId, zoneId)
|
||||||
distObj.generateInit() # Only called when constructed
|
distObj.generateInit() # Only called when constructed
|
||||||
distObj.generate()
|
distObj.generate()
|
||||||
distObj.updateRequiredOtherFields(dclass, di)
|
distObj.updateRequiredOtherFields(dclass, di)
|
||||||
@ -467,7 +569,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
self.handleGenerateWithRequiredOther(di)
|
self.handleGenerateWithRequiredOther(di)
|
||||||
elif wantOtpServer and msgType == CLIENT_DONE_SET_ZONE_RESP:
|
elif wantOtpServer and msgType == CLIENT_DONE_SET_ZONE_RESP:
|
||||||
self.handleSetZoneDone()
|
self.handleSetZoneDone()
|
||||||
elif wantOtpServer and msgType == CLEINT_OBJECT_LOCATION:
|
elif wantOtpServer and msgType == CLIENT_OBJECT_LOCATION:
|
||||||
self.handleObjectLocation(di)
|
self.handleObjectLocation(di)
|
||||||
else:
|
else:
|
||||||
currentLoginState = self.loginFSM.getCurrentState()
|
currentLoginState = self.loginFSM.getCurrentState()
|
||||||
@ -541,22 +643,22 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||||||
## interest managment
|
## interest managment
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
def InterestAdd(self, parentId, zoneId, Description):
|
def InterestAdd(self, parentId, zoneId, Description):
|
||||||
"""
|
"""
|
||||||
Part of the new otp-server code.
|
Part of the new otp-server code.
|
||||||
"""
|
"""
|
||||||
self.__interest_id_assign += 1
|
self.__interest_id_assign += 1
|
||||||
self.__interesthash[self.__interest_id_assign] = Description
|
self.__interesthash[self.__interest_id_assign] = Description
|
||||||
contextId = self.__interest_id_assign;
|
contextId = self.__interest_id_assign
|
||||||
self.__sendAddInterest(contextId, parentId, zoneId)
|
self.__sendAddInterest(contextId, parentId, zoneId)
|
||||||
self.DumpInterests()
|
self.DumpInterests()
|
||||||
return contextId;
|
return contextId
|
||||||
|
|
||||||
def InterestRemove(self, contextId):
|
def InterestRemove(self, contextId):
|
||||||
"""
|
"""
|
||||||
Part of the new otp-server code.
|
Part of the new otp-server code.
|
||||||
"""
|
"""
|
||||||
answer = 0;
|
answer = 0
|
||||||
if self.__interesthash.has_key(contextId):
|
if self.__interesthash.has_key(contextId):
|
||||||
self.__sendRemoveInterest(contextId)
|
self.__sendRemoveInterest(contextId)
|
||||||
del self.__interesthash[contextId]
|
del self.__interesthash[contextId]
|
||||||
|
@ -31,6 +31,9 @@ class DistributedObject(PandaObject):
|
|||||||
except:
|
except:
|
||||||
self.DistributedObject_initialized = 1
|
self.DistributedObject_initialized = 1
|
||||||
self.cr = cr
|
self.cr = cr
|
||||||
|
if wantOtpServer:
|
||||||
|
# Location stores the parentId, zoneId of this object
|
||||||
|
self.__location = (None, None)
|
||||||
|
|
||||||
# Most DistributedObjects are simple and require no real
|
# Most DistributedObjects are simple and require no real
|
||||||
# effort to load. Some, particularly actors, may take
|
# effort to load. Some, particularly actors, may take
|
||||||
@ -150,6 +153,10 @@ class DistributedObject(PandaObject):
|
|||||||
assert(self.notify.debug('disable(): %s' % (self.doId)))
|
assert(self.notify.debug('disable(): %s' % (self.doId)))
|
||||||
self.activeState = ESDisabled
|
self.activeState = ESDisabled
|
||||||
self.__callbacks = {}
|
self.__callbacks = {}
|
||||||
|
if wantOtpServer:
|
||||||
|
self.cr.deleteObjectLocation(self.doId, self.__location[0], self.__location[1])
|
||||||
|
self.__location = (None, None)
|
||||||
|
# TODO: disable my children
|
||||||
|
|
||||||
def isDisabled(self):
|
def isDisabled(self):
|
||||||
"""
|
"""
|
||||||
@ -325,5 +332,13 @@ class DistributedObject(PandaObject):
|
|||||||
if self.__barrierContext != None:
|
if self.__barrierContext != None:
|
||||||
self.sendUpdate("setBarrierReady", [self.__barrierContext])
|
self.sendUpdate("setBarrierReady", [self.__barrierContext])
|
||||||
self.__barrierContext = None
|
self.__barrierContext = None
|
||||||
|
|
||||||
|
if wantOtpServer:
|
||||||
|
def setLocation(self, parentId, zoneId):
|
||||||
|
# The store must run first so we know the old location
|
||||||
|
self.cr.storeObjectLocation(self.doId, parentId, zoneId)
|
||||||
|
self.__location = (parentId, zoneId)
|
||||||
|
|
||||||
|
def getLocation(self):
|
||||||
|
return self.__location
|
||||||
|
|
||||||
|
@ -72,12 +72,11 @@ CLIENT_GET_PET_DETAILS = 81
|
|||||||
CLIENT_GET_PET_DETAILS_RESP = 82
|
CLIENT_GET_PET_DETAILS_RESP = 82
|
||||||
|
|
||||||
# (Proposed new message): CLIENT_SET_WORLD_POS = 83
|
# (Proposed new message): CLIENT_SET_WORLD_POS = 83
|
||||||
|
|
||||||
CLIENT_ADD_INTEREST = 97
|
|
||||||
CLEINT_ALTER_INTEREST = 98
|
|
||||||
CLEINT_REMOVE_INTEREST = 99
|
|
||||||
if wantOtpServer:
|
if wantOtpServer:
|
||||||
CLEINT_OBJECT_LOCATION = 102
|
CLIENT_ADD_INTEREST = 97
|
||||||
|
CLIENT_ALTER_INTEREST = 98
|
||||||
|
CLIENT_REMOVE_INTEREST = 99
|
||||||
|
CLIENT_OBJECT_LOCATION = 102
|
||||||
|
|
||||||
# These messages are ignored when the client is headed to the quiet zone
|
# These messages are ignored when the client is headed to the quiet zone
|
||||||
QUIET_ZONE_IGNORED_LIST = [
|
QUIET_ZONE_IGNORED_LIST = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user