| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- from pandac.PandaModules import *
- from direct.directnotify.DirectNotifyGlobal import directNotify
- from direct.task import Task
- from .DistributedNodeAI import DistributedNodeAI
- from .CartesianGridBase import CartesianGridBase
- class DistributedCartesianGridAI(DistributedNodeAI, CartesianGridBase):
- notify = directNotify.newCategory("DistributedCartesianGridAI")
- RuleSeparator = ":"
- def __init__(self, air, startingZone, gridSize, gridRadius, cellWidth,
- style="Cartesian"):
- DistributedNodeAI.__init__(self, air)
- self.style = style
- self.startingZone = startingZone
- self.gridSize = gridSize
- self.gridRadius = gridRadius
- self.cellWidth = cellWidth
- # Keep track of all AI objects added to the grid
- self.gridObjects = {}
- self.updateTaskStarted = 0
- def delete(self):
- DistributedNodeAI.delete(self)
- self.stopUpdateGridTask()
- def isGridParent(self):
- # If this distributed object is a DistributedGrid return 1.
- # 0 by default
- return 1
- def getCellWidth(self):
- return self.cellWidth
- def getParentingRules(self):
- self.notify.debug("calling getter")
- rule = ("%i%s%i%s%i" % (self.startingZone, self.RuleSeparator,
- self.gridSize, self.RuleSeparator,
- self.gridRadius))
- return [self.style, rule]
- # Reparent and setLocation on av to DistributedOceanGrid
- def addObjectToGrid(self, av, useZoneId=-1, startAutoUpdate=True):
- self.notify.debug("setting parent to grid %s" % self)
- avId = av.doId
- # Create a grid parent
- #gridParent = self.attachNewNode("gridParent-%s" % avId)
- #self.gridParents[avId] = gridParent
- self.gridObjects[avId] = av
- # Put the avatar on the grid
- self.handleAvatarZoneChange(av, useZoneId)
- if (not self.updateTaskStarted) and startAutoUpdate:
- self.startUpdateGridTask()
- def removeObjectFromGrid(self, av):
- # TODO: WHAT LOCATION SHOULD WE SET THIS TO?
- #av.wrtReparentTo(self.parentNP)
- #av.setLocation(self.air.districtId, 1000)
- # Remove grid parent for this av
- avId = av.doId
- if avId in self.gridObjects:
- del self.gridObjects[avId]
- # Stop task if there are no more av's being managed
- if len(self.gridObjects) == 0:
- self.stopUpdateGridTask()
- #####################################################################
- # updateGridTask
- # This task is similar to the processVisibility task for the local client.
- # A couple differences:
- # - we are not doing setInterest on the AI (that is a local client
- # specific call).
- # - we assume that the moving objects on the grid are parented to a
- # gridParent, and are broadcasting their position relative to that
- # gridParent. This makes the task's math easy. Just check to see
- # when our position goes out of the current grid cell. When it does,
- # call handleAvatarZoneChange
- def startUpdateGridTask(self):
- self.stopUpdateGridTask()
- self.updateTaskStarted = 1
- taskMgr.add(self.updateGridTask, self.taskName("updateGridTask"))
- def stopUpdateGridTask(self):
- taskMgr.remove(self.taskName("updateGridTask"))
- self.updateTaskStarted = 0
- def updateGridTask(self, task=None):
- # Run through all grid objects and update their parents if needed
- missingObjs = []
- for avId in self.gridObjects.keys():
- av = self.gridObjects[avId]
- # handle a missing object after it is already gone?
- if (av.isEmpty()):
- task.setDelay(1.0)
- del self.gridObjects[avId]
- continue
- pos = av.getPos()
- if ((pos[0] < 0 or pos[1] < 0) or
- (pos[0] > self.cellWidth or pos[1] > self.cellWidth)):
- # we are out of the bounds of this current cell
- self.handleAvatarZoneChange(av)
- # Do this every second, not every frame
- if (task):
- task.setDelay(1.0)
- return Task.again
- def handleAvatarZoneChange(self, av, useZoneId=-1):
- # Calculate zone id
- # Get position of av relative to this grid
- if (useZoneId == -1):
- pos = av.getPos(self)
- zoneId = self.getZoneFromXYZ(pos)
- else:
- # zone already calculated, position of object might not
- # give the correct zone
- pos = None
- zoneId = useZoneId
- if not self.isValidZone(zoneId):
- self.notify.warning(
- "%s handleAvatarZoneChange %s: not a valid zone (%s) for pos %s" %(self.doId, av.doId, zoneId, pos))
- return
- # Set the location on the server.
- # setLocation will update the gridParent
- av.b_setLocation(self.doId, zoneId)
- def handleSetLocation(self, av, parentId, zoneId):
- pass
- #if (av.parentId != parentId):
- # parent changed, need to look up instance tree
- # to see if avatar's named area location information
- # changed
- #av.requestRegionUpdateTask(regionegionUid)
|