NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

behaviortreemonitor.py (6564B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\debugging\behaviortreemonitor.py
      2 from behaviors import behaviortree
      3 import logging
      4 from behaviors.blackboards import scopes, BlackboardDeletedError
      5 from behaviors.composites import Composite
      6 from behaviors.debugging.tools import DepthFirstTaskIterator
      7 from cluster import SERVICE_BEYONCE
      8 import gametime
      9 logger = logging.getLogger(__name__)
     10 
     11 class BehaviorTreeMonitor(object):
     12     __machoresolve__ = None
     13 
     14     def __init__(self, serviceManager, clientID, itemID):
     15         self.serviceManager = serviceManager
     16         self.clientID = clientID
     17         self.itemID = itemID
     18         self.behaviorTree = None
     19         self.events = []
     20         self.machoNet = serviceManager.GetService('machoNet')
     21         self.taskSeen = []
     22 
     23     def SendToClient(self, *args, **kwargs):
     24         self.machoNet.SinglecastByClientID(self.clientID, 'OnBehaviorDebugUpdate', self.itemID, *args, **kwargs)
     25 
     26     def AttachToBehaviorTree(self, behaviorTree):
     27         self.behaviorTree = behaviorTree
     28         messenger = self.behaviorTree.GetMessenger()
     29         messenger.SubscribeToMessage(behaviortree.MESSAGE_STEP, self.OnTreeStep)
     30         messenger.SubscribeToMessage(behaviortree.MESSAGE_RESET, self.OnTreeReset)
     31         messenger.SubscribeToMessage(behaviortree.MESSAGE_REQUEST_RESET, self.OnTreeResetRequest)
     32         messenger.SubscribeToMessage(behaviortree.MESSAGE_TICK_DONE, self.OnTickDone)
     33         messenger.SubscribeToMessage(behaviortree.MESSAGE_BLOCK_RESET, self.OnTreeSetBlockReset)
     34         self.serviceManager.RegisterForNotifyEvent(self, 'OnSessionDetach')
     35         self.serviceManager.RegisterForNotifyEvent(self, 'OnSessionChanged')
     36 
     37     def DetachFromBehaviorTree(self):
     38         if self.behaviorTree is None:
     39             return
     40         try:
     41             messenger = self.behaviorTree.GetMessenger()
     42             messenger.UnsubscribeFromMessage(behaviortree.MESSAGE_STEP, self.OnTreeStep)
     43             messenger.UnsubscribeFromMessage(behaviortree.MESSAGE_RESET, self.OnTreeReset)
     44             messenger.UnsubscribeFromMessage(behaviortree.MESSAGE_REQUEST_RESET, self.OnTreeResetRequest)
     45             messenger.UnsubscribeFromMessage(behaviortree.MESSAGE_TICK_DONE, self.OnTickDone)
     46             messenger.UnsubscribeFromMessage(behaviortree.MESSAGE_BLOCK_RESET, self.OnTreeSetBlockReset)
     47             self.serviceManager.UnregisterForNotifyEvent(self, 'OnSessionDetach')
     48             self.serviceManager.UnregisterForNotifyEvent(self, 'OnSessionChanged')
     49         except:
     50             logger.exception('Problem detaching debugger from the behavior for entity')
     51         finally:
     52             self.behaviorTree = None
     53 
     54     def OnSessionDetach(self):
     55         logger.warn('OnSessionDetach %s', session)
     56         if getattr(session, 'clientID', None) == self.clientID:
     57             self.DetachFromBehaviorTree()
     58 
     59     def OnSessionChanged(self, isRemote, sess, change):
     60         logger.warn('OnSessionChanged %s %s %s', isRemote, sess, change)
     61         if getattr(sess, 'clientID', None) == self.clientID and 'solarsystemid' in change:
     62             self.DetachFromBehaviorTree()
     63 
     64     def OnTreeReset(self):
     65         logger.debug('OnTreeReset')
     66         self.events.append((self.GetSimTime(), 'Reset', None))
     67 
     68     def OnTreeResetRequest(self, requestedBy):
     69         logger.debug('OnTreeResetRequest requestedBy=%s', requestedBy)
     70         self.events.append((self.GetSimTime(), 'RequestReset', id(requestedBy)))
     71 
     72     def OnTreeSetBlockReset(self, value, task):
     73         logger.debug('OnTreeSetBlockReset task=%s is %sblocking', task, '' if value else 'un-')
     74         self.events.append((self.GetSimTime(), 'SetBlockReset', (id(task), value)))
     75 
     76     def OnTreeStep(self, task):
     77         if task is not None:
     78             self.taskSeen.append(task)
     79         self.events.append((self.GetSimTime(), 'Step', id(task)))
     80 
     81     def OnTickDone(self, context):
     82         if self.behaviorTree is None:
     83             return
     84         events = self.events
     85         self.events = []
     86         taskStatuses = {id(t):t.status.__name__ for t in DepthFirstTaskIterator(self.behaviorTree.GetRootTask())}
     87         tasksSeen = [ id(t) for t in self.taskSeen ]
     88         del self.taskSeen[:]
     89         blackboards = GetBlackboards(context)
     90         self.SendToClient(events, taskStatuses, tasksSeen, blackboards)
     91 
     92     def GetTreeDump(self):
     93         return DumpTree(self.behaviorTree)
     94 
     95     def GetSimTime(self):
     96         return gametime.GetSimTime()
     97 
     98     def MachoResolve(self, session):
     99         result = None
    100         solarsystemid2 = session.GetSessionVariable('solarsystemid2')
    101         if solarsystemid2:
    102             result = self.machoNet.GetNodeFromAddress(SERVICE_BEYONCE, session.solarsystemid2)
    103         return result
    104 
    105 
    106 def DumpTree(behaviorTree):
    107     taskList = []
    108     rootTask = behaviorTree.GetRootTask()
    109     RecursiveDumpTask(taskList, rootTask, 0)
    110     return taskList
    111 
    112 
    113 def RecursiveDumpTask(taskList, task, depth):
    114     taskDict = DumpTask(task, depth)
    115     taskList.append(taskDict)
    116     if issubclass(task.__class__, Composite):
    117         subTasks = []
    118         for subTask in task.GetSubTasks():
    119             subTasks.append(id(subTask))
    120             RecursiveDumpTask(taskList, subTask, depth + 1)
    121 
    122         taskDict['subtasks'] = subTasks
    123 
    124 
    125 def DumpTask(task, depth):
    126     return dict(type=task.__class__.__name__, id=id(task), attributes=get_attribute_dict(task), status=task.status.__name__, depth=depth)
    127 
    128 
    129 def get_attribute_dict(task):
    130     if isinstance(task.attributes, dict):
    131         if task.attributes:
    132             return dict(task.attributes)
    133         return {}
    134     else:
    135         return dict(task.attributes._asdict())
    136 
    137 
    138 def GetBlackboards(context):
    139     bbm = context.blackboardManager
    140     blackboards = {}
    141     for scopeType in scopes.ScopeTypes.values():
    142         if scopeType not in scopes.CONTEXT_ID_BY_SCOPE:
    143             continue
    144         scopeID = context.get(scopes.CONTEXT_ID_BY_SCOPE[scopeType])
    145         if scopeID is not None:
    146             scope = scopes.Scope(scopeType, scopeID)
    147             try:
    148                 bb = bbm.GetBlackboard(scope)
    149             except BlackboardDeletedError:
    150                 continue
    151 
    152             channels = []
    153             for channel in bb.GetMessageChannelList():
    154                 message = channel.GetLastMessage()
    155                 if message is None:
    156                     channels.append((channel.name, None, None))
    157                 else:
    158                     channels.append((channel.name, message.time, message.value))
    159 
    160             blackboards[scope.scopeType, scope.id] = channels
    161 
    162     return blackboards