dynamicResourceSvc.py (12916B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\dynamicResource\dynamicResourceSvc.py 2 import datetimeutils 3 import dynamicresources.client 4 import locks 5 import threadutils 6 from carbon.common.script.sys.service import Service 7 from carbon.common.script.sys.serviceManager import ServiceManager 8 from dynamicresources.client import text 9 from dynamicresources.common.ess.const import LINK_ERROR_ALREADY_LINKED, LINK_VALID, LINK_ERROR_SYSTEM_OFFLINE, LINK_ERROR_NOT_ON_GRID, LINK_ERROR_OUT_OF_RANGE, LINK_ERROR_INVALID_SHIP_TYPE, LINK_ERROR_LINK_OCCUPIED, ESS_LINKABLE_TYPES_LIST, ESS_MAX_LINK_DISTANCE_METERS, LINK_ERROR_NO_BALLPARK 10 from dynamicresources.common.ess.data import get_key_by_type 11 from evetypes import GetTypeIDsByListID 12 from globalConfig import GetDynamicBountySystemEmergencyOffline, DYNAMIC_BOUNTY_SYSTEM_EMERGENCY_OFFLINE_CONFIG as DBS_OFFLINE_KEY, GetESSFeatureFlaggedOffline, ESS_FEATURE_FLAG_DISABLED_CONFIG as ESS_OFFLINE_KEY, GetESSReserveBankFeatureFlaggedOffline, ESS_RESERVE_BANK_DISABLED_CONFIG as RESERVE_OFFLINE_KEY 13 from player_messaging.client.ui_message import prompt_player_fsd_dialog 14 from threadutils import expiring_memoize 15 MAIN_BANK = 0 16 RESERVE_BANK = 1 17 18 class DynamicResourceSvc(Service): 19 __guid__ = 'svc.dynamicResourceSvc' 20 __servicename__ = 'DynamicResourceSvc' 21 __startupdependencies__ = ['machoNet'] 22 __notifyevents__ = ['OnSystemDynamicBountyStateChanged', 23 'OnSystemESSDataChanged', 24 'OnSessionChanged', 25 'OnGlobalConfigUpdated', 26 'OnMainBankPlayerHackSuccess', 27 'OnESSMainBankLinkNotification', 28 'OnESSReserveBankLinkNotification', 29 'OnMainBankPlayerLinkDisconnected', 30 'OnReserveBankPlayerLinkDisconnected'] 31 32 def __init__(self): 33 super(DynamicResourceSvc, self).__init__() 34 self._ess_state_provider = None 35 self._ess_settings = None 36 self._is_ess_state_update_in_progress = False 37 self._pending_ess_state_update = False 38 39 def Run(self, memStream = None): 40 super(DynamicResourceSvc, self).Run(memStream) 41 self._ess_state_provider = dynamicresources.EssStateProvider(state=self._GetInitialEssState(), on_fetch_request=self._ForceUpdateEssStateProvider) 42 self._ess_state_provider.mark_need_fetch() 43 self._ess_settings = dynamicresources.EssSettings(service_manager=ServiceManager.Instance()) 44 45 @property 46 def ess_state_provider(self): 47 return self._ess_state_provider 48 49 @property 50 def ess_settings(self): 51 return self._ess_settings 52 53 @expiring_memoize(5400) 54 def GetDynamicBountySettingForCurrentSystem(self): 55 if GetDynamicBountySystemEmergencyOffline(self.machoNet): 56 return (1.0, False) 57 dynamicBountyMgr = sm.RemoteSvc('dynamicBountyMgr') 58 output, dbsIsActive = dynamicBountyMgr.GetOutputForClientSolarSystem() 59 return (output, dbsIsActive) 60 61 @locks.SingletonCall 62 @expiring_memoize(900) 63 def GetESSDataForCurrentSystem(self): 64 if GetESSFeatureFlaggedOffline(self.machoNet): 65 return None 66 return sm.RemoteSvc('essMgr').GetDataForClientSolarSystem() 67 68 def IsPlayerLinkedToReserveBank(self): 69 essSvc = sm.RemoteSvc('essMgr') 70 return essSvc.IsClientLinkedToReserveBank() 71 72 def CheckLinkEligibility(self, bank): 73 if GetESSFeatureFlaggedOffline(self.machoNet): 74 return LINK_ERROR_SYSTEM_OFFLINE 75 state = self.ess_state_provider.state 76 if state.offline: 77 return LINK_ERROR_SYSTEM_OFFLINE 78 if bank == MAIN_BANK: 79 if state.reserve_bank.linked: 80 return LINK_ERROR_ALREADY_LINKED 81 if state.main_bank.link is not None: 82 if state.main_bank.is_hacking(session.charid): 83 return LINK_ERROR_ALREADY_LINKED 84 else: 85 return LINK_ERROR_LINK_OCCUPIED 86 if bank == RESERVE_BANK: 87 if state.main_bank.link is not None and state.main_bank.link.character_id == session.charid: 88 return LINK_ERROR_ALREADY_LINKED 89 if state.reserve_bank.linked: 90 return LINK_ERROR_ALREADY_LINKED 91 shipID = session.shipid 92 ballpark = sm.GetService('michelle').GetBallpark() 93 if ballpark is None: 94 return LINK_ERROR_NO_BALLPARK 95 try: 96 typeID = ballpark.slimItems[shipID].typeID 97 except KeyError: 98 typeID = None 99 100 if typeID is None or typeID not in GetTypeIDsByListID(ESS_LINKABLE_TYPES_LIST): 101 return LINK_ERROR_INVALID_SHIP_TYPE 102 if ballpark.GetBall(state.ess_item_id) is None: 103 return LINK_ERROR_NOT_ON_GRID 104 dist = ballpark.DistanceBetween(shipID, state.ess_item_id) 105 if dist > ESS_MAX_LINK_DISTANCE_METERS: 106 return LINK_ERROR_OUT_OF_RANGE 107 return LINK_VALID 108 109 def RequestESSMainBankLink(self): 110 eligibility = self.CheckLinkEligibility(MAIN_BANK) 111 if eligibility != LINK_VALID: 112 return eligibility 113 essSvc = sm.RemoteSvc('essMgr') 114 essSvc.AttemptLinkToMainBank() 115 116 def RequestESSReserveBankLink(self): 117 if GetESSReserveBankFeatureFlaggedOffline(self.machoNet) == True: 118 return LINK_ERROR_SYSTEM_OFFLINE 119 eligibility = self.CheckLinkEligibility(RESERVE_BANK) 120 if eligibility != LINK_VALID: 121 return eligibility 122 essSvc = sm.RemoteSvc('essMgr') 123 essSvc.AttemptLinkToReserveBank() 124 125 def RequestESSMainBankUnlink(self): 126 sm.RemoteSvc('essMgr').RequestMainBankUnlink() 127 128 def RequestESSReserveBankUnlink(self): 129 sm.RemoteSvc('essMgr').RequestReserveBankUnlink() 130 131 def RequestUnlockReserveBank(self, typeID): 132 essMgr = sm.RemoteSvc('essMgr') 133 essMgr.RequestUnlockReserveBank(typeID) 134 135 @expiring_memoize(300) 136 def GetESSAccessHistoryForCurrentSystem(self): 137 mainData = sm.RemoteSvc('essMgr').GetMainBankTheftsForClientSolarSystem() 138 reserveData = sm.RemoteSvc('essMgr').GetReserveBankTheftsForClientSolarSystem() 139 return {'main': mainData, 140 'reserve': reserveData} 141 142 def GetESSReserveBankKeysForCurrentSystem(self): 143 dynamicResourceCacheMgr = sm.RemoteSvc('dynamicResourceCacheMgr') 144 key_type_ids = dynamicResourceCacheMgr.GetESSReserveBankKeys(session.solarsystemid2) 145 return [ get_key_by_type(type_id) for type_id in key_type_ids ] 146 147 def OnSystemDynamicBountyStateChanged(self, systemID, rate): 148 if systemID == session.solarsystemid2: 149 self.GetDynamicBountySettingForCurrentSystem.prime_cache_result((self,), (rate, True)) 150 sm.ScatterEvent('OnDynamicBountyUpdate_Local') 151 152 def OnSystemESSDataChanged(self, systemID, data): 153 if systemID == session.solarsystemid2: 154 self.GetESSDataForCurrentSystem.prime_cache_result((self,), data) 155 self.GetESSAccessHistoryForCurrentSystem.clear_cache() 156 self._NotifyEssDataChanged() 157 158 def OnSessionChanged(self, isremote, session, change): 159 if 'solarsystemid2' in change: 160 self.GetDynamicBountySettingForCurrentSystem.clear_cache() 161 sm.ScatterEvent('OnDynamicBountyUpdate_Local') 162 self.GetESSDataForCurrentSystem.clear_cache() 163 self.GetESSAccessHistoryForCurrentSystem.clear_cache() 164 self._NotifyEssDataChanged() 165 166 def OnGlobalConfigUpdated(self, key, val): 167 if key == DBS_OFFLINE_KEY: 168 self.GetDynamicBountySettingForCurrentSystem.clear_cache() 169 sm.ScatterEvent('OnDynamicBountyUpdate_Local') 170 if key == ESS_OFFLINE_KEY or key == RESERVE_OFFLINE_KEY: 171 self.GetESSDataForCurrentSystem.clear_cache() 172 self._NotifyEssDataChanged() 173 174 def OnESSMainBankLinkNotification(self, solar_system_id): 175 if is_current_system(solar_system_id): 176 self.GetESSDataForCurrentSystem.clear_cache() 177 self._NotifyEssDataChanged() 178 179 def OnESSReserveBankLinkNotification(self, solar_system_id): 180 if is_current_system(solar_system_id): 181 self._ess_state_provider.evolve(reserve_bank=self._ess_state_provider.state.reserve_bank.evolve(linked=True)) 182 183 def OnMainBankPlayerHackSuccess(self, hack_data): 184 if is_current_system(hack_data['solarSystemID']): 185 self._ess_state_provider.evolve(main_bank=self._ess_state_provider.state.main_bank.evolve(link_result=dynamicresources.MainBankLinkResult(link_id=hack_data['linkID'], character_id=int(hack_data['characterID']), successful=True))) 186 187 def OnMainBankPlayerLinkDisconnected(self, data): 188 if is_current_system(data['solarSystemID']): 189 self._ess_state_provider.evolve(main_bank=self._ess_state_provider.state.main_bank.evolve(link_result=dynamicresources.MainBankLinkResult(link_id=data['linkID'], character_id=data['characterID'], successful=False))) 190 if data['characterID'] == session.charid: 191 message = text.unlink_reason_description(data['reason']) 192 if message: 193 prompt_player_fsd_dialog('CustomNotify', {'notify': message}) 194 195 def OnReserveBankPlayerLinkDisconnected(self, data): 196 if is_current_system(data['solarSystemID']): 197 self._ess_state_provider.evolve(reserve_bank=self._ess_state_provider.state.reserve_bank.evolve(linked=False)) 198 if data['characterID'] == session.charid: 199 message = text.unlink_reason_description(int(data['reason'])) 200 if message: 201 prompt_player_fsd_dialog('CustomNotify', {'notify': message}) 202 203 def _NotifyEssDataChanged(self): 204 self._UpdateEssStateProvider() 205 sm.ScatterEvent('OnESSDataUpdate_Local') 206 207 @threadutils.threaded 208 def _ForceUpdateEssStateProvider(self): 209 self._UpdateEssStateProvider(force=True) 210 211 def _UpdateEssStateProvider(self, force = False): 212 if self._is_ess_state_update_in_progress: 213 self._pending_ess_state_update = True 214 return 215 self._is_ess_state_update_in_progress = True 216 try: 217 self._pending_ess_state_update = True 218 while self._pending_ess_state_update: 219 self._pending_ess_state_update = False 220 if is_current_system(None): 221 self._ess_state_provider.evolve(status=dynamicresources.EssStatus.offline, ess_item_id=None) 222 continue 223 if not self._ess_state_provider.has_subscribers and not force: 224 self._ess_state_provider.mark_need_fetch() 225 continue 226 ess_data = self.GetESSDataForCurrentSystem() 227 if ess_data is None or ess_data['essID'] is None: 228 self._ess_state_provider.evolve(status=dynamicresources.EssStatus.offline, ess_item_id=None) 229 continue 230 current_state = self._ess_state_provider.state 231 main_bank_link = None 232 if ess_data['mainBankLink']: 233 main_bank_link = dynamicresources.MainBankLink(link_id=ess_data['mainBankLink']['linkID'], character_id=ess_data['mainBankLink']['characterID'], start=datetimeutils.filetime_to_datetime(ess_data['mainBankLink']['startedAt']), end=datetimeutils.filetime_to_datetime(ess_data['mainBankLink']['completesAt'])) 234 last_pulse_start = ess_data['reserveBankLastPulseInitiated'] 235 if last_pulse_start is not None: 236 last_pulse_start = datetimeutils.filetime_to_datetime(last_pulse_start) 237 pulses_remaining = ess_data['reserveBankPulsesRemaining'] 238 link_count = ess_data['reserveBankActiveLinks'] 239 linked = False 240 if pulses_remaining > 0 and link_count > 0: 241 linked = self.IsPlayerLinkedToReserveBank() 242 self._ess_state_provider.evolve(status=dynamicresources.EssStatus.online, ess_item_id=ess_data['essID'], main_bank=current_state.main_bank.evolve(balance=ess_data['mainValue'], link=main_bank_link), reserve_bank=dynamicresources.ReserveBankState(balance=ess_data['reserveValue'], pulses_total=ess_data['reserveBankPulsesTotal'], pulses_remaining=pulses_remaining, last_pulse_start=last_pulse_start, link_count=link_count, linked=linked)) 243 244 finally: 245 self._is_ess_state_update_in_progress = False 246 247 def _GetInitialEssState(self): 248 return dynamicresources.EssState(status=dynamicresources.EssStatus.loading, ess_item_id=None, in_range=False, main_bank=dynamicresources.MainBankState(balance=0, link=None, link_result=None), reserve_bank=dynamicresources.ReserveBankState(balance=0, pulses_total=0, pulses_remaining=0, last_pulse_start=None, link_count=0, linked=False)) 249 250 251 def is_current_system(solar_system_id): 252 return getattr(session, 'solarsystemid2', None) == solar_system_id