DistributedCartesianGridAI.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. from pandac.PandaModules import *
  2. from direct.directnotify.DirectNotifyGlobal import directNotify
  3. from direct.task import Task
  4. from .DistributedNodeAI import DistributedNodeAI
  5. from .CartesianGridBase import CartesianGridBase
  6. class DistributedCartesianGridAI(DistributedNodeAI, CartesianGridBase):
  7. notify = directNotify.newCategory("DistributedCartesianGridAI")
  8. RuleSeparator = ":"
  9. def __init__(self, air, startingZone, gridSize, gridRadius, cellWidth,
  10. style="Cartesian"):
  11. DistributedNodeAI.__init__(self, air)
  12. self.style = style
  13. self.startingZone = startingZone
  14. self.gridSize = gridSize
  15. self.gridRadius = gridRadius
  16. self.cellWidth = cellWidth
  17. # Keep track of all AI objects added to the grid
  18. self.gridObjects = {}
  19. self.updateTaskStarted = 0
  20. def delete(self):
  21. DistributedNodeAI.delete(self)
  22. self.stopUpdateGridTask()
  23. def isGridParent(self):
  24. # If this distributed object is a DistributedGrid return 1.
  25. # 0 by default
  26. return 1
  27. def getCellWidth(self):
  28. return self.cellWidth
  29. def getParentingRules(self):
  30. self.notify.debug("calling getter")
  31. rule = ("%i%s%i%s%i" % (self.startingZone, self.RuleSeparator,
  32. self.gridSize, self.RuleSeparator,
  33. self.gridRadius))
  34. return [self.style, rule]
  35. # Reparent and setLocation on av to DistributedOceanGrid
  36. def addObjectToGrid(self, av, useZoneId=-1, startAutoUpdate=True):
  37. self.notify.debug("setting parent to grid %s" % self)
  38. avId = av.doId
  39. # Create a grid parent
  40. #gridParent = self.attachNewNode("gridParent-%s" % avId)
  41. #self.gridParents[avId] = gridParent
  42. self.gridObjects[avId] = av
  43. # Put the avatar on the grid
  44. self.handleAvatarZoneChange(av, useZoneId)
  45. if (not self.updateTaskStarted) and startAutoUpdate:
  46. self.startUpdateGridTask()
  47. def removeObjectFromGrid(self, av):
  48. # TODO: WHAT LOCATION SHOULD WE SET THIS TO?
  49. #av.wrtReparentTo(self.parentNP)
  50. #av.setLocation(self.air.districtId, 1000)
  51. # Remove grid parent for this av
  52. avId = av.doId
  53. if avId in self.gridObjects:
  54. del self.gridObjects[avId]
  55. # Stop task if there are no more av's being managed
  56. if len(self.gridObjects) == 0:
  57. self.stopUpdateGridTask()
  58. #####################################################################
  59. # updateGridTask
  60. # This task is similar to the processVisibility task for the local client.
  61. # A couple differences:
  62. # - we are not doing setInterest on the AI (that is a local client
  63. # specific call).
  64. # - we assume that the moving objects on the grid are parented to a
  65. # gridParent, and are broadcasting their position relative to that
  66. # gridParent. This makes the task's math easy. Just check to see
  67. # when our position goes out of the current grid cell. When it does,
  68. # call handleAvatarZoneChange
  69. def startUpdateGridTask(self):
  70. self.stopUpdateGridTask()
  71. self.updateTaskStarted = 1
  72. taskMgr.add(self.updateGridTask, self.taskName("updateGridTask"))
  73. def stopUpdateGridTask(self):
  74. taskMgr.remove(self.taskName("updateGridTask"))
  75. self.updateTaskStarted = 0
  76. def updateGridTask(self, task=None):
  77. # Run through all grid objects and update their parents if needed
  78. missingObjs = []
  79. for avId in self.gridObjects.keys():
  80. av = self.gridObjects[avId]
  81. # handle a missing object after it is already gone?
  82. if (av.isEmpty()):
  83. task.setDelay(1.0)
  84. del self.gridObjects[avId]
  85. continue
  86. pos = av.getPos()
  87. if ((pos[0] < 0 or pos[1] < 0) or
  88. (pos[0] > self.cellWidth or pos[1] > self.cellWidth)):
  89. # we are out of the bounds of this current cell
  90. self.handleAvatarZoneChange(av)
  91. # Do this every second, not every frame
  92. if (task):
  93. task.setDelay(1.0)
  94. return Task.again
  95. def handleAvatarZoneChange(self, av, useZoneId=-1):
  96. # Calculate zone id
  97. # Get position of av relative to this grid
  98. if (useZoneId == -1):
  99. pos = av.getPos(self)
  100. zoneId = self.getZoneFromXYZ(pos)
  101. else:
  102. # zone already calculated, position of object might not
  103. # give the correct zone
  104. pos = None
  105. zoneId = useZoneId
  106. if not self.isValidZone(zoneId):
  107. self.notify.warning(
  108. "%s handleAvatarZoneChange %s: not a valid zone (%s) for pos %s" %(self.doId, av.doId, zoneId, pos))
  109. return
  110. # Set the location on the server.
  111. # setLocation will update the gridParent
  112. av.b_setLocation(self.doId, zoneId)
  113. def handleSetLocation(self, av, parentId, zoneId):
  114. pass
  115. #if (av.parentId != parentId):
  116. # parent changed, need to look up instance tree
  117. # to see if avatar's named area location information
  118. # changed
  119. #av.requestRegionUpdateTask(regionegionUid)