Browse Source

set location for quests

Dave Schuyler 20 năm trước cách đây
mục cha
commit
ddef13c674
1 tập tin đã thay đổi với 368 bổ sung357 xóa
  1. 368 357
      direct/src/distributed/DoCollectionManager.py

+ 368 - 357
direct/src/distributed/DoCollectionManager.py

@@ -1,357 +1,368 @@
-#hack:
-BAD_DO_ID = BAD_ZONE_ID = -1
-
-class DoCollectionManager:
-    def __init__(self):
-        # Dict of {DistributedObject ids : DistributedObjects}
-        self.doId2do = {}
-        if wantOtpServer:
-            # Dict of {
-            #   parent DistributedObject id: 
-            #     { zoneIds : [child DistributedObject ids] }}
-            self.__doHierarchy = {}
-
-    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.
-        """
-        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:
-            AIRepository.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.info(
-                    "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 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)
-            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)
-
-            ## if oldParentId == parentId:
-                ## # Case 1: Same parent, new zone
-                ## parentZoneDict = self.__doHierarchy.setdefault(parentId, {})
-                ## # Remove this doId from the old zone list
-                ## zoneDoSet = parentZoneDict.setdefault(oldZoneId, set())
-                ## if doId in zoneDoSet:
-                    ## zoneDoSet.remove(doId)
-                ## # Add it to the new zone list
-                ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
-                ## zoneDoSet[doId] = None
-                ## ## if zoneDoSet is None:
-                    ## ## # No existing objList for this zone, let's make a new one
-                    ## ## parentZoneDict[zoneId] = [doId]
-                ## ## else:
-                    ## ## # Just add this doId to the existing list
-                    ## ## assert(doId not in objList)
-                    ## ## zoneDoSet.append(doId)
-            ## else:
-                ## # Case 2: New parent, valid old parent
-                ## if (oldParentId is not None) and (oldZoneId is not None):
-                    ## # First delete the old location
-                    ## self.deleteObjectLocation(doId, oldParentId, oldZoneId)
-                ## # Case 2: continued, already deleted from old location
-                ## # Case 3: New parent - no old parent
-                ## parentZoneDict = self.__doHierarchy.setdefault(parentId, {})
-                ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
-                ## zoneDoSet[doId] = None
-                ## ## if parentZoneDict is None:
-                    ## ## # This parent is not here, just fill the whole entry in
-                    ## ## self.__doHierarchy[parentId] = {zoneId : {doId: None}}
-                ## ## else:
-                    ## ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
-                    ## ## zoneDoSet[doId] = None
-                    ## ## 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 doId
-                        ## ## parentZoneDict[zoneId] = {doId: None}
-                    ## ## else:
-                        ## ## assert doId not in objList
-                        ## ## # Just add this doId to the existing list
-                        ## ## objList[doId] = None
-
-        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):
-            assert self.notify.debugStateCall(self)
-            if location is None:
-                location = (do.parentId, do.zoneId)
-
-            assert do.doId not in self.doId2do
-            self.doId2do[do.doId]=do
-
-            if location is not None:
-                assert do.doId not in self.zoneId2doIds.get(location,{})
-                self.zoneId2doIds.setdefault(location, {})
-                self.zoneId2doIds[location][do.doId]=do
-    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 do.doId in self.doId2do
-            location = do.getLocation()
-            if location is not None:
-                if location not in self.zoneId2doIds:
-                    AIRepository.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]
-
-            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:
-                    AIRepository.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):
-            oldLocation = (oldParentId, oldZoneId)
-            newLocation = (newParentId, newZoneId)
-            # HACK: DistributedGuildMemberUD starts in -1,-1, which isnt ever put in the
-            # zoneId2doIds table
-            if oldLocation != (BAD_DO_ID, BAD_ZONE_ID):
-                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]
-            # 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
+#hack:
+BAD_DO_ID = BAD_ZONE_ID = -1
+
+class DoCollectionManager:
+    def __init__(self):
+        # Dict of {DistributedObject ids : DistributedObjects}
+        self.doId2do = {}
+        if wantOtpServer:
+            # Dict of {
+            #   parent DistributedObject id: 
+            #     { zoneIds : [child DistributedObject ids] }}
+            self.__doHierarchy = {}
+
+    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.
+        """
+        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:
+            AIRepository.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.info(
+                    "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)
+
+            ## if oldParentId == parentId:
+                ## # Case 1: Same parent, new zone
+                ## parentZoneDict = self.__doHierarchy.setdefault(parentId, {})
+                ## # Remove this doId from the old zone list
+                ## zoneDoSet = parentZoneDict.setdefault(oldZoneId, set())
+                ## if doId in zoneDoSet:
+                    ## zoneDoSet.remove(doId)
+                ## # Add it to the new zone list
+                ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
+                ## zoneDoSet[doId] = None
+                ## ## if zoneDoSet is None:
+                    ## ## # No existing objList for this zone, let's make a new one
+                    ## ## parentZoneDict[zoneId] = [doId]
+                ## ## else:
+                    ## ## # Just add this doId to the existing list
+                    ## ## assert(doId not in objList)
+                    ## ## zoneDoSet.append(doId)
+            ## else:
+                ## # Case 2: New parent, valid old parent
+                ## if (oldParentId is not None) and (oldZoneId is not None):
+                    ## # First delete the old location
+                    ## self.deleteObjectLocation(doId, oldParentId, oldZoneId)
+                ## # Case 2: continued, already deleted from old location
+                ## # Case 3: New parent - no old parent
+                ## parentZoneDict = self.__doHierarchy.setdefault(parentId, {})
+                ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
+                ## zoneDoSet[doId] = None
+                ## ## if parentZoneDict is None:
+                    ## ## # This parent is not here, just fill the whole entry in
+                    ## ## self.__doHierarchy[parentId] = {zoneId : {doId: None}}
+                ## ## else:
+                    ## ## zoneDoSet = parentZoneDict.setdefault(zoneId, {})
+                    ## ## zoneDoSet[doId] = None
+                    ## ## 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 doId
+                        ## ## parentZoneDict[zoneId] = {doId: None}
+                    ## ## else:
+                        ## ## assert doId not in objList
+                        ## ## # Just add this doId to the existing list
+                        ## ## objList[doId] = None
+
+        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):
+            assert self.notify.debugStateCall(self)
+            if location is None:
+                location = (do.parentId, do.zoneId)
+
+            assert do.doId not in self.doId2do
+            self.doId2do[do.doId]=do
+
+            if location is not None:
+                assert do.doId not in self.zoneId2doIds.get(location,{})
+                self.zoneId2doIds.setdefault(location, {})
+                self.zoneId2doIds[location][do.doId]=do
+    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 do.doId in self.doId2do
+            location = do.getLocation()
+            if location is not None:
+                if location not in self.zoneId2doIds:
+                    AIRepository.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]
+
+            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:
+                    AIRepository.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):
+            oldLocation = (oldParentId, oldZoneId)
+            newLocation = (newParentId, newZoneId)
+            # HACK: DistributedGuildMemberUD starts in -1,-1, which isnt ever put in the
+            # zoneId2doIds table
+            if oldLocation != (BAD_DO_ID, BAD_ZONE_ID):
+                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]
+            # 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