| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- #hack:
- BAD_DO_ID = BAD_ZONE_ID = 0xFFFFFFFF
- BAD_CHANNEL_ID = 0xFFFFFFFFFFFFFFFF
- class DoCollectionManager:
- def __init__(self):
- # Dict of {DistributedObject ids : DistributedObjects}
- self.doId2do = {}
- # for OTP: (parentId, zoneId) to dict of doId->DistributedObjectAI
- # for NON-OTP: zoneId to dict of doId->DistributedObjectAI
- self.zoneId2doIds={}
- if self.hasOwnerView():
- # Dict of {DistributedObject ids : DistributedObjects} for 'owner' views of objects
- self.doId2ownerView = {}
- if wantOtpServer:
- # Dict of {
- # parent DistributedObject id:
- # { zoneIds : [child DistributedObject ids] }}
- self.__doHierarchy = {}
- def getDo(self, doId):
- return self.doId2do.get(doId)
- def getOwnerView(self, doId):
- assert self.hasOwnerView()
- return self.doId2ownerView.get(doId)
- def getDoTable(self, ownerView):
- if ownerView:
- assert self.hasOwnerView()
- return self.doId2ownerView
- else:
- return self.doId2do
- def doFind(self, str):
- """
- Returns list of distributed objects with matching str in value.
- """
- for value in self.doId2do.values():
- if `value`.find(str) >= 0:
- return value
- def doFindAll(self, str):
- """
- Returns list of distributed objects with matching str in value.
- """
- matches = []
- for value in self.doId2do.values():
- if `value`.find(str) >= 0:
- matches.append(value)
- return matches
- def getDoHierarchy(self):
- return self.__doHierarchy
- if __debug__:
- def printObjects(self):
- format="%10s %10s %10s %30s %20s"
- title=format%("parentId", "zoneId", "doId", "dclass", "name")
- print title
- print '-'*len(title)
- for distObj in self.doId2do.values():
- print format%(
- distObj.__dict__.get("parentId"),
- distObj.__dict__.get("zoneId"),
- distObj.__dict__.get("doId"),
- distObj.dclass.getName(),
- distObj.__dict__.get("name"))
- def getDoList(self, parentId, zoneId=None, classType=None):
- """
- parentId is any distributed object id.
- zoneId is a uint32, defaults to None (all zones). Try zone 2 if
- you're not sure which zone to use (0 is a bad/null zone and
- 1 has had reserved use in the past as a no messages zone, while
- 2 has traditionally been a global, uber, misc stuff zone).
- dclassType is a distributed class type filter, defaults
- to None (no filter).
-
- If dclassName is None then all objects in the zone are returned;
- otherwise the list is filtered to only include objects of that type.
- """
- return [self.doId2do.get(i)
- for i in self.getDoIdList(parentId, zoneId, classType)]
- def getDoIdList(self, parentId, zoneId=None, classType=None):
- """
- parentId is any distributed object id.
- zoneId is a uint32, defaults to None (all zones). Try zone 2 if
- you're not sure which zone to use (0 is a bad/null zone and
- 1 has had reserved use in the past as a no messages zone, while
- 2 has traditionally been a global, uber, misc stuff zone).
- dclassType is a distributed class type filter, defaults
- to None (no filter).
-
- If dclassName is None then all objects in the zone are returned;
- otherwise the list is filtered to only include objects of that type.
- """
- parent=self.__doHierarchy.get(parentId)
- if parent is None:
- return []
- if zoneId is None:
- r = []
- for zone in parent.values():
- for obj in zone:
- r.append(obj)
- else:
- r = parent.get(zoneId, [])
- if classType is not None:
- a = []
- for obj in r:
- if isinstance(obj, classType):
- a.append(obj)
- r = a
- return r
-
- def countObjects(self, classType):
- """
- Counts the number of objects of the given type in the
- repository (for testing purposes)
- """
- count = 0
- for dobj in self.doId2do.values():
- if isinstance(dobj, classType):
- count += 1
- return count
- def getAllOfType(self, type):
- # Returns a list of all DistributedObjects in the repository
- # of a particular type.
- result = []
- for obj in self.doId2do.values():
- if isinstance(obj, type):
- result.append(obj)
- return result
- def findAnyOfType(self, type):
- # Searches the repository for any object of the given type.
- for obj in self.doId2do.values():
- if isinstance(obj, type):
- return obj
- return None
- #----------------------------------
- def deleteDistributedObjects(self):
- # Get rid of all the distributed objects
- for doId in self.doId2do.keys():
- # Look up the object
- do = self.doId2do[doId]
- self.deleteDistObject(do)
- # Get rid of everything that manages distributed objects
- self.deleteObjects()
- # the zoneId2doIds table should be empty now
- if len(self.zoneId2doIds) > 0:
- self.notify.warning(
- 'zoneId2doIds table not empty: %s' % self.zoneId2doIds)
- self.zoneId2doIds = {}
- if wantOtpServer:
- def handleObjectLocation(self, di):
- # CLIENT_OBJECT_LOCATION
- doId = di.getUint32()
- parentId = di.getUint32()
- zoneId = di.getUint32()
- obj = self.doId2do.get(doId)
- if obj is not None:
- self.notify.debug(
- "handleObjectLocation: doId: %s parentId: %s zoneId: %s"%
- (doId, parentId, zoneId))
- # Let the object finish the job
- obj.setLocation(parentId, zoneId)
- self.storeObjectLocation(doId, parentId, zoneId)
- else:
- self.notify.warning(
- "handleObjectLocation: Asked to update non-existent obj: %s" % (doId))
-
- def handleSetLocation(self, di):
- # This was initially added because creating a distributed quest
- # object would cause a message like this to be generated.
- assert self.notify.debugStateCall(self)
- parentId = di.getUint32()
- zoneId = di.getUint32()
- distObj = self.doId2do.get(self.getMsgChannel())
- if distObj is not None:
- distObj.setLocation(parentId, zoneId)
- def storeObjectLocation(self, doId, parentId, zoneId):
- if (parentId is None) or (zoneId is None):
- # Do not store null values
- return
- # TODO: check current location
- obj = self.doId2do.get(doId)
- if obj is not None:
- oldParentId = obj.parentId
- oldZoneId = obj.zoneId
- if oldParentId != parentId:
- # Remove old location
- parentZoneDict = self.__doHierarchy.get(oldParentId)
- if parentZoneDict is not None:
- zoneDoSet = parentZoneDict.get(oldZoneId)
- if zoneDoSet is not None and doId in zoneDoSet:
- zoneDoSet.remove(doId)
- if len(zoneDoSet) == 0:
- del parentZoneDict[oldZoneId]
- # Add to new location
- parentZoneDict = self.__doHierarchy.setdefault(parentId, {})
- zoneDoSet = parentZoneDict.setdefault(zoneId, set())
- zoneDoSet.add(doId)
- 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)
-
- if wantOtpServer:
- def addDOToTables(self, do, location=None, ownerView=False):
- assert self.notify.debugStateCall(self)
- assert not hasattr(do, "isQueryAllResponse") or not do.isQueryAllResponse
- if not ownerView:
- if location is None:
- location = (do.parentId, do.zoneId)
- doTable = self.getDoTable(ownerView)
-
- #assert do.doId not in doTable
- if do.doId in doTable:
- print "ignoring repeated object %s" % (do.doId)
- return
-
- doTable[do.doId]=do
- if not ownerView:
- if self.isValidLocationTuple(location):
- assert do.doId not in self.zoneId2doIds.get(location,{})
- self.zoneId2doIds.setdefault(location, {})
- self.zoneId2doIds[location][do.doId]=do
- def isValidLocationTuple(self, location):
- return (location is not None
- and location != (0xffffffff, 0xffffffff)
- and location != (0, 0))
- else:
- # NON OTP
- def addDOToTables(self, do, zoneId=None):
- assert self.notify.debugStateCall(self)
- if zoneId is None:
- zoneId = do.zoneId
- assert do.doId not in self.doId2do
- self.doId2do[do.doId]=do
- if zoneId is not None:
- assert do.doId not in self.zoneId2doIds.get(zoneId,{})
- self.zoneId2doIds.setdefault(zoneId, {})
- self.zoneId2doIds[zoneId][do.doId]=do
- if wantOtpServer:
- def removeDOFromTables(self, do):
- assert self.notify.debugStateCall(self)
- assert not hasattr(do, "isQueryAllResponse") or not do.isQueryAllResponse
- #assert do.doId in self.doId2do
- location = do.getLocation()
- if location is not None:
- if location not in self.zoneId2doIds:
- self.notify.warning(
- 'dobj %s (%s) has invalid location: %s' %
- (do, do.doId, location))
- else:
- assert do.doId in self.zoneId2doIds[location]
- del self.zoneId2doIds[location][do.doId]
- if len(self.zoneId2doIds[location]) == 0:
- del self.zoneId2doIds[location]
- if do.doId in self.doId2do:
- del self.doId2do[do.doId]
- else:
- def removeDOFromTables(self, do):
- assert self.notify.debugStateCall(self)
- assert do.doId in self.doId2do
- if do.zoneId is not None:
- if do.zoneId not in self.zoneId2doIds:
- self.notify.warning(
- 'dobj %s (%s) has invalid zoneId: %s' %
- (do, do.doId, do.zoneId))
- else:
- assert do.doId in self.zoneId2doIds[do.zoneId]
- del(self.zoneId2doIds[do.zoneId][do.doId])
- if len(self.zoneId2doIds[do.zoneId]) == 0:
- del self.zoneId2doIds[do.zoneId]
- del self.doId2do[do.doId]
-
- if wantOtpServer:
- def changeDOZoneInTables(self, do, newParentId, newZoneId, oldParentId, oldZoneId):
- assert not hasattr(do, "isQueryAllResponse") or not do.isQueryAllResponse
- oldLocation = (oldParentId, oldZoneId)
- newLocation = (newParentId, newZoneId)
- # HACK: DistributedGuildMemberUD starts in -1,-1, which isnt ever put in the
- # zoneId2doIds table
- if self.isValidLocationTuple(oldLocation):
- assert self.notify.debugStateCall(self)
- assert oldLocation in self.zoneId2doIds
- assert do.doId in self.zoneId2doIds[oldLocation]
- assert do.doId not in self.zoneId2doIds.get(newLocation,{})
- # remove from old zone
- del(self.zoneId2doIds[oldLocation][do.doId])
- if len(self.zoneId2doIds[oldLocation]) == 0:
- del self.zoneId2doIds[oldLocation]
- if self.isValidLocationTuple(newLocation):
- # add to new zone
- self.zoneId2doIds.setdefault(newLocation, {})
- self.zoneId2doIds[newLocation][do.doId]=do
- def getObjectsInZone(self, location):
- """ call this to get a dict of doId:distObj for a zone.
- Creates a shallow copy, so you can do whatever you want with the
- dict. """
- assert self.notify.debugStateCall(self)
- return copy.copy(self.zoneId2doIds.get(location, {}))
- def getObjectsOfClassInZone(self, location, objClass):
- """ returns dict of doId:object for a zone, containing all objects
- that inherit from 'class'. returned dict is safely mutable. """
- assert self.notify.debugStateCall(self)
- doDict = {}
- for doId, do in self.zoneId2doIds.get(location, {}).items():
- if isinstance(do, objClass):
- doDict[doId] = do
- return doDict
- else:
- # NON OTP
- def changeDOZoneInTables(self, do, newZoneId, oldZoneId):
- ##print "changeDOZoneInTables:%s, dclass:%s, newZoneId:%s OldZoneId:%s"%(do.doId, do.dclass.getName(), newZoneId,oldZoneId)
- assert self.notify.debugStateCall(self)
- assert oldZoneId in self.zoneId2doIds
- assert do.doId in self.zoneId2doIds[oldZoneId]
- assert do.doId not in self.zoneId2doIds.get(newZoneId,{})
- # remove from old zone
- del(self.zoneId2doIds[oldZoneId][do.doId])
- if len(self.zoneId2doIds[oldZoneId]) == 0:
- del self.zoneId2doIds[oldZoneId]
- # add to new zone
- self.zoneId2doIds.setdefault(newZoneId, {})
- self.zoneId2doIds[newZoneId][do.doId]=do
- def getObjectsInZone(self, zoneId):
- """ call this to get a dict of doId:distObj for a zone.
- Creates a shallow copy, so you can do whatever you want with the
- dict. """
- assert self.notify.debugStateCall(self)
- return copy.copy(self.zoneId2doIds.get(zoneId, {}))
- def getObjectsOfClassInZone(self, zoneId, objClass):
- """ returns dict of doId:object for a zone, containing all objects
- that inherit from 'class'. returned dict is safely mutable. """
- assert self.notify.debugStateCall(self)
- doDict = {}
- for doId, do in self.zoneId2doIds.get(zoneId, {}).items():
- if isinstance(do, objClass):
- doDict[doId] = do
- return doDict
|