Source code for direct.distributed.DistributedCartesianGridAI


from panda3d.core import *
from panda3d.direct import *
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.task import Task
from direct.task.TaskManagerGlobal import taskMgr
from .DistributedNodeAI import DistributedNodeAI
from .CartesianGridBase import CartesianGridBase

[docs]class DistributedCartesianGridAI(DistributedNodeAI, CartesianGridBase): notify = directNotify.newCategory("DistributedCartesianGridAI") RuleSeparator = ":"
[docs] 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
[docs] def delete(self): DistributedNodeAI.delete(self) self.stopUpdateGridTask()
[docs] def isGridParent(self): # If this distributed object is a DistributedGrid return 1. # 0 by default return 1
[docs] def getCellWidth(self): return self.cellWidth
[docs] 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
[docs] 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 startAutoUpdate and not self.updateTaskStarted: self.startUpdateGridTask()
[docs] 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
[docs] def startUpdateGridTask(self): self.stopUpdateGridTask() self.updateTaskStarted = 1 taskMgr.add(self.updateGridTask, self.taskName("updateGridTask"))
[docs] def stopUpdateGridTask(self): taskMgr.remove(self.taskName("updateGridTask")) self.updateTaskStarted = 0
[docs] def updateGridTask(self, task=None): # Run through all grid objects and update their parents if needed missingObjs = [] for avId in list(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
[docs] 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)
[docs] 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)