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)