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

bountySvc.py (13178B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\bountySvc.py
      2 import blue
      3 import uthread
      4 import telemetry
      5 import localization
      6 from carbon.common.script.sys.service import Service
      7 from eve.common.lib import appConst as const, killRightTracker
      8 from eve.common.script.sys import idCheckers
      9 from eve.common.script.util import bountyUtil
     10 from eveexceptions import UserError
     11 from globalConfig.getFunctions import IsPlayerBountyHidden
     12 from caching.memoize import Memoize
     13 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     14 
     15 class BountyService(Service):
     16     __guid__ = 'svc.bountySvc'
     17     __startupdependencies__ = ['machoNet']
     18     __notifyevents__ = ['DoBallsAdded',
     19      'OnKillRightCreated',
     20      'OnKillRightUsed',
     21      'OnKillRightActivated',
     22      'OnGlobalConfigChanged',
     23      'OnKillRightForYouSold',
     24      'OnSessionReset']
     25     DISABLE_BOUNTY_KEY = 'isDynamicBountiesAndKillRightsDisabled'
     26 
     27     def __init__(self):
     28         super(BountyService, self).__init__()
     29         self.bounties = {}
     30         self.cacheTime = 5 * const.MIN
     31         self.myKillRights = None
     32         self.killRightTracker = None
     33 
     34     def Run(self, *args, **kwargs):
     35         Service.Run(self, *args, **kwargs)
     36         config = self.machoNet.GetGlobalConfig()
     37         self._SetDisabledStatus(config)
     38         self.Reset()
     39 
     40     def Reset(self):
     41         self.bounties = {}
     42         self.myKillRights = None
     43         self.killRightTracker = killRightTracker.KillRightTracker(self.FetchKillRightsFromServer, blue.os.GetWallclockTime, 5 * const.MIN)
     44 
     45     def OnSessionReset(self):
     46         self.GetMyBounties.clear_memoized()
     47         self.Reset()
     48 
     49     def _SetDisabledStatus(self, config):
     50         self.isDisabled = int(config.get(self.DISABLE_BOUNTY_KEY, 0))
     51 
     52     def OnGlobalConfigChanged(self, config):
     53         self._SetDisabledStatus(config)
     54 
     55     def GetBounty(self, *ownerIDs):
     56         if IsPlayerBountyHidden(self.machoNet):
     57             return 0
     58         ownerIDs = [ ownerID for ownerID in ownerIDs if ownerID is not None ]
     59         self.FetchBounties(ownerIDs)
     60         return sum((self.bounties[ownerID][0].bounty for ownerID in ownerIDs))
     61 
     62     def GetBountyFromCache(self, ownerID):
     63         return self.bounties[ownerID][0].bounty
     64 
     65     def GetBounties(self, *ownerIDs):
     66         if IsPlayerBountyHidden(self.machoNet):
     67             return {}
     68         ownerIDs = [ ownerID for ownerID in ownerIDs if ownerID is not None ]
     69         self.FetchBounties(ownerIDs)
     70         return {ownerID:self.bounties[ownerID][0].bounty for ownerID in ownerIDs}
     71 
     72     def AddToBounty(self, ownerID, amount):
     73         newBounty = sm.ProxySvc('bountyProxy').AddToBounty(ownerID, amount)
     74         bountyUtil.CacheBounties(self.bounties, [newBounty])
     75         self.GetMyBounties.clear_memoized()
     76 
     77     def CanHaveBounty(self, slimItem):
     78         if IsPlayerBountyHidden(self.machoNet):
     79             return False
     80         try:
     81             categoryID = slimItem.categoryID
     82         except AttributeError:
     83             return False
     84 
     85         if categoryID == const.categoryShip and slimItem.charID is not None:
     86             return True
     87         if categoryID == const.categoryStarbase:
     88             return True
     89         return False
     90 
     91     def QuickHasBounty(self, slimItem):
     92         if not self.CanHaveBounty(slimItem):
     93             return False
     94         for ownerID in (slimItem.charID, slimItem.corpID, slimItem.allianceID):
     95             try:
     96                 bounty = self.bounties[ownerID][0].bounty
     97             except KeyError:
     98                 bounty = 0
     99 
    100             if bounty > 0:
    101                 return True
    102 
    103         return False
    104 
    105     def QuickHasKillRight(self, slimItem):
    106         if getattr(slimItem, 'charID', None) is None:
    107             return False
    108         if self.killRightTracker.GetKillRightsFromCache(slimItem.charID):
    109             return True
    110         for killRight in self.GetMyKillRights():
    111             if killRight.fromID == session.charid and killRight.toID == slimItem.charID:
    112                 return True
    113 
    114         return False
    115 
    116     def FetchBounties(self, targetIDs):
    117         bountiesToUpdate = {targetID for targetID in targetIDs if self.IsObsolete(targetID)}
    118         self.LogInfo('FetchBounties - Got', len(bountiesToUpdate), 'that are not cached or expired')
    119         if bountiesToUpdate:
    120             bounties = [ bounty for targetID, bounty in self.GetBountiesFromServer(bountiesToUpdate) ]
    121             bountyUtil.CacheBounties(self.bounties, bounties)
    122 
    123     def IsObsolete(self, targetID, useTime = None):
    124         if useTime is None:
    125             useTime = blue.os.GetWallclockTime()
    126         try:
    127             return blue.os.GetWallclockTime() > self.bounties[targetID][1] + self.cacheTime
    128         except KeyError:
    129             return True
    130 
    131     def GetBountiesFromServer(self, targetIDs):
    132         return sm.ProxySvc('bountyProxy').GetBounties(targetIDs)
    133 
    134     def DoBallsAdded(self, slimItems, *args, **kwargs):
    135         uthread.pool('BountySvc::DoBallsAdded', self._DoBallsAdded, slimItems)
    136 
    137     def OnKillRightCreated(self, killRightID, fromID, toID, expiryTime):
    138         self.InvalidateGetMyKillRights()
    139 
    140     def OnKillRightUsed(self, killRightID, toID):
    141         try:
    142             del self.killRightTracker.killRightsByToID[toID]
    143         except KeyError:
    144             pass
    145 
    146         self.InvalidateGetMyKillRights()
    147 
    148     def OnKillRightActivated(self):
    149         prompt_player_fsd_dialog('CustomNotify', {'notify': localization.GetByLabel('UI/CharacterSheet/CharacterSheetWindow/KilLRightActivated')})
    150 
    151     def OnKillRightForYouSold(self, killRightID):
    152         self.InvalidateGetMyKillRights()
    153         sm.ScatterEvent('OnKillRightSold', killRightID)
    154 
    155     @telemetry.ZONE_METHOD
    156     def _DoBallsAdded(self, slimItems):
    157         if self.isDisabled:
    158             return
    159         ownersToQuery = set()
    160         charIDs = set()
    161         validItemIDs = set()
    162         for ball, slim in slimItems:
    163             if slim.categoryID not in (const.categoryShip, const.categoryStarbase):
    164                 continue
    165             if slim.charID is not None and idCheckers.IsOwner(slim.charID):
    166                 charIDs.add(slim.charID)
    167             if slim.corpID is not None and idCheckers.IsOwner(slim.corpID):
    168                 ownersToQuery.add(slim.corpID)
    169                 validItemIDs.add(slim.itemID)
    170             if slim.allianceID is not None and idCheckers.IsOwner(slim.allianceID):
    171                 ownersToQuery.add(slim.allianceID)
    172                 validItemIDs.add(slim.itemID)
    173 
    174         self.LogInfo('_DoBallsAdded fetching possible bounties for', len(validItemIDs), 'entities with', len(ownersToQuery), 'seperate owners')
    175         if ownersToQuery or charIDs:
    176             self.FetchBountiesAndKillRightsFromServer(charIDs, ownersToQuery)
    177             sm.ChainEvent('ProcessBountyInfoUpdated', validItemIDs)
    178 
    179     def GetTopPilotBounties(self, page = 0):
    180         return self.GetTopBounties(sm.ProxySvc('bountyProxy').GetTopPilotBounties, page)
    181 
    182     def GetTopCorpBounties(self, page = 0):
    183         return self.GetTopBounties(sm.ProxySvc('bountyProxy').GetTopCorpBounties, page)
    184 
    185     def GetTopAllianceBounties(self, page = 0):
    186         return self.GetTopBounties(sm.ProxySvc('bountyProxy').GetTopAllianceBounties, page)
    187 
    188     def GetTopBounties(self, fetcher, page):
    189         newBounties, lastFetchingTime = fetcher(page)
    190         bountiesToCache = [ bounty for bounty in newBounties if self.IsObsolete(bounty.targetID, lastFetchingTime) ]
    191         self.LogInfo('GetTopBounties::Got', len(newBounties), 'but caching', len(bountiesToCache))
    192         bountyUtil.CacheBounties(self.bounties, bountiesToCache)
    193         return sorted(newBounties, key=lambda x: x.bounty, reverse=True)
    194 
    195     def GetTopPilotBountyHunters(self, page = 0):
    196         return sm.ProxySvc('bountyProxy').GetTopPilotBountyHunters(page)[0]
    197 
    198     def GetTopCorporationBountyHunters(self, page = 0):
    199         return sm.ProxySvc('bountyProxy').GetTopCorporationBountyHunters(page)[0]
    200 
    201     def GetTopAllianceBountyHunters(self, page = 0):
    202         return sm.ProxySvc('bountyProxy').GetTopAllianceBountyHunters(page)[0]
    203 
    204     @Memoize
    205     def GetMyBounties(self):
    206         return sm.ProxySvc('bountyProxy').GetMyBounties()
    207 
    208     def GMReimburseBounties(self):
    209         sm.ProxySvc('bountyProxy').GMReimburseBounties()
    210 
    211     def GMClearBountyCache(self):
    212         objectCaching = sm.GetService('objectCaching')
    213         for entry in objectCaching.cachedMethodCalls.keys():
    214             if entry[0] == 'bountyProxy':
    215                 objectCaching.InvalidateCachedMethodCall(*entry)
    216 
    217         sm.ProxySvc('bountyProxy').GMClearBountyCache()
    218 
    219     def SearchBounties(self, targetID):
    220         if idCheckers.IsCharacter(targetID):
    221             fetcher = sm.ProxySvc('bountyProxy').SearchCharBounties
    222         elif idCheckers.IsCorporation(targetID):
    223             fetcher = sm.ProxySvc('bountyProxy').SearchCorpBounties
    224         elif idCheckers.IsAlliance(targetID):
    225             fetcher = sm.ProxySvc('bountyProxy').SearchAllianceBounties
    226         bountyAndRank = fetcher(targetID)
    227         bountyUtil.CacheBounties(self.bounties, [ bounty for rank, bounty in bountyAndRank ])
    228         return bountyAndRank
    229 
    230     def CancelSellKillRight(self, killRightID, toID):
    231         sm.ProxySvc('bountyProxy').CancelSellKillRight(killRightID, toID)
    232         self.killRightTracker.OnKillRightRemoved(toID, killRightID)
    233         self.InvalidateGetMyKillRights()
    234         sm.ScatterEvent('OnKillRightSellCancel', killRightID)
    235 
    236     def SellKillRight(self, killRightID, price, restrictedTo = None):
    237         killRights = sm.ProxySvc('bountyProxy').SellKillRight(killRightID, price, restrictedTo)
    238         if killRights is not None:
    239             for killRight in killRights:
    240                 self.killRightTracker.OnKillRightAdded(killRight)
    241 
    242         self.InvalidateGetMyKillRights()
    243 
    244     def GetMyKillRights(self):
    245         if self.myKillRights is not None:
    246             return self.myKillRights
    247         else:
    248             killRights = sm.ProxySvc('bountyProxy').GetMyKillRights()
    249             self.myKillRights = killRights
    250             return killRights
    251 
    252     def GetKillRights(self, toIDs):
    253         toIDs = [ toID for toID in toIDs if toID is not None and idCheckers.IsCharacter(toID) and idCheckers.IsOwner(toID) ]
    254         validIDs = [session.charid, session.corpid]
    255         if session.allianceid is not None:
    256             validIDs.append(session.allianceid)
    257         return self.killRightTracker.GetKillRights(toIDs, *validIDs)
    258 
    259     def FetchKillRightsFromServer(self, toIDs):
    260         self.LogInfo('Fetching', len(toIDs), 'kill rights from the server')
    261         return sm.ProxySvc('bountyProxy').GetKillRightsOnCharacters(toIDs)
    262 
    263     def FetchBountiesAndKillRightsFromServer(self, charIDs, ownerIDs):
    264         bountiesToFetch = {ownerID for ownerID in ownerIDs if self.IsObsolete(ownerID)}
    265         killRightsToFetch = self.killRightTracker.GetInvalidKillRights(charIDs)
    266         self.LogInfo('FetchBountiesAndKillRightsFromServer - fetching', len(bountiesToFetch), 'for bounties and', len(killRightsToFetch), 'for killRights')
    267         if not (bountiesToFetch or killRightsToFetch):
    268             self.LogInfo('FetchBountiesAndKillRightsFromServer - Bailing out because nothing to fetch')
    269             return
    270         myKillRights, (bounties, killRights) = uthread.parallel([(self.GetMyKillRights, ()), (sm.ProxySvc('bountyProxy').GetBountiesAndKillRights, (bountiesToFetch, killRightsToFetch))])
    271         bountyUtil.CacheBounties(self.bounties, [ bounty for targetID, bounty in bounties ])
    272         self.killRightTracker.CacheKillRights(killRights, killRightsToFetch)
    273 
    274     def ClearAllKillRightData(self):
    275         self.killRightTracker.killRightsByToID.clear()
    276         self.InvalidateGetMyKillRights()
    277 
    278     def GetBestKillRight(self, toID):
    279         for killRight in self.GetMyKillRights():
    280             if killRight.fromID == session.charid and killRight.toID == toID:
    281                 return (killRight.killRightID, None)
    282 
    283         killRights = self.GetKillRights([toID])
    284         if not killRights:
    285             return (None, None)
    286         killRight = min(killRights, key=lambda x: x.price)
    287         return (killRight.killRightID, killRight.price)
    288 
    289     def BuyKillRight(self, killRightID, toID, shipID, price):
    290         try:
    291             sm.RemoteSvc('killRightMgr').BuyKillRight(killRightID, price)
    292         except UserError as e:
    293             if e.msg in ('NoValidKillRight', 'KillRightExpired', 'KillRightNotForSale'):
    294                 self.killRightTracker.OnKillRightRemoved(toID, killRightID)
    295                 sm.ChainEvent('ProcessBountyInfoUpdated', [shipID])
    296             raise
    297 
    298     def ActivateKillRight(self, killRightID, toID, shipID):
    299         try:
    300             sm.RemoteSvc('killRightMgr').ActivateKillRight(killRightID)
    301         except UserError as e:
    302             if e.msg in ('NoValidKillRight', 'KillRightExpired'):
    303                 self.killRightTracker.OnKillRightRemoved(toID, killRightID)
    304                 self.InvalidateGetMyKillRights()
    305                 sm.ChainEvent('ProcessBountyInfoUpdated', [shipID])
    306             raise
    307 
    308     def InvalidateGetMyKillRights(self):
    309         self.myKillRights = None
    310         sm.GetService('objectCaching').InvalidateCachedMethodCall('bountyProxy', 'GetMyKillRights')