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

registry.py (13499B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dbuff\common\registry.py
      2 from collections import defaultdict
      3 from .aggregators import CreateAggregator
      4 from .attribute import DynamicBuffAttribute
      5 from ccpProfile import TimedFunction
      6 from dbuff.storage import GetDbuffCollection
      7 from dbuff.common.priorityQueue import BuffPriorityQueue
      8 import gametime
      9 
     10 class BuffRegistry(object):
     11     clientNotifier = None
     12 
     13     def __init__(self, modifierApplier, clientNotifier, dbuffEventLogger):
     14         self._modifierApplier = modifierApplier
     15         self.clientNotifier = clientNotifier
     16         self.dbuffEventLogger = dbuffEventLogger
     17         self._buffPriorityQueue = BuffPriorityQueue()
     18         self._dynamicBuffs = DynamicBuffStore()
     19         self._continuousBuffSourcesByItem = {}
     20 
     21     @TimedFunction('dbuff::BuffRegistry::ApplyBuffsToItems')
     22     def ApplyBuffsToItems(self, targetItemIDs, duration, collectionValues, sourceOwnerID = None):
     23         expiryTime = gametime.GetSimTime() + int(duration)
     24         for dbuffCollectionID, dbuffValue in collectionValues.iteritems():
     25             for targetItemID in targetItemIDs:
     26                 dynamicBuff = self._GetDynamicBuffIfExists(targetItemID, dbuffCollectionID)
     27                 if dynamicBuff is None:
     28                     self._InsertNewDynamicBuff(targetItemID, dbuffCollectionID, expiryTime, dbuffValue)
     29                 else:
     30                     dynamicBuff.MergeNewTimedInput(expiryTime, dbuffValue)
     31                 self.ScheduleClientUpdate(targetItemID)
     32 
     33         if sourceOwnerID and targetItemIDs:
     34             if self.dbuffEventLogger:
     35                 self.dbuffEventLogger.LogDbuffApplied(sourceOwnerID, targetItemIDs, duration, collectionValues)
     36 
     37     @TimedFunction('dbuff::BuffRegistry::ApplyContinuousBuffsToItem')
     38     def ApplyContinuousBuffsToItem(self, itemID, collectionValues, sourceItemID = None, sourceOwnerID = None):
     39         for dbuffCollectionID, dbuffValue in collectionValues.iteritems():
     40             self._RegisterContinuousBuffAffectingItem(itemID, dbuffCollectionID, sourceItemID)
     41             dynamicBuff = self._GetDynamicBuffIfExists(itemID, dbuffCollectionID)
     42             if dynamicBuff is None:
     43                 self._InsertNewDynamicBuff(itemID, dbuffCollectionID, None, dbuffValue)
     44             else:
     45                 dynamicBuff.SetContinuousInput(dbuffValue)
     46             self.ScheduleClientUpdate(itemID)
     47 
     48         if sourceOwnerID:
     49             if self.dbuffEventLogger:
     50                 self.dbuffEventLogger.LogContinuousDbuffApplied(sourceOwnerID, itemID, collectionValues)
     51 
     52     @TimedFunction('dbuff::BuffRegistry::ClearContinuousBuffsFromItem')
     53     def ClearContinuousBuffsFromItem(self, itemID, dbuffCollectionIDs, sourceItemID = None, sourceOwnerID = None):
     54         for dbuffCollectionID in dbuffCollectionIDs:
     55             dynamicBuff = self._GetDynamicBuffIfExists(itemID, dbuffCollectionID)
     56             if dynamicBuff is not None:
     57                 if self._IsItemAffectedByContinuousBuff(itemID, dbuffCollectionID):
     58                     self._UnregisterContinuousBuffAffectingItem(itemID, dbuffCollectionID, sourceItemID)
     59                 if not self._IsItemAffectedByContinuousBuff(itemID, dbuffCollectionID):
     60                     dynamicBuff.ClearContinuousInput()
     61             self.ScheduleClientUpdate(itemID)
     62 
     63         if sourceOwnerID:
     64             if self.dbuffEventLogger:
     65                 self.dbuffEventLogger.LogContinuousDbuffCleared(sourceOwnerID, itemID, dbuffCollectionIDs)
     66 
     67     def RemoveBuffsFromItem(self, targetItemID):
     68         dynamicBuffsToRemove = self._dynamicBuffs.GetAllForTarget(targetItemID)
     69         if dynamicBuffsToRemove is not None:
     70             for dynamicBuff in dynamicBuffsToRemove:
     71                 self._modifierApplier.RemoveFromDogmaItem(dynamicBuff)
     72                 if dynamicBuff.GetNextExpiryTime() is not None:
     73                     self._buffPriorityQueue.Remove(dynamicBuff)
     74 
     75             self._dynamicBuffs.DeleteAllForTarget(targetItemID)
     76             self.ScheduleClientUpdate(targetItemID)
     77 
     78     @TimedFunction('dbuff::BuffRegistry::ProcessAllReadyBuffsInQueue')
     79     def ProcessAllReadyBuffsInQueue(self):
     80         now = gametime.GetSimTime()
     81         while self._ProcessNextReadyBuffInQueue(now):
     82             pass
     83 
     84     def _ProcessNextReadyBuffInQueue(self, now):
     85         nextBuff = self._buffPriorityQueue.PopNextReadyBuff(now)
     86         if nextBuff is None:
     87             return False
     88         nextBuff.RecalculateOutput(now)
     89         if nextBuff.IsExpired():
     90             self._Discard(nextBuff)
     91         self.ScheduleClientUpdate(nextBuff.targetItemID)
     92         return True
     93 
     94     def _InsertNewDynamicBuff(self, targetItemID, dbuffCollectionID, expiryTime, value):
     95         dynamicBuff = DynamicBuff(self._buffPriorityQueue, targetItemID, dbuffCollectionID, expiryTime, value)
     96         self._dynamicBuffs.Insert(targetItemID, dbuffCollectionID, dynamicBuff)
     97         self._modifierApplier.ApplyToDogmaItem(dynamicBuff)
     98 
     99     def _GetDynamicBuffIfExists(self, targetItemID, dbuffCollectionID):
    100         return self._dynamicBuffs.Get(targetItemID, dbuffCollectionID)
    101 
    102     def _Discard(self, dynamicBuff):
    103         self._modifierApplier.RemoveFromDogmaItem(dynamicBuff)
    104         self._dynamicBuffs.Delete(dynamicBuff.targetItemID, dynamicBuff.dbuffCollectionID)
    105 
    106     def ScheduleClientUpdate(self, itemID):
    107         if self.clientNotifier:
    108             self.clientNotifier.ScheduleClientUpdate(itemID)
    109 
    110     def GetDbuffStateForClient(self, itemID):
    111         buffs = self._dynamicBuffs.GetAllForTarget(itemID)
    112         if buffs:
    113             return [ buff.GetStateForClient() for buff in buffs ]
    114 
    115     def _RegisterContinuousBuffAffectingItem(self, itemID, dbuffCollectionID, sourceItemID):
    116         if sourceItemID is None:
    117             return
    118         if itemID not in self._continuousBuffSourcesByItem:
    119             self._continuousBuffSourcesByItem[itemID] = {}
    120         if dbuffCollectionID not in self._continuousBuffSourcesByItem[itemID]:
    121             self._continuousBuffSourcesByItem[itemID][dbuffCollectionID] = set()
    122         self._continuousBuffSourcesByItem[itemID][dbuffCollectionID].add(sourceItemID)
    123 
    124     def _IsItemAffectedByContinuousBuff(self, itemID, dbuffCollectionID):
    125         if itemID not in self._continuousBuffSourcesByItem:
    126             return False
    127         if dbuffCollectionID not in self._continuousBuffSourcesByItem[itemID]:
    128             return False
    129         return len(self._continuousBuffSourcesByItem[itemID][dbuffCollectionID]) > 0
    130 
    131     def _UnregisterContinuousBuffAffectingItem(self, itemID, dbuffCollectionID, sourceItemID):
    132         if sourceItemID is None:
    133             return
    134         self._continuousBuffSourcesByItem[itemID][dbuffCollectionID].discard(sourceItemID)
    135         if not self._IsItemAffectedByContinuousBuff(itemID, dbuffCollectionID):
    136             del self._continuousBuffSourcesByItem[itemID][dbuffCollectionID]
    137         if len(self._continuousBuffSourcesByItem[itemID]) == 0:
    138             del self._continuousBuffSourcesByItem[itemID]
    139 
    140 
    141 class DynamicBuffStore(object):
    142 
    143     def __init__(self):
    144         self._itemBuffs = defaultdict(dict)
    145 
    146     def Insert(self, targetItemID, dbuffCollectionID, dynamicBuff):
    147         self._itemBuffs[targetItemID][dbuffCollectionID] = dynamicBuff
    148 
    149     def Get(self, targetItemID, dbuffCollectionID):
    150         buffsByCollectionID = self._itemBuffs.get(targetItemID)
    151         if buffsByCollectionID is not None:
    152             return buffsByCollectionID.get(dbuffCollectionID)
    153 
    154     def GetAllForTarget(self, targetItemID):
    155         buffsByCollectionID = self._itemBuffs.get(targetItemID)
    156         if buffsByCollectionID is not None:
    157             return buffsByCollectionID.values()
    158 
    159     def Delete(self, targetItemID, dbuffCollectionID):
    160         buffsByCollectionID = self._itemBuffs.get(targetItemID)
    161         if buffsByCollectionID is not None:
    162             del buffsByCollectionID[dbuffCollectionID]
    163             if len(buffsByCollectionID) == 0:
    164                 del self._itemBuffs[targetItemID]
    165 
    166     def DeleteAllForTarget(self, targetItemID):
    167         self._itemBuffs.pop(targetItemID, None)
    168 
    169 
    170 class DynamicBuff(object):
    171     buffPriorityQueue = None
    172     targetItemID = None
    173     dbuffCollectionID = None
    174     aggregator = None
    175     dynamicBuffAttribute = None
    176 
    177     def __init__(self, buffPriorityQueue, targetItemID, dbuffCollectionID, expiryTime, outputValue):
    178         self.buffPriorityQueue = buffPriorityQueue
    179         self.targetItemID = targetItemID
    180         self.dbuffCollectionID = dbuffCollectionID
    181         self.aggregator = CreateAggregator(dbuffCollectionID, expiryTime, outputValue)
    182         self.dynamicBuffAttribute = DynamicBuffAttribute(outputValue)
    183         self._UpdatePositionInPriorityQueue()
    184 
    185     @TimedFunction('dbuff::DynamicBuff::MergeNewTimedInput')
    186     def MergeNewTimedInput(self, expiryTime, value):
    187         self.aggregator.MergeNewTimedInput(expiryTime, value)
    188         self.dynamicBuffAttribute.SetOutputValue(self.aggregator.GetCurrentOutputValue())
    189         self._UpdatePositionInPriorityQueue()
    190 
    191     @TimedFunction('dbuff::DynamicBuff::SetContinuousInput')
    192     def SetContinuousInput(self, value):
    193         self.aggregator.SetContinuousInput(value)
    194         self.dynamicBuffAttribute.SetOutputValue(self.aggregator.GetCurrentOutputValue())
    195         self._UpdatePositionInPriorityQueue()
    196 
    197     @TimedFunction('dbuff::DynamicBuff::ClearContinuousInput')
    198     def ClearContinuousInput(self):
    199         self.aggregator.ClearContinuousInput()
    200         if self.aggregator.HasInputs():
    201             self.dynamicBuffAttribute.SetOutputValue(self.aggregator.GetCurrentOutputValue())
    202         self._UpdatePositionInPriorityQueue()
    203 
    204     @TimedFunction('dbuff::DynamicBuff::RecalculateOutput')
    205     def RecalculateOutput(self, now):
    206         self.aggregator.DiscardExpiredTimedInputs(now)
    207         if self.aggregator.HasInputs():
    208             self.dynamicBuffAttribute.SetOutputValue(self.aggregator.GetCurrentOutputValue())
    209             self._UpdatePositionInPriorityQueue()
    210 
    211     def IsExpired(self):
    212         return not self.aggregator.HasInputs()
    213 
    214     def GetNextExpiryTime(self):
    215         return self.aggregator.GetNextExpiryTime()
    216 
    217     def _UpdatePositionInPriorityQueue(self):
    218         expiryTime = self.GetNextExpiryTime()
    219         if expiryTime is not None:
    220             self.buffPriorityQueue.Add(self, expiryTime)
    221 
    222     def GetStateForClient(self):
    223         return (self.dbuffCollectionID, self.aggregator.GetStateForClient())
    224 
    225 
    226 class ModifierApplier(object):
    227 
    228     def __init__(self, dogmaLM):
    229         self._AddM = dogmaLM.AddModifierWithSource
    230         self._AddLM = dogmaLM.AddLocationModifierWithSource
    231         self._AddLGM = dogmaLM.AddLocationGroupModifierWithSource
    232         self._AddLRSM = dogmaLM.AddLocationRequiredSkillModifierWithSource
    233         self._RemoveM = dogmaLM.RemoveModifierWithSource
    234         self._RemoveLM = dogmaLM.RemoveLocationModifierWithSource
    235         self._RemoveLGM = dogmaLM.RemoveLocationGroupModifierWithSource
    236         self._RemoveLRSM = dogmaLM.RemoveLocationRequiredSkillModifierWithSource
    237         self._IsItemLoaded = dogmaLM.IsItemLoaded
    238         self._IsItemUnloading = dogmaLM.IsItemUnloading
    239 
    240     @TimedFunction('dbuff::ModifierApplier::ApplyToDogmaItem')
    241     def ApplyToDogmaItem(self, dynamicBuff):
    242         targetItemID = dynamicBuff.targetItemID
    243         if not self._IsItemLoaded(targetItemID) or self._IsItemUnloading(targetItemID):
    244             return
    245         attribute = dynamicBuff.dynamicBuffAttribute
    246         dbuffCollection = GetDbuffCollection(dynamicBuff.dbuffCollectionID)
    247         operation = dbuffCollection.operation
    248         for itemMod in dbuffCollection.itemModifiers:
    249             self._AddM(operation, targetItemID, itemMod.dogmaAttributeID, attribute)
    250 
    251         for locationModifiers in dbuffCollection.locationModifiers:
    252             self._AddLM(operation, targetItemID, locationModifiers.dogmaAttributeID, attribute)
    253 
    254         for locationGroupModifier in dbuffCollection.locationGroupModifiers:
    255             self._AddLGM(operation, targetItemID, locationGroupModifier.groupID, locationGroupModifier.dogmaAttributeID, attribute)
    256 
    257         for locationRequiredSkillModifier in dbuffCollection.locationRequiredSkillModifiers:
    258             self._AddLRSM(operation, targetItemID, locationRequiredSkillModifier.skillID, locationRequiredSkillModifier.dogmaAttributeID, attribute)
    259 
    260     @TimedFunction('dbuff::ModifierApplier::RemoveFromDogmaItem')
    261     def RemoveFromDogmaItem(self, dynamicBuff):
    262         targetItemID = dynamicBuff.targetItemID
    263         if not self._IsItemLoaded(targetItemID):
    264             return
    265         attribute = dynamicBuff.dynamicBuffAttribute
    266         dbuffCollection = GetDbuffCollection(dynamicBuff.dbuffCollectionID)
    267         operation = dbuffCollection.operation
    268         for itemModifier in dbuffCollection.itemModifiers:
    269             self._RemoveM(operation, targetItemID, itemModifier.dogmaAttributeID, attribute)
    270 
    271         for locationModifiers in dbuffCollection.locationModifiers:
    272             self._RemoveLM(operation, targetItemID, locationModifiers.dogmaAttributeID, attribute)
    273 
    274         for locationGroupModifier in dbuffCollection.locationGroupModifiers:
    275             self._RemoveLGM(operation, targetItemID, locationGroupModifier.groupID, locationGroupModifier.dogmaAttributeID, attribute)
    276 
    277         for locationRequiredSkillModifier in dbuffCollection.locationRequiredSkillModifiers:
    278             self._RemoveLRSM(operation, targetItemID, locationRequiredSkillModifier.skillID, locationRequiredSkillModifier.dogmaAttributeID, attribute)