move interest code to DoInterestManager

This commit is contained in:
Dave Schuyler 2005-01-28 02:55:41 +00:00
parent bfbfcc0f74
commit d50d46a46e
4 changed files with 135 additions and 129 deletions

View File

@ -15,13 +15,13 @@ from PyDatagram import PyDatagram
from PyDatagramIterator import PyDatagramIterator from PyDatagramIterator import PyDatagramIterator
class ClientRepository(ConnectionRepository.ConnectionRepository): class ClientRepository(ConnectionRepository.ConnectionRepository):
"""
""" This maintains a client-side connection with a Panda server. This maintains a client-side connection with a Panda server.
It currently supports several different versions of the server: It currently supports several different versions of the server:
within the VR Studio, we are currently in transition from the within the VR Studio, we are currently in transition from the
Toontown server to the OTP server; people outside the VR studio Toontown server to the OTP server; people outside the VR studio
will use the Panda LAN server provided by CMU.""" will use the Panda LAN server provided by CMU.
"""
notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository") notify = DirectNotifyGlobal.directNotify.newCategory("ClientRepository")
def __init__(self): def __init__(self):
@ -29,11 +29,11 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.setClientDatagram(1) self.setClientDatagram(1)
self.recorder = base.recorder self.recorder = base.recorder
if wantOtpServer: if wantOtpServer:
# this is used to imulate the old setzone behavior # this is used to imulate the old setzone behavior
# with set locationa and set interest # with set locationa and set interest
self.old_setzone_interest_handle = None self.old_setzone_interest_handle = None
# Dict of {DistributedObject ids : DistributedObjects} # Dict of {DistributedObject ids : DistributedObjects}
self.doId2do = {} self.doId2do = {}
if wantOtpServer: if wantOtpServer:
@ -49,7 +49,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.worldScale = render.attachNewNode("worldScale") # for grid zones. self.worldScale = render.attachNewNode("worldScale") # for grid zones.
self.worldScale.setScale(base.config.GetFloat('world-scale', 100)) self.worldScale.setScale(base.config.GetFloat('world-scale', 100))
self.priorWorldPos = None self.priorWorldPos = None
# create a parentMgr to handle distributed reparents # create a parentMgr to handle distributed reparents
# this used to be 'token2nodePath' # this used to be 'token2nodePath'
self.parentMgr = ParentMgr.ParentMgr() self.parentMgr = ParentMgr.ParentMgr()
@ -63,12 +63,12 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.heartbeatInterval = base.config.GetDouble('heartbeat-interval', 10) self.heartbeatInterval = base.config.GetDouble('heartbeat-interval', 10)
self.heartbeatStarted = 0 self.heartbeatStarted = 0
self.lastHeartbeat = 0 self.lastHeartbeat = 0
if wantOtpServer: #%# if wantOtpServer:
# Top level Interest Manager #%# # Top level Interest Manager
self._interestIdAssign = 1 #%# self._interestIdAssign = 1
self._interestIdScops = 100; #%# self._interestIdScops = 100;
self._interests = {} #%# self._interests = {}
# By default, the ClientRepository is set up to respond to # By default, the ClientRepository is set up to respond to
# datagrams from the CMU Panda LAN server. You can # datagrams from the CMU Panda LAN server. You can
@ -169,7 +169,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
if wantOtpServer: if wantOtpServer:
def handleObjectLocation(self, di): def handleObjectLocation(self, di):
# CLIENT_OBJECT_LOCATION # CLIENT_OBJECT_LOCATION
doId = di.getUint32() doId = di.getUint32()
parentId = di.getUint32() parentId = di.getUint32()
zoneId = di.getUint32() zoneId = di.getUint32()
@ -208,7 +208,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# Just add this objId to the existing list # Just add this objId to the existing list
assert(objId not in objList) assert(objId not in objList)
objList.append(objId) objList.append(objId)
return return
# Case 2: New parent, valid old parent # Case 2: New parent, valid old parent
# First delete the old location # First delete the old location
@ -247,17 +247,17 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
else: else:
# Just remove the object # Just remove the object
objList.remove(objId) objList.remove(objId)
def handleGenerateWithRequired(self, di): def handleGenerateWithRequired(self, di):
if wantOtpServer: if wantOtpServer:
parentId = di.getUint32() parentId = di.getUint32()
zoneId = 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
@ -268,9 +268,9 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
dclass.stopGenerate() dclass.stopGenerate()
def handleGenerateWithRequiredOther(self, di): def handleGenerateWithRequiredOther(self, di):
if wantOtpServer: if wantOtpServer:
parentId = di.getUint32() parentId = di.getUint32()
zoneId = 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
@ -287,9 +287,9 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
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:
parentId = di.getUint32() parentId = di.getUint32()
zoneId = 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
@ -309,9 +309,9 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
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:
parentId = di.getUint32() parentId = di.getUint32()
zoneId = 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
@ -382,7 +382,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
dclass = self.dclassesByName[dcname] dclass = self.dclassesByName[dcname]
# 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)
# Construct a new one # Construct a new one
classDef = dclass.getClassDef() classDef = dclass.getClassDef()
if classDef == None: if classDef == None:
@ -535,7 +535,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
doId = di.getUint32() doId = di.getUint32()
#print("Updating " + str(doId)) #print("Updating " + str(doId))
# Find the DO # Find the DO
do = self.doId2do.get(doId) do = self.doId2do.get(doId)
if (do != None): if (do != None):
# Let the dclass finish the job # Let the dclass finish the job
@ -573,11 +573,10 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
def handleSetDOIDrange(self, di): def handleSetDOIDrange(self, di):
# This method is only used in conjunction with the CMU LAN # This method is only used in conjunction with the CMU LAN
# server. # server.
self.DOIDbase = di.getUint32() self.DOIDbase = di.getUint32()
self.DOIDlast = self.DOIDbase + di.getUint32() self.DOIDlast = self.DOIDbase + di.getUint32()
self.DOIDnext = self.DOIDbase self.DOIDnext = self.DOIDbase
return None
def handleRequestGenerates(self, di): def handleRequestGenerates(self, di):
# When new clients join the zone of an object, they need to hear # When new clients join the zone of an object, they need to hear
@ -586,7 +585,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# This method is only used in conjunction with the CMU LAN # This method is only used in conjunction with the CMU LAN
# server. # server.
assert(self.DOIDnext < self.DOIDlast); assert(self.DOIDnext < self.DOIDlast);
zone = di.getUint32() zone = di.getUint32()
for obj in self.doId2do.values(): for obj in self.doId2do.values():
@ -595,7 +594,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
if (self.isLocalId(id)): if (self.isLocalId(id)):
self.send(obj.dclass.clientFormatGenerate(obj, id, zone, [])) self.send(obj.dclass.clientFormatGenerate(obj, id, zone, []))
def handleUnexpectedMsgType(self, msgType, di): def handleUnexpectedMsgType(self, msgType, di):
if msgType == CLIENT_GO_GET_LOST: if msgType == CLIENT_GO_GET_LOST:
self.handleGoGetLost(di) self.handleGoGetLost(di)
elif msgType == CLIENT_HEARTBEAT: elif msgType == CLIENT_HEARTBEAT:
@ -618,7 +617,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_OTHER: elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_OTHER:
self.handleGenerateWithRequiredOther(di) self.handleGenerateWithRequiredOther(di)
elif msgType == CLIENT_DONE_INTEREST_RESP: elif msgType == CLIENT_DONE_INTEREST_RESP:
self.handleInterestDoneMessage(di) self.handleInterestDoneMessage(di)
elif msgType == CLIENT_OBJECT_LOCATION: elif msgType == CLIENT_OBJECT_LOCATION:
self.handleObjectLocation(di) self.handleObjectLocation(di)
else: else:
@ -715,52 +714,52 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
if wantOtpServer: if wantOtpServer:
def sendEmulateSetZone(self, zoneId, visibleZoneList=None, parentIdin=None, event=None): def sendEmulateSetZone(self, zoneId, visibleZoneList=None, parentIdin=None, event=None):
""" """
This Will Move The avatar and set an interest to that location .. This Will Move The avatar and set an interest to that location ..
""" """
parentId = parentIdin; parentId = parentIdin;
if parentId is None: if parentId is None:
parentId = base.localAvatar.defaultShard; parentId = base.localAvatar.defaultShard;
MyAvID = base.localAvatar.doId; MyAvID = base.localAvatar.doId;
# move thwe avatar.. # move thwe avatar..
self.sendSetLocation(MyAvID,parentId,zoneId); self.sendSetLocation(MyAvID,parentId,zoneId);
# move the interest.. # move the interest..
InterestZones = zoneId; InterestZones = zoneId;
if visibleZoneList is not None: if visibleZoneList is not None:
InterestZones = visibleZoneList InterestZones = visibleZoneList
if(self.old_setzone_interest_handle == None): if(self.old_setzone_interest_handle == None):
self.old_setzone_interest_handle = self.addInterest(parentId, InterestZones, "OldSetZone Imulator", event) self.old_setzone_interest_handle = self.addInterest(parentId, InterestZones, "OldSetZone Imulator", event)
else: else:
self.alterInterest(self.old_setzone_interest_handle,parentId, InterestZones, "OldSetZone Imulator", event) self.alterInterest(self.old_setzone_interest_handle,parentId, InterestZones, "OldSetZone Imulator", event)
def sendEmulateSetZoneOff(self): def sendEmulateSetZoneOff(self):
MyAvID = base.localAvatar.doId; MyAvID = base.localAvatar.doId;
self.sendSetLocation(MyAvID,0,0); self.sendSetLocation(MyAvID,0,0);
if self.old_setzone_interest_handle is not None: if self.old_setzone_interest_handle is not None:
self.removeInterest(self.old_setzone_interest_handle) self.removeInterest(self.old_setzone_interest_handle)
self.old_setzone_interest_handle = None self.old_setzone_interest_handle = None
def sendSetLocation(self,doId,parentId,zoneId): def sendSetLocation(self,doId,parentId,zoneId):
datagram = PyDatagram() datagram = PyDatagram()
datagram.addUint16(CLIENT_OBJECT_LOCATION) datagram.addUint16(CLIENT_OBJECT_LOCATION)
datagram.addUint32(doId) datagram.addUint32(doId)
datagram.addUint32(parentId) datagram.addUint32(parentId)
datagram.addUint32(zoneId) datagram.addUint32(zoneId)
self.send(datagram) self.send(datagram)
else: else:
def sendSetZoneMsg(self, zoneId, visibleZoneList=None): def sendSetZoneMsg(self, zoneId, visibleZoneList=None):
datagram = PyDatagram() datagram = PyDatagram()
# Add message type # Add message type
datagram.addUint16(CLIENT_SET_ZONE) datagram.addUint16(CLIENT_SET_ZONE)
# Add zone id # Add zone id
datagram.addUint32(zoneId) datagram.addUint32(zoneId)
# if we have an explicit list of visible zones, add them # if we have an explicit list of visible zones, add them
if visibleZoneList is not None: if visibleZoneList is not None:
vzl = list(visibleZoneList) vzl = list(visibleZoneList)
@ -778,7 +777,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
di.getDatagram().dumpHex(ostream) di.getDatagram().dumpHex(ostream)
msgType = self.getMsgType() msgType = self.getMsgType()
if not wantOtpServer: if not wantOtpServer:
if msgType == CLIENT_DONE_SET_ZONE_RESP: if msgType == CLIENT_DONE_SET_ZONE_RESP:
@ -788,7 +787,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self.handleUnexpectedMsgType(msgType, di) self.handleUnexpectedMsgType(msgType, di)
else: else:
self.handler(msgType, di) self.handler(msgType, di)
# If we're processing a lot of datagrams within one frame, we # If we're processing a lot of datagrams within one frame, we
# may forget to send heartbeats. Keep them coming! # may forget to send heartbeats. Keep them coming!
self.considerHeartbeat() self.considerHeartbeat()
@ -797,7 +796,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
# These are the sort of messages we may expect from the public # These are the sort of messages we may expect from the public
# Panda server. # Panda server.
if msgType == CLIENT_SET_DOID_RANGE: if msgType == CLIENT_SET_DOID_RANGE:
self.handleSetDOIDrange(di) self.handleSetDOIDrange(di)
elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_RESP: elif msgType == CLIENT_CREATE_OBJECT_REQUIRED_RESP:
@ -815,9 +814,10 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
else: else:
self.handleUnexpectedMsgType(msgType, di) self.handleUnexpectedMsgType(msgType, di)
if wantOtpServer: #%#:
# interest managment if 0 and wantOtpServer:
# interest managment
def addInterest(self, parentId, zoneIdList, description, event=None): def addInterest(self, parentId, zoneIdList, description, event=None):
""" """
Part of the new otp-server code. Part of the new otp-server code.
@ -830,53 +830,53 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
self._sendAddInterest(contextId, scopeId, parentId, zoneIdList) self._sendAddInterest(contextId, scopeId, parentId, zoneIdList)
assert self.printInterests() assert self.printInterests()
return contextId return contextId
def removeInterest(self, contextId, event=None): def removeInterest(self, contextId, event=None):
""" """
Part of the new otp-server code. Part of the new otp-server code.
""" """
answer = 0 answer = 0
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
if event is not None: if event is not None:
self._interestIdScops += 1 self._interestIdScops += 1
self._interests[contextId][2] = event self._interests[contextId][2] = event
self._interests[contextId][1] = self._interestIdScops self._interests[contextId][1] = self._interestIdScops
self._sendRemoveInterest(contextId) self._sendRemoveInterest(contextId)
del self._interests[contextId] del self._interests[contextId]
else: else:
self._interests[contextId][3] = "PendingDel" self._interests[contextId][3] = "PendingDel"
self._interests[contextId][2] = None self._interests[contextId][2] = None
self._interests[contextId][1] = 0 self._interests[contextId][1] = 0
self._sendRemoveInterest(contextId) self._sendRemoveInterest(contextId)
answer = 1 answer = 1
assert self.printInterests() assert self.printInterests()
return answer return answer
def alterInterest(self, contextId, parentId, zoneIdList, description = None, event=None): def alterInterest(self, contextId, parentId, zoneIdList, description = None, event=None):
""" """
Part of the new otp-server code. Part of the new otp-server code.
Removes old and adds new.. Removes old and adds new..
""" """
answer = 0 answer = 0
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
self._interestIdScops += 1 self._interestIdScops += 1
if description is not None: if description is not None:
self._interests[contextId][0] = description self._interests[contextId][0] = description
self._interests[contextId][1] = self._interestIdScops; self._interests[contextId][1] = self._interestIdScops;
self._interests[contextId][2] = event; self._interests[contextId][2] = event;
self._sendAddInterest(contextId,self._interestIdScops, parentId, zoneIdList) self._sendAddInterest(contextId,self._interestIdScops, parentId, zoneIdList)
answer = 1 answer = 1
assert self.printInterests() assert self.printInterests()
else: else:
self.notify.warning("alterInterest: contextId not found: %s" % (contextId)) self.notify.warning("alterInterest: contextId not found: %s" % (contextId))
return answer return answer
def GetInterestScopeID(self, contextId): def GetInterestScopeID(self, contextId):
""" """
Part of the new otp-server code. Part of the new otp-server code.
Return a ScopeId Id for an Interest Return a ScopeId Id for an Interest
""" """
answer = 0 answer = 0
@ -885,11 +885,11 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
else: else:
self.notify.warning("GetInterestScopeID: contextId not found: %s" % (contextId)) self.notify.warning("GetInterestScopeID: contextId not found: %s" % (contextId))
return answer return answer
def GetInterestScopeEvent(self, contextId): def GetInterestScopeEvent(self, contextId):
""" """
Part of the new otp-server code. Part of the new otp-server code.
Return a ScopeId Id for an Interest Return a ScopeId Id for an Interest
""" """
answer = None answer = None
@ -898,29 +898,29 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
else: else:
self.notify.warning("GetInterestScopeEvent: contextId not found: %s" % (contextId)) self.notify.warning("GetInterestScopeEvent: contextId not found: %s" % (contextId))
return answer return answer
def _PonderRemoveFlaggedInterest(self, handle): def _PonderRemoveFlaggedInterest(self, handle):
""" """
Part of the new otp-server code. Part of the new otp-server code.
Return a ScopeId Id for an Interest Return a ScopeId Id for an Interest
""" """
answer = None answer = None
if self._interests.has_key(handle): if self._interests.has_key(handle):
if self._interests[handle][3] == "PendingDel": if self._interests[handle][3] == "PendingDel":
del self._interests[handle] del self._interests[handle]
if __debug__: if __debug__:
def printInterests(self): def printInterests(self):
""" """
Part of the new otp-server code. Part of the new otp-server code.
""" """
print "*********************** Interest Sets **************" print "*********************** Interest Sets **************"
for i in self._interests.keys(): for i in self._interests.keys():
print "Interest ID:%s, Description=%s Scope=%s Event=%s Mode=%s"%(i, self._interests[i][0],self._interests[i][1],self._interests[i][2],self._interests[i][3]) print "Interest ID:%s, Description=%s Scope=%s Event=%s Mode=%s"%(i, self._interests[i][0],self._interests[i][1],self._interests[i][2],self._interests[i][3])
print "****************************************************" print "****************************************************"
return 1 # for assert() return 1 # for assert()
def _sendAddInterest(self, contextId, scopeId, parentId, zoneIdList): def _sendAddInterest(self, contextId, scopeId, parentId, zoneIdList):
""" """
Part of the new otp-server code. Part of the new otp-server code.
@ -936,17 +936,17 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
datagram.addUint16(contextId) datagram.addUint16(contextId)
datagram.addUint32(scopeId) datagram.addUint32(scopeId)
datagram.addUint32(parentId) datagram.addUint32(parentId)
print zoneIdList print zoneIdList
if isinstance(zoneIdList,types.ListType): if isinstance(zoneIdList,types.ListType):
vzl = list(zoneIdList) vzl = list(zoneIdList)
vzl.sort() vzl.sort()
PythonUtil.uniqueElements(vzl) PythonUtil.uniqueElements(vzl)
for zone in vzl: for zone in vzl:
datagram.addUint32(zone) datagram.addUint32(zone)
else: else:
datagram.addUint32(zoneIdList) datagram.addUint32(zoneIdList)
self.send(datagram) self.send(datagram)
@ -964,29 +964,29 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
datagram.addUint16(CLIENT_REMOVE_INTEREST) datagram.addUint16(CLIENT_REMOVE_INTEREST)
datagram.addUint16(contextId) datagram.addUint16(contextId)
self.send(datagram) self.send(datagram)
def handleInterestDoneMessage(self, di): def handleInterestDoneMessage(self, di):
""" """
This handles the interest done messages and may dispatch a This handles the interest done messages and may dispatch a
action based on the ID , Context action based on the ID , Context
""" """
id = di.getUint16() id = di.getUint16()
scope = di.getUint32() scope = di.getUint32()
expect_scope = self.GetInterestScopeID(id) expect_scope = self.GetInterestScopeID(id)
print "handleInterestDoneMessage--> Received ID:%s Scope:%s"%(id,scope); print "handleInterestDoneMessage--> Received ID:%s Scope:%s"%(id,scope);
if expect_scope == scope: if expect_scope == scope:
print "handleInterestDoneMessage--> Scope Match:%s Scope:%s"%(id,scope); print "handleInterestDoneMessage--> Scope Match:%s Scope:%s"%(id,scope);
event = self.GetInterestScopeEvent(id) event = self.GetInterestScopeEvent(id)
if event is not None: if event is not None:
print "handleInterestDoneMessage--> Send Event : %s"%(event); print "handleInterestDoneMessage--> Send Event : %s"%(event);
messenger.send(event) messenger.send(event)
else: else:
print "handleInterestDoneMessage--> No Event "; print "handleInterestDoneMessage--> No Event ";
self._PonderRemoveFlaggedInterest(id) self._PonderRemoveFlaggedInterest(id)
else: else:
print "handleInterestDoneMessage--> Scope MisMatch :%s :%s"%(expect_scope,scope); print "handleInterestDoneMessage--> Scope MisMatch :%s :%s"%(expect_scope,scope);
assert self.printInterests() assert self.printInterests()
def sendHeartbeat(self): def sendHeartbeat(self):
datagram = PyDatagram() datagram = PyDatagram()
@ -1004,7 +1004,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
if not self.heartbeatStarted: if not self.heartbeatStarted:
self.notify.debug("Heartbeats not started; not sending.") self.notify.debug("Heartbeats not started; not sending.")
return return
elapsed = globalClock.getRealTime() - self.lastHeartbeat elapsed = globalClock.getRealTime() - self.lastHeartbeat
if elapsed < 0 or elapsed > self.heartbeatInterval: if elapsed < 0 or elapsed > self.heartbeatInterval:
# It's time to send the heartbeat again (or maybe someone # It's time to send the heartbeat again (or maybe someone
@ -1029,7 +1029,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
def waitForNextHeartBeat(self): def waitForNextHeartBeat(self):
taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask, taskMgr.doMethodLater(self.heartbeatInterval, self.sendHeartbeatTask,
"heartBeat") "heartBeat")
def sendUpdate(self, do, fieldName, args, sendToId = None): def sendUpdate(self, do, fieldName, args, sendToId = None):
dg = do.dclass.clientFormatUpdate(fieldName, sendToId or do.doId, args) dg = do.dclass.clientFormatUpdate(fieldName, sendToId or do.doId, args)
@ -1038,7 +1038,7 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
def sendUpdateZone(self, obj, zoneId): def sendUpdateZone(self, obj, zoneId):
# This method is only used in conjunction with the CMU LAN # This method is only used in conjunction with the CMU LAN
# server. # server.
id = obj.doId id = obj.doId
assert(self.isLocalId(id)) assert(self.isLocalId(id))
self.sendDeleteMsg(id, 1) self.sendDeleteMsg(id, 1)

View File

@ -1,14 +1,14 @@
from pandac.PandaModules import * from pandac.PandaModules import *
from direct.task import Task from direct.task import Task
from direct.directnotify import DirectNotifyGlobal from direct.directnotify import DirectNotifyGlobal
from direct.showbase import DirectObject from direct.distributed.DoInterestManager import DoInterestManager
from PyDatagram import PyDatagram from PyDatagram import PyDatagram
from PyDatagramIterator import PyDatagramIterator from PyDatagramIterator import PyDatagramIterator
import types import types
import imp import imp
class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository): class ConnectionRepository(DoInterestManager, CConnectionRepository):
""" """
This is a base class for things that know how to establish a This is a base class for things that know how to establish a
connection (and exchange datagrams) with a gameserver. This connection (and exchange datagrams) with a gameserver. This
@ -18,12 +18,13 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
taskPriority = -30 taskPriority = -30
def __init__(self, config): def __init__(self, config):
DirectObject.DirectObject.__init__(self) assert self.notify.debugCall()
DoInterestManager.__init__(self)
CConnectionRepository.__init__(self) CConnectionRepository.__init__(self)
self.setPythonRepository(self) self.setPythonRepository(self)
self.config = config self.config = config
# Set this to 'http' to establish a connection to the server # Set this to 'http' to establish a connection to the server
# using the HTTPClient interface, which ultimately uses the # using the HTTPClient interface, which ultimately uses the
# OpenSSL socket library (even though SSL is not involved). # OpenSSL socket library (even though SSL is not involved).
@ -66,7 +67,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
self.dclassesByName = {} self.dclassesByName = {}
self.dclassesByNumber = {} self.dclassesByNumber = {}
self.hashVal = 0 self.hashVal = 0
dcImports = {} dcImports = {}
if dcFileNames == None: if dcFileNames == None:
readResult = dcFile.readAll() readResult = dcFile.readAll()
@ -100,7 +101,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
symbolName += self.dcSuffix symbolName += self.dcSuffix
importSymbols.append(symbolName) importSymbols.append(symbolName)
self.importModule(dcImports, moduleName, importSymbols) self.importModule(dcImports, moduleName, importSymbols)
# Now get the class definition for the classes named in the DC # Now get the class definition for the classes named in the DC
@ -120,7 +121,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
if not hasattr(classDef, className): if not hasattr(classDef, className):
self.notify.error("Module %s does not define class %s." % (className, className)) self.notify.error("Module %s does not define class %s." % (className, className))
classDef = getattr(classDef, className) classDef = getattr(classDef, className)
if type(classDef) != types.ClassType: if type(classDef) != types.ClassType:
self.notify.error("Symbol %s is not a class name." % (className)) self.notify.error("Symbol %s is not a class name." % (className))
else: else:
@ -147,7 +148,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
importSymbols = module.__all__ importSymbols = module.__all__
else: else:
importSymbols = module.__dict__.keys() importSymbols = module.__dict__.keys()
for symbolName in importSymbols: for symbolName in importSymbols:
if hasattr(module, symbolName): if hasattr(module, symbolName):
dcImports[symbolName] = getattr(module, symbolName) dcImports[symbolName] = getattr(module, symbolName)
@ -185,7 +186,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
## self.connectHttp = 1 ## self.connectHttp = 1
## self.tcpConn = SocketStreamRecorder() ## self.tcpConn = SocketStreamRecorder()
## self.recorder.addRecorder('gameserver', self.tcpConn) ## self.recorder.addRecorder('gameserver', self.tcpConn)
## self.startReaderPollTask() ## self.startReaderPollTask()
## if successCallback: ## if successCallback:
## successCallback(*successArgs) ## successCallback(*successArgs)
@ -245,7 +246,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
self.notify.info("Closing connection to server.") self.notify.info("Closing connection to server.")
CConnectionRepository.disconnect(self) CConnectionRepository.disconnect(self)
self.stopReaderPollTask() self.stopReaderPollTask()
def httpConnectCallback(self, ch, serverList, serverIndex, def httpConnectCallback(self, ch, serverList, serverIndex,
successCallback, successArgs, successCallback, successArgs,
failureCallback, failureArgs): failureCallback, failureArgs):
@ -268,17 +269,17 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
## # connection to the SocketStreamRecorder object. ## # connection to the SocketStreamRecorder object.
## self.tcpConn.userManagesMemory = 0 ## self.tcpConn.userManagesMemory = 0
## self.tcpConn = stream ## self.tcpConn = stream
self.startReaderPollTask() self.startReaderPollTask()
if successCallback: if successCallback:
successCallback(*successArgs) successCallback(*successArgs)
elif serverIndex < len(serverList): elif serverIndex < len(serverList):
# No connection yet, but keep trying. # No connection yet, but keep trying.
url = serverList[serverIndex] url = serverList[serverIndex]
self.notify.info("Connecting to %s via HTTP interface." % (url.cStr())) self.notify.info("Connecting to %s via HTTP interface." % (url.cStr()))
ch.preserveStatus() ch.preserveStatus()
ch.beginConnectTo(DocumentSpec(url)) ch.beginConnectTo(DocumentSpec(url))
ch.spawnTask(name = 'connect-to-server', ch.spawnTask(name = 'connect-to-server',
callback = self.httpConnectCallback, callback = self.httpConnectCallback,
@ -296,7 +297,7 @@ class ConnectionRepository(DirectObject.DirectObject, CConnectionRepository):
# already. This might fail if the OpenSSL library isn't # already. This might fail if the OpenSSL library isn't
# available. Returns the HTTPClient (also self.http), or None # available. Returns the HTTPClient (also self.http), or None
# if not set. # if not set.
if self.http == None: if self.http == None:
try: try:
self.http = HTTPClient() self.http = HTTPClient()

View File

@ -330,8 +330,8 @@ class DistributedObject(PandaObject):
self.__barrierContext = None self.__barrierContext = None
if wantOtpServer: if wantOtpServer:
def addInterest(self, zoneId, note=""): def addInterest(self, zoneId, note="", event=None):
self.cr.addInterest(self.getDoId(), zoneId, note) self.cr.addInterest(self.getDoId(), zoneId, note, event)
def setLocation(self, parentId, zoneId): def setLocation(self, parentId, zoneId):
# The store must run first so we know the old location # The store must run first so we know the old location

View File

@ -9,25 +9,21 @@ p.s. A great deal of this code is just code moved from ClientRepository.py.
from pandac.PandaModules import * from pandac.PandaModules import *
from MsgTypes import * from MsgTypes import *
from direct.task import Task
from direct.directnotify import DirectNotifyGlobal from direct.directnotify import DirectNotifyGlobal
import CRCache from direct.showbase.PythonUtil import *
import ConnectionRepository from direct.showbase import DirectObject
from direct.showbase import PythonUtil
import ParentMgr
import RelatedObjectMgr
import time
from ClockDelta import *
from PyDatagram import PyDatagram from PyDatagram import PyDatagram
from PyDatagramIterator import PyDatagramIterator #from PyDatagramIterator import PyDatagramIterator
class DoInterestManager(DirectObject.DirectObject): class DoInterestManager(DirectObject.DirectObject):
""" """
Top level Interest Manager Top level Interest Manager
""" """
notify = DirectNotifyGlobal.directNotify.newCategory("DoInterestManager") if __debug__:
notify = DirectNotifyGlobal.directNotify.newCategory("DoInterestManager")
def __init__(self): def __init__(self):
assert self.notify.debugCall()
DirectObject.DirectObject.__init__(self) DirectObject.DirectObject.__init__(self)
self._interestIdAssign = 1 self._interestIdAssign = 1
self._interestIdScopes = 100; self._interestIdScopes = 100;
@ -37,6 +33,7 @@ class DoInterestManager(DirectObject.DirectObject):
""" """
Look into a zone. Look into a zone.
""" """
assert self.notify.debugCall()
self._interestIdAssign += 1 self._interestIdAssign += 1
self._interestIdScopes += 1 self._interestIdScopes += 1
contextId = self._interestIdAssign contextId = self._interestIdAssign
@ -50,6 +47,7 @@ class DoInterestManager(DirectObject.DirectObject):
""" """
Stop looking in a zone Stop looking in a zone
""" """
assert self.notify.debugCall()
answer = 0 answer = 0
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
if event is not None: if event is not None:
@ -73,6 +71,7 @@ class DoInterestManager(DirectObject.DirectObject):
""" """
Removes old interests and adds new interests. Removes old interests and adds new interests.
""" """
assert self.notify.debugCall()
answer = 0 answer = 0
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
self._interestIdScopes += 1 self._interestIdScopes += 1
@ -94,6 +93,7 @@ class DoInterestManager(DirectObject.DirectObject):
Part of the new otp-server code. Part of the new otp-server code.
Return a ScopeId Id for an Interest Return a ScopeId Id for an Interest
""" """
assert self.notify.debugCall()
answer = 0 answer = 0
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
answer = self._interests[contextId][1]; answer = self._interests[contextId][1];
@ -106,6 +106,7 @@ class DoInterestManager(DirectObject.DirectObject):
""" """
returns an event for an interest. returns an event for an interest.
""" """
assert self.notify.debugCall()
answer = None answer = None
if self._interests.has_key(contextId): if self._interests.has_key(contextId):
answer = self._interests[contextId][2]; answer = self._interests[contextId][2];
@ -117,6 +118,7 @@ class DoInterestManager(DirectObject.DirectObject):
""" """
Consider whether we should cull the interest set. Consider whether we should cull the interest set.
""" """
assert self.notify.debugCall()
if self._interests.has_key(handle): if self._interests.has_key(handle):
if self._interests[handle][3] == "PendingDel": if self._interests[handle][3] == "PendingDel":
del self._interests[handle] del self._interests[handle]
@ -146,6 +148,7 @@ class DoInterestManager(DirectObject.DirectObject):
necessarily have any relationship to the same contextId necessarily have any relationship to the same contextId
on another client. on another client.
""" """
assert self.notify.debugCall()
datagram = PyDatagram() datagram = PyDatagram()
# Add message type # Add message type
datagram.addUint16(CLIENT_ADD_INTEREST) datagram.addUint16(CLIENT_ADD_INTEREST)
@ -169,6 +172,7 @@ class DoInterestManager(DirectObject.DirectObject):
necessarily have any relationship to the same contextId necessarily have any relationship to the same contextId
on another client. on another client.
""" """
assert self.notify.debugCall()
datagram = PyDatagram() datagram = PyDatagram()
# Add message type # Add message type
datagram.addUint16(CLIENT_REMOVE_INTEREST) datagram.addUint16(CLIENT_REMOVE_INTEREST)
@ -180,19 +184,20 @@ class DoInterestManager(DirectObject.DirectObject):
This handles the interest done messages and may dispatch a This handles the interest done messages and may dispatch a
action based on the ID, Context action based on the ID, Context
""" """
assert self.notify.debugCall()
id = di.getUint16() id = di.getUint16()
scope = di.getUint32() scope = di.getUint32()
expect_scope = self.GetInterestScopeID(id) expect_scope = self.getInterestScopeId(id)
print "handleInterestDoneMessage--> Received ID:%s Scope:%s"%(id,scope); print "handleInterestDoneMessage--> Received ID:%s Scope:%s"%(id,scope);
if expect_scope == scope: if expect_scope == scope:
print "handleInterestDoneMessage--> Scope Match:%s Scope:%s"%(id,scope); print "handleInterestDoneMessage--> Scope Match:%s Scope:%s"%(id,scope);
event = self.GetInterestScopeEvent(id) event = self.getInterestScopeEvent(id)
if event is not None: if event is not None:
print "handleInterestDoneMessage--> Send Event : %s"%(event); print "handleInterestDoneMessage--> Send Event : %s"%(event);
messenger.send(event) messenger.send(event)
else: else:
print "handleInterestDoneMessage--> No Event "; print "handleInterestDoneMessage--> No Event ";
self._PonderRemoveFlaggedInterest(id) self._ponderRemoveFlaggedInterest(id)
else: else:
print "handleInterestDoneMessage--> Scope MisMatch :%s :%s"%(expect_scope,scope); print "handleInterestDoneMessage--> Scope MisMatch :%s :%s"%(expect_scope,scope);