uiController.py (18933B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\skyhook\uiController.py 2 import numbers 3 import evetypes 4 import gametime 5 from brennivin.itertoolsext import Bundle 6 from carbon.common.script.util.format import FmtDate, FmtAmt 7 from const import SEC 8 from dogma.const import attributeSpecialColonyResourcesHoldCapacity 9 from eve.client.script.environment.invControllers import ShipColonyResourcesHold, ShipCargo 10 from eve.client.script.ui.eveColor import CHERRY_RED_HEX, CRYO_BLUE_HEX, LED_GREY_HEX 11 from eve.client.script.ui.shared.skyhook import NOT_AVAILABLE, UNDEFINED 12 from evelink import Link, format_show_info_url 13 from evelink.client import corporation_link, type_link 14 from inventorycommon import const as invConst 15 from inventorycommon.const import typeInfrastructureHub 16 from localization import GetByLabel 17 import orbitalSkyhook.resourceRichness as resourceRichness 18 from player_messaging.client.ui_message import prompt_player_fsd_dialog 19 from publicGateway.grpc.exceptions import GenericException 20 from signals import Signal 21 from sovereignty.resource.shared.planetary_resources_cache import DataUnavailableError 22 from sovereignty.skyhook.client.errors import SkyhookNotFoundError, SkyhookDeactivateForbiddenError, SkyhookActivateForbiddenError, SkyhookDeactivateInternalError 23 from sovereignty.skyhook.shared.skyhook_type_inference import get_skyhook_type_and_amount, POWER, WORKFORCE 24 from spacecomponents.client.components.orbitalSkyhook import ExtractReagentsToShip 25 from stackless_response_router.exceptions import TimeoutException 26 from spacecomponents.common.componentConst import LINK_WITH_SHIP 27 import logging 28 logger = logging.getLogger(__name__) 29 TEXT_NOTIFY_FORBIDDEN_ONLINE = 'Forbidden to set skyhook online' 30 TEXT_NOTIFY_COULDNT_ONLINE = "couldn't set online, Timed out" 31 TEXT_FORBIDDEN_OFFLINE = 'Forbidden to set skyhook online' 32 TEXT_FAILED_OFFLINE = 'Failed to set skyhook offline' 33 TEXT_TIMEOUT_OFFLINE = "couldn't set offline, Timed out" 34 35 class CurrentSkyhookUiController(object): 36 __notifyevents__ = ['OnLinkedShipChanged'] 37 38 def __init__(self, itemID, isAuthorisedToTake): 39 self._itemID = itemID 40 self._reagentTypeID = UNDEFINED 41 self._slimItem = UNDEFINED 42 self._planetID = UNDEFINED 43 self._linkedShipID = UNDEFINED 44 self._isAuthorisedToTake = isAuthorisedToTake 45 self.selectedQty = None 46 self.product = None 47 self.productAmount = 0 48 self.sovereigntyResourceSvc = sm.GetService('sovereigntyResourceSvc') 49 self.on_linked_ship_updated = Signal() 50 sm.RegisterNotify(self) 51 52 def __del__(self): 53 sm.UnregisterNotify(self) 54 55 def OnLinkedShipChanged(self, linkItemID, linkedShipID): 56 if linkItemID != self.reagentSiloItemID: 57 return 58 self._linkedShipID = linkedShipID 59 self.on_linked_ship_updated(linkItemID, linkedShipID) 60 61 def IsSameItemID(self, itemID): 62 return self._itemID == itemID 63 64 @property 65 def itemID(self): 66 return self._itemID 67 68 @property 69 def isAuthorisedToTake(self): 70 return self._isAuthorisedToTake 71 72 @property 73 def slimItem(self): 74 if self._slimItem == UNDEFINED: 75 self._slimItem = sm.GetService('michelle').GetItem(self.itemID) 76 return self._slimItem 77 78 @property 79 def reagentTypeID(self): 80 if self._reagentTypeID == UNDEFINED: 81 self._reagentTypeID = self.GetPlanetReagentType() 82 return self._reagentTypeID 83 84 @property 85 def planetID(self): 86 if self._planetID == UNDEFINED: 87 self._planetID = self.slimItem.planetID 88 return self._planetID 89 90 @property 91 def reagentSiloItemID(self): 92 return self.slimItem.reagentSiloItemID 93 94 @property 95 def linkedShipID(self): 96 if self._linkedShipID == UNDEFINED: 97 if self.reagentSiloItemID is None: 98 self._linkedShipID = None 99 else: 100 ballpark = sm.GetService('michelle').GetBallpark() 101 linkComponent = ballpark.componentRegistry.GetComponentForItem(self.reagentSiloItemID, LINK_WITH_SHIP) 102 self._linkedShipID = linkComponent.linkedShipID 103 return self._linkedShipID 104 105 def GetSkyhookName(self): 106 return GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/SlimSkyhookName', typeID=self.slimItem.typeID, planetID=self.planetID) 107 108 def GetOwnerID(self): 109 slimItem = sm.GetService('michelle').GetItem(self._itemID) 110 return slimItem.ownerID 111 112 def GetOwnerName(self): 113 ownerID = self.GetOwnerID() 114 if ownerID: 115 return corporation_link(ownerID) 116 return '-' 117 118 def GetResourceDestInfo(self): 119 solarsystemStructureInfo = sm.GetService('sov').GetSovStructuresInfoForSolarSystem(session.solarsystemid2) 120 for s in solarsystemStructureInfo: 121 if s.typeID == typeInfrastructureHub: 122 return s 123 124 def GetResourceDestName(self): 125 destInfo = self.GetResourceDestInfo() 126 if not destInfo: 127 return '-' 128 solarSystemName = cfg.evelocations.Get(destInfo.solarSystemID).name 129 itemName = '%s %s' % (solarSystemName, evetypes.GetName(destInfo.typeID)) 130 itemLink = Link(url=format_show_info_url(destInfo.typeID, destInfo.itemID), text=itemName) 131 ownerName = corporation_link(destInfo.ownerID) 132 text = '%s (%s)' % (itemLink, ownerName) 133 return text 134 135 def HasConfigRoles(self): 136 if self.slimItem.ownerID != session.corpid: 137 return False 138 if session.corprole & const.corpRoleStationManager: 139 return True 140 return False 141 142 def GetProductNameAndRichnessTexture(self): 143 product = self.GetProduct() 144 if not product: 145 return (GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable'), None, None) 146 onlineState = self.GetOnlineState() 147 amount = self.productAmount or 0 148 text = '' 149 texturePath = None 150 hintPath = None 151 textHint = None 152 if isinstance(product, numbers.Number): 153 amountPerMin = amount / 60.0 154 text = '%s - %s' % (type_link(product), GetByLabel('UI/Sovereignty/AmountPerMinute', value=float(amountPerMin))) 155 texturePath, hintPath = resourceRichness.GetPlanetReagentRichnessTexturePathAndHint(amount, product) 156 elif product == POWER: 157 if onlineState: 158 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/PowerAmount', amount=FmtAmt(self.productAmount)) 159 else: 160 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/PowerProductionOffline', amount=FmtAmt(self.productAmount)) 161 texturePath, hintPath = resourceRichness.GetPlanetPowerRichnessTexturePath(amount) 162 elif product == WORKFORCE: 163 text, texturePath, hintPath, textHint = self._GetWorkforceTextAndTexture(onlineState, amount) 164 if text: 165 return (text, 166 texturePath, 167 hintPath, 168 textHint) 169 return (GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable'), 170 None, 171 None, 172 None) 173 174 def _GetWorkforceTextAndTexture(self, onlineState, amount): 175 texturePath, hintPath = resourceRichness.GetPlanetWorkforceRichnessTexturePath(amount) 176 textHint = None 177 productAmount = self.productAmount 178 currentWorkforceAmount = self.sovereigntyResourceSvc.GetCurrentWorkforceForSkyhook(self.itemID) 179 if currentWorkforceAmount is not None and productAmount != currentWorkforceAmount: 180 percentage_different = round((currentWorkforceAmount - self.productAmount) / float(self.productAmount) * 100) 181 color = CHERRY_RED_HEX if percentage_different < 0 else CRYO_BLUE_HEX 182 if onlineState: 183 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/WorkforceAmountModified', amount=FmtAmt(currentWorkforceAmount), perc=percentage_different, perc_color=color) 184 else: 185 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/WorkforceOfflineModified', amount=FmtAmt(currentWorkforceAmount), perc=percentage_different, perc_color=color) 186 textHint = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/WorkforceModifiedHint', amount=FmtAmt(currentWorkforceAmount), total_amount=FmtAmt(productAmount), perc=percentage_different, previous_color=LED_GREY_HEX) 187 return (text, 188 texturePath, 189 hintPath, 190 textHint) 191 if onlineState: 192 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/WorkforceAmount', amount=FmtAmt(self.productAmount)) 193 else: 194 text = GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/WorkforceOffline', amount=FmtAmt(self.productAmount)) 195 return (text, 196 texturePath, 197 hintPath, 198 textHint) 199 200 def _GetSkyhookData(self): 201 try: 202 skyhookData = self.sovereigntyResourceSvc.GetSkyhook(self.itemID) 203 except Exception: 204 return None 205 206 return skyhookData 207 208 def GetProduct(self): 209 if self.product is None: 210 skyhookData = self._GetSkyhookData() 211 if skyhookData is None: 212 return 213 reagentDefinition = skyhookData.get_first_reagent_data() 214 reagentTypeID = None 215 reagentAmountsInfo = None 216 if reagentDefinition is not None: 217 reagentTypeID = reagentDefinition.type_id 218 reagentAmountsInfo = (reagentDefinition.configuration.amount_per_period, reagentDefinition.configuration.period) 219 power = self._GetProductDataForPlanet(self.sovereigntyResourceSvc.GetPlanetPowerProduction, skyhookData.resource_version) 220 workforce = self._GetProductDataForPlanet(self.sovereigntyResourceSvc.GetPlanetWorkforceProduction, skyhookData.resource_version) 221 self.product, self.productAmount = get_skyhook_type_and_amount(reagentTypeID, reagentAmountsInfo, power, workforce) 222 return self.product 223 224 def GetPlanetReagentType(self): 225 skyhookData = self._GetSkyhookData() 226 if skyhookData is None: 227 return self._GetProductDataForPlanet(self.sovereigntyResourceSvc.GetPlanetReagentType) 228 reagentData = skyhookData.get_first_reagent_data() 229 if reagentData is not None: 230 return reagentData.type_id 231 232 def _GetProductDataForPlanet(self, func, version = None): 233 try: 234 return func(self._planetID, version) 235 except DataUnavailableError as e: 236 logger.exception('Failed to get colony data') 237 return NOT_AVAILABLE 238 239 def GetOnlineState(self): 240 try: 241 return self.sovereigntyResourceSvc.IsProductionActiveAtSkyhook(self.itemID) 242 except SkyhookNotFoundError as e: 243 logger.exception('Failed to find skyhook') 244 except TimeoutException as e: 245 logger.exception('Skyhook: Timed out while getting online state') 246 except GenericException as e: 247 logger.exception('Failed to find skyhook active state') 248 249 return NOT_AVAILABLE 250 251 def SetOnline(self): 252 try: 253 return self.sovereigntyResourceSvc.ActivateSkyhook(self.itemID) 254 except SkyhookNotFoundError as e: 255 logger.exception('Failed to find skyhook') 256 except SkyhookDeactivateInternalError as e: 257 logger.exception('Failed to deactivate skyhook') 258 except SkyhookActivateForbiddenError as e: 259 logger.exception('Forbidden to online skyhook') 260 prompt_player_fsd_dialog('CustomNotify', {'notify': TEXT_NOTIFY_FORBIDDEN_ONLINE}) 261 except TimeoutException as e: 262 logger.exception('Skyhook: Timed out while onlining') 263 prompt_player_fsd_dialog('CustomNotify', {'notify': TEXT_NOTIFY_COULDNT_ONLINE}) 264 265 def SetOffline(self): 266 try: 267 return self.sovereigntyResourceSvc.DeactivateSkyhook(self.itemID) 268 except SkyhookNotFoundError as e: 269 logger.exception('Failed to find skyhook') 270 except SkyhookDeactivateForbiddenError as e: 271 logger.exception('Forbidden to offline skyhook') 272 prompt_player_fsd_dialog('CustomNotify', {'notify': TEXT_FORBIDDEN_OFFLINE}) 273 except SkyhookDeactivateInternalError as e: 274 logger.exception('Failed to deactivate skyhook') 275 prompt_player_fsd_dialog('CustomNotify', {'notify': TEXT_FAILED_OFFLINE}) 276 except TimeoutException as e: 277 logger.exception('Skyhook: Timed out while offlining') 278 prompt_player_fsd_dialog('CustomNotify', {'notify': TEXT_TIMEOUT_OFFLINE}) 279 280 def GetStorageQtyAndCapacity(self): 281 try: 282 skyhook_data = self._GetSkyhookData() 283 if skyhook_data is None: 284 secure_amount, insecure_amount = self.sovereigntyResourceSvc.GetPlanetReagentMaxAmounts(self.planetID) 285 else: 286 reagent_data = skyhook_data.get_first_reagent_data() 287 secure_amount, insecure_amount = reagent_data.configuration.secure_capacity, reagent_data.configuration.insecure_capacity 288 return (secure_amount, insecure_amount) 289 except SkyhookNotFoundError as e: 290 logger.exception('Failed to find skyhook') 291 except TimeoutException as e: 292 logger.exception('Skyhook: Timed out while getting reagents in skyhook') 293 except GenericException as e: 294 logger.exception('Failed to find skyhook reagents') 295 296 return NOT_AVAILABLE 297 298 def GetAmountInStorageText(self): 299 maxAmounts = self.GetStorageQtyAndCapacity() 300 if maxAmounts == NOT_AVAILABLE: 301 return (GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable'), None) 302 maxSecure, maxInsecure = maxAmounts 303 totalMaxQty = maxSecure + maxInsecure 304 reagentTypeID, secure_amount, insecure_amount = self.GetReagentsInSkyhook() 305 if NOT_AVAILABLE in (reagentTypeID, secure_amount, insecure_amount): 306 return (GetByLabel('UI/OrbitalSkyhook/SkyhookWnd/NoDataAvailable'), None) 307 unitVolume = evetypes.GetVolume(reagentTypeID) 308 secureVolume = secure_amount * unitVolume 309 insecureVolume = insecure_amount * unitVolume 310 totalVolume = round(secureVolume + insecureVolume) 311 maxVolume = round(totalMaxQty * unitVolume) 312 hintInfo = Bundle(secureVolume=round(secureVolume), maxSecureVolume=round(maxSecure * unitVolume), insecureVolume=round(insecureVolume), maxInsecureVolume=round(maxInsecure * unitVolume)) 313 return ('%s / %s ' % (FmtAmt(totalVolume), GetByLabel('UI/Contracts/ContractsWindow/NumericVolume', volume=FmtAmt(maxVolume))), hintInfo) 314 315 def GetReagentsInSkyhook(self): 316 try: 317 skyhookData = self._GetSkyhookData() 318 if skyhookData is None: 319 return (NOT_AVAILABLE, NOT_AVAILABLE, NOT_AVAILABLE) 320 reagentTypeID = skyhookData.get_first_reagent_data().type_id 321 secure_amount, insecure_amount = self.sovereigntyResourceSvc.GetReagentsInSkyhookNow(self.itemID) 322 return (reagentTypeID, secure_amount or 0, insecure_amount or 0) 323 except DataUnavailableError as e: 324 logger.exception('Failed to get colony data') 325 except TimeoutException as e: 326 logger.exception('Skyhook: Timed out while getting reagents in skyhook') 327 except GenericException as e: 328 logger.exception('Failed to find skyhook reagents') 329 330 return (NOT_AVAILABLE, NOT_AVAILABLE, NOT_AVAILABLE) 331 332 def GetNextReagentHarvestTimeAndAmount(self): 333 try: 334 nextTimestamp, amount, isFull = self.sovereigntyResourceSvc.GetNextReagentHarvestTimeAndAmount(self.itemID) 335 if (nextTimestamp, amount, isFull) == (None, None, False): 336 return (NOT_AVAILABLE, 337 NOT_AVAILABLE, 338 NOT_AVAILABLE, 339 False) 340 period = self.sovereigntyResourceSvc.GetNextHarvestPeriod(self.itemID) 341 previousTimestamp = nextTimestamp - period * SEC 342 progressSec = (gametime.GetWallclockTime() - previousTimestamp) / SEC 343 progress = progressSec / float(period) 344 return (nextTimestamp, 345 amount, 346 progress, 347 isFull) 348 except DataUnavailableError as e: 349 logger.exception('Failed to get colony data') 350 except TimeoutException as e: 351 logger.exception('Skyhook: Timed out while getting reagents in skyhook') 352 except GenericException as e: 353 logger.exception('Failed to find skyhook reagents') 354 355 return (NOT_AVAILABLE, 356 NOT_AVAILABLE, 357 NOT_AVAILABLE, 358 False) 359 360 def GetNextReagentHarvestAmounts(self): 361 try: 362 secured, unsecured = self.sovereigntyResourceSvc.GetNextReagentHarvestAmounts(self.itemID) 363 return (secured, unsecured) 364 except DataUnavailableError as e: 365 logger.exception('Failed to get colony data') 366 except TimeoutException as e: 367 logger.exception('Skyhook: Timed out while getting reagents in skyhook') 368 except GenericException as e: 369 logger.exception('Failed to find skyhook reagents') 370 371 return (NOT_AVAILABLE, NOT_AVAILABLE) 372 373 def ExtractReagentsToShip(self): 374 if self.HasResourceBay(): 375 flagID = invConst.flagColonyResourcesHold 376 holdController = ShipColonyResourcesHold() 377 else: 378 flagID = invConst.flagCargo 379 holdController = ShipCargo() 380 cap = holdController.GetCapacity() 381 availableVolume = cap.capacity - cap.used 382 selectedVolume = self.GetSelectedVolume() 383 selectedQty = self.selectedQty 384 if selectedVolume > availableVolume: 385 qtyToExtract = int(availableVolume / evetypes.GetVolume(self.reagentTypeID)) 386 else: 387 qtyToExtract = selectedQty 388 if not qtyToExtract: 389 if self.HasResourceBay(): 390 raise UserError('SkyhookNoUnitsFitInShipHold', {'holdName': holdController.GetName()}) 391 raise UserError('SkyhookNoUnitsFitInShipCargo') 392 try: 393 quantityExtracted = ExtractReagentsToShip(self.itemID, flagID, qtyToExtract) 394 prompt_player_fsd_dialog('SkyhookExtractionSuccess', {'numUnits': quantityExtracted}) 395 except Exception: 396 raise UserError('SkyhookExtractionFailed') 397 398 def GetSelectedVolume(self): 399 if self.reagentTypeID == NOT_AVAILABLE: 400 return 0 401 return self.selectedQty * evetypes.GetVolume(self.reagentTypeID) 402 403 def HasResourceBay(self): 404 return bool(sm.GetService('godma').GetAttributeValueByID(session.shipid, attributeSpecialColonyResourcesHoldCapacity)) 405 406 def GetTheftVulnerabilityForSkyhook(self): 407 return self.sovereigntyResourceSvc.GetTheftVulnerabilityForSkyhook(self.itemID)