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

tasks.py (7026B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\behaviors\tasks.py
      2 import weakref
      3 from collections import defaultdict
      4 from behaviors import status
      5 from behaviors.blackboards import scopes, BlackboardDeletedError
      6 from behaviors.blackboards.scopes import ItemScope
      7 from brennivin.itertoolsext import Bundle
      8 from ccpProfile import TimedFunction
      9 import weakness
     10 import logging
     11 logger = logging.getLogger(__name__)
     12 
     13 class TaskAttributeMissingError(Exception):
     14     pass
     15 
     16 
     17 class Task(object):
     18     __attributes__ = {}
     19 
     20     def __init__(self, attributes = None):
     21         self.SetAttributes(attributes or Bundle())
     22         self.status = None
     23         self.SetStatusToInvalid()
     24         self.exitObserver = None
     25         self.context = None
     26         self.behaviorTree = None
     27 
     28     def OnEnter(self):
     29         self.SetStatusToRunning()
     30 
     31     def OnExit(self):
     32         pass
     33 
     34     def Update(self):
     35         pass
     36 
     37     def CleanUp(self):
     38         self.SetStatusToInvalid()
     39 
     40     def Tick(self, behaviorTree, context):
     41         if self.status is status.TaskInvalidStatus:
     42             self.SetEnvironment(behaviorTree, context)
     43             self.OnEnter()
     44         self.Update()
     45         self.OnStatusUpdate()
     46 
     47     def NotifyExited(self):
     48         if self.exitObserver:
     49             self.exitObserver(self)
     50 
     51     def SetExitObserver(self, exitObserver):
     52         self.exitObserver = weakness.callable_proxy(exitObserver)
     53 
     54     def Exit(self):
     55         self.NotifyExited()
     56         self.OnExit()
     57 
     58     def SetAttributes(self, attributes):
     59         self.attributes = attributes
     60 
     61     def HasSubTasks(self):
     62         return False
     63 
     64     def SetEnvironment(self, behaviorTree, context):
     65         self.behaviorTree = weakref.proxy(behaviorTree)
     66         self.context = weakref.proxy(context)
     67 
     68     def GetChannelFromAddress(self, address):
     69         channel_cache = self.context.task_channel_cache[self]
     70         if address in channel_cache:
     71             return channel_cache[address]
     72         else:
     73             channel = scopes.GetChannelFromAddress(self.context, address)
     74             channel_cache[address] = channel
     75             return channel
     76 
     77     @TimedFunction('behaviors::tasks::Task::GetLastBlackboardValue')
     78     def GetLastBlackboardValue(self, address):
     79         return self.GetChannelFromAddress(address).GetLastMessageValue()
     80 
     81     def GetLastBlackboardValueWithMaxAge(self, address, maxAge):
     82         return self.GetChannelFromAddress(address).GetLastMessageValueWithMaxAge(maxAge)
     83 
     84     @TimedFunction('behaviors::tasks::Task::SendBlackboardValue')
     85     def SendBlackboardValue(self, address, value):
     86         return self.GetChannelFromAddress(address).SendMessage(value)
     87 
     88     def SubscribeToBlackboard(self, address, handler):
     89         self.GetChannelFromAddress(address).AddObserver(handler)
     90 
     91     def UnsubscribeToBlackboard(self, address, handler):
     92         try:
     93             self.GetChannelFromAddress(address).RemoveObserver(handler)
     94         except BlackboardDeletedError:
     95             pass
     96 
     97     def GetEventMessenger(self):
     98         return self.context.ballpark.eventMessenger
     99 
    100     def SubscribeItem(self, itemID, messageId, handler):
    101         self.GetEventMessenger().SubscribeItem(itemID, messageId, handler)
    102 
    103     def UnsubscribeItem(self, itemID, messageId, handler):
    104         try:
    105             self.GetEventMessenger().UnsubscribeItem(itemID, messageId, handler)
    106         except ReferenceError:
    107             logger.debug('Unable to unsubscribe from message as behavior is probably dead and context reference is lost. (itemID=%s, messageId=%, handler=%s)', itemID, messageId, handler)
    108 
    109     def SetStatusToInvalid(self):
    110         self.status = status.TaskInvalidStatus
    111 
    112     def SetStatusToSuccess(self):
    113         self.status = status.TaskSuccessStatus
    114 
    115     def SetStatusToFailed(self):
    116         self.status = status.TaskFailureStatus
    117 
    118     def SetStatusToSuspended(self):
    119         self.status = status.TaskSuspendedStatus
    120 
    121     def SetStatusToRunning(self):
    122         self.status = status.TaskRunningStatus
    123 
    124     def SetStatusToBlocked(self):
    125         self.status = status.TaskBlockingStatus
    126 
    127     def IsInvalid(self):
    128         return self.status is status.TaskInvalidStatus
    129 
    130     def IsSuspended(self):
    131         return self.status == status.TaskSuspendedStatus
    132 
    133     def IsRunning(self):
    134         return self.status == status.TaskRunningStatus
    135 
    136     def IsSuccessful(self):
    137         return self.status == status.TaskSuccessStatus
    138 
    139     def IsFailed(self):
    140         return self.status == status.TaskFailureStatus
    141 
    142     def IsBlocked(self):
    143         return self.status == status.TaskBlockingStatus
    144 
    145     def SetStatusToSuccessIfTrueElseToFailed(self, value):
    146         if value:
    147             self.SetStatusToSuccess()
    148         else:
    149             self.SetStatusToFailed()
    150 
    151     def GetMessageChannelForItemId(self, itemId, channelAddress):
    152         scope = ItemScope(itemId)
    153         return self.context.blackboardManager.GetBlackboard(scope).GetMessageChannel(channelAddress)
    154 
    155     def GetMessageChannelForGroupId(self, groupId, channelAddress):
    156         scope = scopes.EntityGroupScope(groupId)
    157         return self.context.blackboardManager.GetBlackboard(scope).GetMessageChannel(channelAddress)
    158 
    159     def HasAttribute(self, attributeName):
    160         return hasattr(self.attributes, attributeName) and getattr(self.attributes, attributeName) is not None
    161 
    162     def GetTaskName(self):
    163         return type(self).__name__
    164 
    165     def GetContextValue(self, valueName):
    166         return self.context.task_cache[self].get(valueName)
    167 
    168     def SetContextValue(self, valueName, value):
    169         self.context.task_cache[self][valueName] = value
    170 
    171     def HasContextValue(self, valueName):
    172         return valueName in self.context.task_cache[self]
    173 
    174     def ResetBlackboardAddressCache(self):
    175         self.context.task_channel_cache = defaultdict(dict)
    176 
    177     def OnStatusUpdate(self):
    178         self.status.OnUpdated(self)
    179 
    180 
    181 class BlockingTask(Task):
    182 
    183     def OnEnter(self):
    184         self.SetStatusToBlocked()
    185         self.behaviorTree.BlockReset(self)
    186 
    187     def OnExit(self):
    188         self.behaviorTree.UnblockReset(self)
    189 
    190 
    191 class MonitorTask(Task):
    192 
    193     @TimedFunction('behaviors::tasks::MonitorTask::OnEnter')
    194     def OnEnter(self):
    195         item_id = self._get_item_id()
    196         if item_id is None:
    197             self.SetStatusToFailed()
    198             return
    199         self.SubscribeItem(self._get_item_id(), self._get_message(), self._self_process_message)
    200         self.SetStatusToSuccess()
    201 
    202     def _get_item_id(self):
    203         return self.context.myItemId
    204 
    205     def _get_message(self):
    206         raise NotImplementedError
    207 
    208     @TimedFunction('behaviors::tasks::MonitorTask::_self_process_message')
    209     def _self_process_message(self, *args):
    210         if self._can_process_message(*args):
    211             self.behaviorTree.RequestReset(requestedBy=self)
    212 
    213     def _can_process_message(self, *args):
    214         return True
    215 
    216     def CleanUp(self):
    217         if not self.IsInvalid():
    218             self.UnsubscribeItem(self._get_item_id(), self._get_message(), self._self_process_message)
    219             self.SetStatusToInvalid()