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

clonejumpsvc.py (15724B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\services\clonejumpsvc.py
      2 import logging
      3 import sys
      4 import carbonui.const as uiconst
      5 import eve.common.lib.appConst as const
      6 import localization
      7 import uthread2
      8 from carbon.common.script.net.moniker import Moniker
      9 from carbon.common.script.sys.service import Service
     10 from eve.common.script.sys import eveCfg
     11 from eve.common.script.util.eveFormat import FmtISK
     12 from eveexceptions import ExceptionEater, UserError
     13 from inventorycommon.typeHelpers import GetAveragePrice
     14 from menucheckers import SessionChecker
     15 import blue
     16 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     17 log = logging.getLogger(__name__)
     18 
     19 class CloneJump(Service):
     20     __exportedcalls__ = {'GetClones': [],
     21      'GetCloneImplants': [],
     22      'GetShipClones': [],
     23      'GetStationClones': [],
     24      'HasCloneReceivingBay': [],
     25      'GetCloneAtLocation': [],
     26      'GetImplantsForClone': [],
     27      'DestroyInstalledClone': [],
     28      'CloneJump': [],
     29      'OfferShipCloneInstallation': [],
     30      'LastCloneJumpTime': [],
     31      'ValidateInstallJumpClone': []}
     32     __guid__ = 'svc.clonejump'
     33     __displayname__ = 'Clone Jump Service'
     34     __notifyevents__ = ['OnShipJumpCloneInstallationOffered',
     35      'OnShipJumpCloneInstallationDone',
     36      'OnJumpCloneCacheInvalidated',
     37      'OnShipJumpCloneCacheInvalidated',
     38      'OnStationJumpCloneCacheInvalidated',
     39      'OnShipJumpCloneInstallationCanceled',
     40      'OnSessionReset',
     41      'OnSessionChanged']
     42     __dependencies__ = []
     43     __update_on_reload__ = 0
     44 
     45     def Run(self, memStream = None):
     46         Service.Run(self, memStream)
     47         self.Initialize()
     48 
     49     def Initialize(self):
     50         self.jumpClones = None
     51         self.jumpCloneImplants = None
     52         self.shipJustClonesShipID = None
     53         self.shipJumpClones = None
     54         self.timeLastJump = None
     55         self.stationJumpClones = None
     56         self.cloneInstallOfferActive = 0
     57         self.lastCloneJumpTime = None
     58         self.clonejumpCheck = None
     59         self.cloneJumpingFromShip = False
     60 
     61     def GetClones(self):
     62         self.GetCloneState()
     63         return self.jumpClones
     64 
     65     def GetCloneImplants(self):
     66         self.GetCloneState()
     67         return self.jumpCloneImplants
     68 
     69     def SetJumpCloneName(self, cloneID, newName):
     70         lm = self.GetLM()
     71         lm.SetJumpCloneName(cloneID, newName)
     72 
     73     def GetLM(self):
     74         if session.solarsystemid or session.structureid:
     75             return Moniker('jumpCloneSvc', (session.solarsystemid, const.groupSolarSystem))
     76         else:
     77             return Moniker('jumpCloneSvc', (session.stationid, const.groupStation))
     78 
     79     def GetCloneState(self):
     80         if self.jumpClones is None:
     81             lm = self.GetLM()
     82             kv = lm.GetCloneState()
     83             self.jumpClones = kv.clones
     84             self.jumpCloneImplants = kv.implants
     85             self.timeLastJump = kv.timeLastJump
     86 
     87     def GetShipClones(self):
     88         shipID = eveCfg.GetActiveShip()
     89         if not self.shipJumpClones or shipID != self.shipJustClonesShipID:
     90             lm = self.GetLM()
     91             self.shipJustClonesShipID = shipID
     92             self.shipJumpClones = lm.GetShipCloneState()
     93         return self.shipJumpClones
     94 
     95     def GetStationClones(self):
     96         if not self.stationJumpClones:
     97             lm = self.GetLM()
     98             self.stationJumpClones = lm.GetStationCloneState()
     99         return self.stationJumpClones
    100 
    101     def GetNumClonesInPilotsStructure(self):
    102         if session.structureid != session.shipid:
    103             return
    104         return self.GetLM().GetNumClonesInPilotsStructure()
    105 
    106     def OfferShipCloneInstallation(self, charID):
    107         lm = self.GetLM()
    108         sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CloneJump/WaitingForAck'), localization.GetByLabel('UI/CloneJump/InstallationInviteSent', player=charID), 1, 2, abortFunc=self.CancelShipCloneInstallation)
    109         try:
    110             lm.OfferShipCloneInstallation(charID)
    111         except UserError as e:
    112             sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CloneJump/CloneInstallAborted'), '', 1, 1)
    113             raise
    114 
    115     def LastCloneJumpTime(self):
    116         self.GetCloneState()
    117         return self.timeLastJump
    118 
    119     def DestroyInstalledClone(self, cloneID):
    120         message = None
    121         clonePrice = self.GetPriceForClone(cloneID)
    122         myClones = self.GetClones()
    123         if myClones:
    124             myClones = myClones.Index('jumpCloneID')
    125             if cloneID in myClones:
    126                 if myClones[cloneID].locationID == session.stationid:
    127                     message = localization.GetByLabel('UI/CloneJump/ReallyDestroyCloneAtCurrentStation')
    128                 else:
    129                     cfg.evelocations.Prime([myClones[cloneID].locationID])
    130                     message = localization.GetByLabel('UI/CloneJump/ReallyDestroyCloneAtSomewhereElse', location=myClones[cloneID].locationID)
    131                 if clonePrice:
    132                     cloneText = localization.GetByLabel('UI/CloneJump/EstimatedClonePrice', iskValue=clonePrice)
    133                     message = '%s<br>%s' % (message, cloneText)
    134         if not message:
    135             if eveCfg.GetActiveShip():
    136                 shipClones = self.GetShipClones()
    137                 if shipClones:
    138                     shipClones = shipClones.Index('jumpCloneID')
    139                     if cloneID in shipClones:
    140                         cfg.eveowners.Prime([shipClones[cloneID].ownerID])
    141                         cfg.evelocations.Prime([shipClones[cloneID].locationID])
    142                         message = localization.GetByLabel('UI/CloneJump/ReallyDestroyCloneInShip', owner=shipClones[cloneID].ownerID, ship=shipClones[cloneID].locationID)
    143                         if clonePrice:
    144                             cloneText = localization.GetByLabel('UI/CloneJump/EstimatedClonePrice', iskValue=clonePrice)
    145                             message = '%s<br>%s' % (message, cloneText)
    146         if not message:
    147             return
    148         ret = prompt_player_fsd_dialog('AskAreYouSure', {'cons': message}, uiconst.YESNO)
    149         if ret == uiconst.ID_YES:
    150             lm = self.GetLM()
    151             lm.DestroyInstalledClone(cloneID)
    152 
    153     def InstallCloneInStation(self):
    154         if not self.CanJumpCloneFromCurrentLocation():
    155             return
    156         lm = self.GetLM()
    157         cost = lm.GetPriceForClone()
    158         if cost > 0.0:
    159             response = prompt_player_fsd_dialog('AskAcceptJumpCloneCost', {'cost': cost}, uiconst.YESNO)
    160             if response != uiconst.ID_YES:
    161                 return
    162         if session.stationid:
    163             lm.InstallCloneInStation()
    164         else:
    165             lm.InstallCloneInStructure()
    166 
    167     def CancelShipCloneInstallation(self, *args):
    168         sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CloneJump/CloneInstallAborted'), '', 1, 1)
    169         lm = self.GetLM()
    170         lm.CancelShipCloneInstallation()
    171 
    172     def CanJumpCloneFromCurrentLocation(self):
    173         if session.stationid:
    174             return True
    175         if session.structureid:
    176             return True
    177         return False
    178 
    179     def ActivateCloneJumpCheck(self, cloneJumpCheck):
    180         self.clonejumpCheck = cloneJumpCheck
    181 
    182     def DeactivateCloneJumpCheck(self):
    183         self.clonejumpCheck = None
    184 
    185     def CheckCloneJump(self):
    186         if not callable(self.clonejumpCheck):
    187             return True
    188         return self.clonejumpCheck()
    189 
    190     def CloneJump(self, destLocationID, cloneID):
    191         if not self.CanJumpCloneFromCurrentLocation():
    192             prompt_player_fsd_dialog('NotAtStation')
    193             return
    194         if not self.CheckCloneJump():
    195             return
    196         lm = self.GetLM()
    197         cost = lm.GetPriceForClone()
    198         if cost > 0.0:
    199             response = prompt_player_fsd_dialog('AskAcceptJumpCloneCost', {'cost': cost}, uiconst.YESNO)
    200             if response != uiconst.ID_YES:
    201                 return
    202         checker = SessionChecker(session, sm)
    203         inCapsule = checker.IsPilotInCapsule()
    204         if inCapsule and not GetJumpDelay():
    205             self._CloneJump(destLocationID, cloneID, cost)
    206         else:
    207             uthread2.start_tasklet(self.UnboardShipAndCloneJump_thread, destLocationID, cloneID, cost, inCapsule)
    208 
    209     def _CloneJump(self, destLocationID, cloneID, cost):
    210         self.cloneJumpingFromShip = None
    211         lm = self.GetLM()
    212         try:
    213             sm.GetService('sessionMgr').PerformSessionChange('clonejump', lm.CloneJump, destLocationID, cloneID, cost, False)
    214             sm.GetService('infoPanel').UpdateSessionTimer()
    215         except UserError as e:
    216             if e.msg not in ('JumpCheckWillLoseExistingClone', 'JumpCheckIntoShip', 'JumpCheckIntoStructure'):
    217                 sm.ScatterEvent('OnCloneJumpUpdate')
    218                 raise e
    219             if prompt_player_fsd_dialog(e.msg, e.dict, uiconst.YESNO) == uiconst.ID_YES:
    220                 session.ResetSessionChangeTimer('Retrying with confirmation approval')
    221                 sm.GetService('sessionMgr').PerformSessionChange('clonejump', lm.CloneJump, destLocationID, cloneID, cost, True)
    222                 sm.GetService('infoPanel').UpdateSessionTimer()
    223             else:
    224                 sm.ScatterEvent('OnCloneJumpUpdate')
    225             sys.exc_clear()
    226 
    227     def UnboardShipAndCloneJump_thread(self, destLocationID, cloneID, cost, inCapsule = False):
    228         if self.cloneJumpingFromShip:
    229             return
    230         prompt_player_fsd_dialog('StartingCloneJumping')
    231         shipID = session.shipid
    232         ship = sm.GetService('godma').GetItem(shipID)
    233         self.cloneJumpingFromShip = (shipID, cloneID)
    234         if blue.os.GetSimTime() < session.nextSessionChange:
    235             sm.ScatterEvent('OnCloneJumpUpdate')
    236         while blue.os.GetSimTime() < session.nextSessionChange:
    237             blue.synchro.Yield()
    238 
    239         if not self.cloneJumpingFromShip or self.cloneJumpingFromShip[0] != shipID:
    240             sm.ScatterEvent('OnCloneJumpUpdate')
    241             return
    242         if not inCapsule:
    243             prompt_player_fsd_dialog('DisembarkingFromShip')
    244             sm.GetService('station').TryLeaveShip(ship)
    245         jumpDelay = GetJumpDelay()
    246         uthread2.Sleep(jumpDelay)
    247         while blue.os.GetSimTime() < session.nextSessionChange:
    248             blue.synchro.Yield()
    249 
    250         if self.cloneJumpingFromShip and self.cloneJumpingFromShip[0] == shipID:
    251             self._CloneJump(destLocationID, cloneID, cost)
    252         else:
    253             sm.ScatterEvent('OnCloneJumpUpdate')
    254 
    255     def GetCloneAtLocation(self, locationID):
    256         clones = self.GetClones()
    257         if clones:
    258             for c in clones:
    259                 if locationID == c.locationID:
    260                     return (c.jumpCloneID, c.cloneName)
    261 
    262         return (None, None)
    263 
    264     def GetImplantsForClone(self, cloneID):
    265         cloneImplants = self.GetCloneImplants()
    266         if not cloneImplants:
    267             return []
    268         implantsByCloneID = cloneImplants.Filter('jumpCloneID')
    269         return implantsByCloneID.get(cloneID, [])
    270 
    271     def GetPriceForClone(self, cloneID):
    272         typeIDs = [ x for x in self.GetImplantsForClone(cloneID) ]
    273         if not typeIDs:
    274             return 0
    275         implantCost = sum((GetAveragePrice(x.typeID) or 0 for x in typeIDs))
    276         return implantCost
    277 
    278     def HasCloneReceivingBay(self):
    279         if session.shipid:
    280             ship = sm.GetService('godma').GetItem(session.shipid)
    281             for module in ship.modules:
    282                 if const.typeCloneVatBayI == module.typeID:
    283                     return True
    284 
    285         return False
    286 
    287     def OnJumpCloneCacheInvalidated(self):
    288         self.jumpClones = None
    289         self.jumpCloneImplants = None
    290         self.timeLastJump = None
    291         sm.ScatterEvent('OnCloneJumpUpdate')
    292 
    293     def OnShipJumpCloneCacheInvalidated(self, locationID, charID):
    294         if eveCfg.GetActiveShip() == locationID:
    295             self.shipJumpClones = None
    296             sm.ScatterEvent('OnShipCloneJumpUpdate')
    297 
    298     def OnStationJumpCloneCacheInvalidated(self, locationID, charID):
    299         if session.stationid == locationID:
    300             self.stationJumpClones = None
    301             sm.ScatterEvent('OnCloneJumpUpdate')
    302 
    303     def OnShipJumpCloneInstallationOffered(self, args):
    304         offeringCharID, targetCharID, shipID, b = (args[0],
    305          args[1],
    306          args[2],
    307          args[3])
    308         self.cloneInstallOfferActive = 1
    309         cfg.eveowners.Prime([offeringCharID, targetCharID])
    310         offeringChar = cfg.eveowners.Get(offeringCharID)
    311         cfg.evelocations.Prime([shipID])
    312         ship = cfg.evelocations.Get(shipID)
    313         lm = self.GetLM()
    314         costs = lm.GetPriceForClone()
    315         ret = prompt_player_fsd_dialog('JumpCloneInstallationOffered', {'offerer': offeringChar.name,
    316          'shipname': ship.name,
    317          'costs': FmtISK(costs)}, uiconst.YESNO)
    318         try:
    319             if ret == uiconst.ID_YES:
    320                 lm.AcceptShipCloneInstallation()
    321             elif ret != uiconst.ID_CLOSE:
    322                 lm.CancelShipCloneInstallation()
    323         except UserError as e:
    324             prompt_player_fsd_dialog(e.msg, e.dict)
    325             sys.exc_clear()
    326 
    327         self.cloneInstallOfferActive = 0
    328 
    329     def OnShipJumpCloneInstallationDone(self, args):
    330         offeringCharID, targetCharID, shipID, b = (args[0],
    331          args[1],
    332          args[2],
    333          args[3])
    334         self.cloneInstallOfferActive = 0
    335         sm.ScatterEvent('OnShipJumpCloneUpdate')
    336         sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CloneJump/CloneInstallFinished'), '', 1, 1)
    337 
    338     def OnShipJumpCloneInstallationCanceled(self, args):
    339         try:
    340             sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CloneJump/CloneInstallAborted'), '', 1, 1)
    341             lm = self.GetLM()
    342             lm.CancelShipCloneInstallation()
    343         except UserError as e:
    344             self.LogInfo('Ignoring usererror', e.msg, 'while cancelling ship clone installation')
    345             sys.exc_clear()
    346 
    347     def OnSessionReset(self):
    348         self.Initialize()
    349 
    350     def OnSessionChanged(self, isRemote, session, change):
    351         if not self.cloneJumpingFromShip:
    352             return
    353         if len(change) == 1 and 'shipid' in change:
    354             oldShipID, newShipID = change['shipid']
    355             if oldShipID == self.cloneJumpingFromShip[0]:
    356                 checker = SessionChecker(session, sm)
    357                 if checker.IsPilotInCapsule():
    358                     return
    359         prompt_player_fsd_dialog('CloneJumpingCancelled')
    360         self.cloneJumpingFromShip = None
    361 
    362     def IsCloneJumping(self):
    363         return bool(self.cloneJumpingFromShip)
    364 
    365     def IsJumpingIntoClone(self, cloneID):
    366         if not self.IsCloneJumping():
    367             return False
    368         if self.cloneJumpingFromShip[1] == cloneID:
    369             return True
    370         return False
    371 
    372     def ValidateInstallJumpClone(self):
    373         try:
    374             error_labels = self.GetLM().ValidateInstallJumpClone()
    375         except Exception:
    376             log.exception('Unknown error caught during clone install validation')
    377             sys.exc_clear()
    378             error_labels = ['UI/Medical/Errors/UnknownValidationError']
    379 
    380         errors = []
    381         for label in error_labels:
    382             if isinstance(label, basestring):
    383                 errors.append(localization.GetByLabel(label))
    384             else:
    385                 with ExceptionEater():
    386                     label, args = label
    387                     errors.append(localization.GetByLabel(label, **args))
    388 
    389         return errors
    390 
    391 
    392 def GetJumpDelay():
    393     jumpDelay = 0
    394     if session and session.nextSessionChange:
    395         duration = session.nextSessionChange - blue.os.GetSimTime()
    396         if duration > 0:
    397             jumpDelay = duration / const.SEC + 1
    398     return jumpDelay