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)