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

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)