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

structureProximityTracker.py (8434B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\services\structure\structureProximityTracker.py
      2 import telemetry
      3 from caching.memoize import Memoize
      4 from carbon.common.script.sys.service import Service
      5 from carbon.common.script.util.timerstuff import AutoTimer
      6 from collections import defaultdict
      7 from eve.common.lib import appConst as const
      8 from eve.client.script.ui.services.structure.error import InvalidStateOfRegistry
      9 from eve.common.script.sys.idCheckers import IsStation
     10 from evetypes import IsStructureAlwaysGlobal
     11 from contextlib import contextmanager
     12 UPDATE_STRUCTURE_VISIBILITY_TIMEOUT = 2000
     13 
     14 class StructureProximityTracker(Service):
     15     __guid__ = 'svc.structureProximityTracker'
     16     __notifyevents__ = ['OnBallAdded',
     17      'DoBallRemove',
     18      'DoBallsRemove',
     19      'OnSessionChanged',
     20      'OnStructuresReloaded',
     21      'OnDockingAccessChangedForCurrentSolarSystem_Local']
     22     __dependencies__ = ['michelle', 'structureDirectory']
     23 
     24     def Run(self, *args):
     25         self.structureVisibilityRegistry = defaultdict(bool)
     26         self.dockableStructuresInSystem = defaultdict(bool)
     27         self.dockableStructuresInSystemHaveChanged = False
     28         self._TriggerStructureVisibilityUpdates()
     29 
     30     def IsStructureDockable(self, structureID):
     31         if self.dockableStructuresInSystemHaveChanged:
     32             self.RefreshDockability_Memoized()
     33         return self.dockableStructuresInSystem[structureID]
     34 
     35     def IsStructureInRange(self, structureID):
     36         return self.michelle.IsBallVisible(structureID)
     37 
     38     def IsStructureVisible(self, structureID):
     39         item = self.michelle.GetItem(structureID)
     40         if item and IsStructureAlwaysGlobal(item.typeID):
     41             return True
     42         return self.IsStructureDockable(structureID) or self.IsStructureInRange(structureID)
     43 
     44     def _SetStructureVisibility(self, structureID, isVisible):
     45         self.structureVisibilityRegistry[structureID] = isVisible
     46         sm.ScatterEvent('OnStructureVisibilityUpdated', structureID)
     47 
     48     def _ClearVisibilityRegistry(self):
     49         for structureID in self.structureVisibilityRegistry:
     50             self._SetStructureVisibility(structureID, False)
     51 
     52         self.structureVisibilityRegistry.clear()
     53         sm.ScatterEvent('OnStructuresVisibilityUpdated')
     54 
     55     def _ResetVisibility(self):
     56         for structureID in self.structureVisibilityRegistry:
     57             self._SetStructureVisibility(structureID, False)
     58 
     59         sm.ScatterEvent('OnStructuresVisibilityUpdated')
     60 
     61     @Memoize(3)
     62     def RefreshDockability_Memoized(self):
     63         self._RefreshDockability()
     64 
     65     @telemetry.ZONE_METHOD
     66     def _RefreshDockability(self):
     67         oldDockableStrucutures = {structureID for structureID, dockable in self.dockableStructuresInSystem.iteritems() if dockable == True}
     68         self.dockableStructuresInSystem.clear()
     69         hasVisibilityChangedForAnyStructure = False
     70         wereDockableStructuresOutdated = self.dockableStructuresInSystemHaveChanged
     71         self.dockableStructuresInSystemHaveChanged = False
     72         newDockableStructures = self._GetDockableStructures()
     73         for structureID in self.structureVisibilityRegistry:
     74             isStructureInRange = self.IsStructureInRange(structureID)
     75             wasStructureDockable = structureID in oldDockableStrucutures
     76             isStructureDockable = structureID in newDockableStructures
     77             self.dockableStructuresInSystem[structureID] = isStructureDockable
     78             hasVisibilityChanged = not isStructureInRange and wasStructureDockable != isStructureDockable
     79             if hasVisibilityChanged:
     80                 hasVisibilityChangedForAnyStructure = True
     81                 self._SetStructureVisibility(structureID, isStructureDockable)
     82 
     83         for structureID in newDockableStructures:
     84             self.dockableStructuresInSystem[structureID] = True
     85 
     86         if hasVisibilityChangedForAnyStructure:
     87             sm.ScatterEvent('OnStructuresVisibilityUpdated')
     88         if wereDockableStructuresOutdated:
     89             sm.ScatterEvent('OnStructureAccessUpdated')
     90 
     91     @telemetry.ZONE_METHOD
     92     def _GetDockableStructures(self):
     93         dockableStructures = []
     94         allDockableStructuresInSolarSystem = self.structureDirectory.GetStructuresInCurrentSystem()
     95         for structureID in allDockableStructuresInSolarSystem:
     96             shouldTrackStructure = not IsStation(structureID)
     97             if shouldTrackStructure:
     98                 dockableStructures.append(structureID)
     99 
    100         return dockableStructures
    101 
    102     def _TriggerStructureVisibilityUpdates(self):
    103         setattr(self, 'updateStructureVisibilityTimerThread', AutoTimer(UPDATE_STRUCTURE_VISIBILITY_TIMEOUT, self._UpdateStructureVisibility))
    104 
    105     @telemetry.ZONE_METHOD
    106     def _UpdateStructureVisibility(self):
    107         hasVisibilityChangedForAnyStructure = False
    108         for structureID, wasVisible in self.structureVisibilityRegistry.iteritems():
    109             isVisible = self.IsStructureVisible(structureID)
    110             if wasVisible != isVisible:
    111                 hasVisibilityChangedForAnyStructure = True
    112                 self._SetStructureVisibility(structureID, isVisible)
    113 
    114         if hasVisibilityChangedForAnyStructure:
    115             sm.ScatterEvent('OnStructuresVisibilityUpdated')
    116 
    117     @contextmanager
    118     def CallFunctionWithStructureVisibilityUpdatesPaused(self):
    119         self.updateStructureVisibilityTimerThread = None
    120         try:
    121             yield
    122             self._TriggerStructureVisibilityUpdates()
    123         except InvalidStateOfRegistry:
    124             pass
    125 
    126     def OnSessionChanged(self, isRemote, session, change):
    127         hasSolarSystemChanged = 'solarsystemid' in change
    128         hasStructureIdChanged = 'structureid' in change
    129         if hasSolarSystemChanged:
    130             self.RefreshDockability_Memoized.clear_memoized()
    131             with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    132                 self._ClearVisibilityRegistry()
    133         elif hasStructureIdChanged:
    134             with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    135                 self._ResetVisibility()
    136 
    137     def OnStructuresReloaded(self):
    138         with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    139             self._RefreshDockability()
    140 
    141     def OnBallAdded(self, slimItem):
    142         if slimItem.categoryID == const.categoryStructure:
    143             structureToAdd = slimItem.itemID
    144             with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    145                 self._AddStructureToRegistry(structureToAdd)
    146 
    147     def DoBallRemove(self, ball, slimItem, terminal):
    148         if slimItem.categoryID == const.categoryStructure:
    149             structureToRemove = slimItem.itemID
    150             with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    151                 self._RemoveStructureFromRegistry(structureToRemove)
    152 
    153     def DoBallsRemove(self, pythonBalls, isRelease):
    154         structuresToRemove = []
    155         for _ball, slimItem, _terminal in pythonBalls:
    156             if slimItem.categoryID == const.categoryStructure:
    157                 structuresToRemove.append(slimItem.itemID)
    158 
    159         if structuresToRemove:
    160             with self.CallFunctionWithStructureVisibilityUpdatesPaused():
    161                 self._RemoveStructuresFromRegistry(structuresToRemove)
    162 
    163     def _AddStructureToRegistry(self, structureToAdd):
    164         if structureToAdd in self.structureVisibilityRegistry:
    165             raise InvalidStateOfRegistry()
    166         isVisible = self.IsStructureVisible(structureToAdd)
    167         self.structureVisibilityRegistry[structureToAdd] = self._SetStructureVisibility(structureToAdd, isVisible)
    168         sm.ScatterEvent('OnStructuresVisibilityUpdated')
    169 
    170     def _RemoveStructureFromRegistry(self, structureToRemove):
    171         if structureToRemove not in self.structureVisibilityRegistry:
    172             raise InvalidStateOfRegistry()
    173         self._SetStructureVisibility(structureToRemove, False)
    174         del self.structureVisibilityRegistry[structureToRemove]
    175         sm.ScatterEvent('OnStructuresVisibilityUpdated')
    176 
    177     def _RemoveStructuresFromRegistry(self, structuresToRemove):
    178         for structureToRemove in structuresToRemove:
    179             self._RemoveStructureFromRegistry(structureToRemove)
    180 
    181     def OnDockingAccessChangedForCurrentSolarSystem_Local(self):
    182         self.dockableStructuresInSystemHaveChanged = True
    183 
    184     def HasDockingAccessChanged(self):
    185         return bool(self.dockableStructuresInSystemHaveChanged)