clientColony.py (8268B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\environment\planet\clientColony.py 2 from eve.common.lib import appConst 3 from eve.common.script.planet.baseColony import BaseColony 4 from eve.common.script.planet.surfacePoint import SurfacePoint 5 import eve.common.script.util.planetCommon as planetCommon 6 import blue 7 import localization 8 import evetypes 9 from eve.common.script.util.eveFormat import FmtISK 10 from eveexceptions import UserError 11 12 class ClientColony(BaseColony): 13 __name__ = 'ClientColony' 14 15 def Init(self): 16 BaseColony.Init(self) 17 self.nextTemporaryPinID = 0 18 self.nextTemporaryRouteID = 0 19 self.cumulativePinCreationCost = 0 20 self.cumulativeUpgradeCost = 0 21 22 def ResetPinCreationCost(self): 23 self.cumulativePinCreationCost = 0 24 self.cumulativeUpgradeCost = 0 25 26 def RemoveCreationCost(self, typeID): 27 self.cumulativePinCreationCost -= evetypes.GetBasePrice(typeID) 28 if self.cumulativePinCreationCost < 0: 29 self.cumulativePinCreationCost = 0 30 31 def GetTemporaryPinID(self): 32 self.nextTemporaryPinID += 1 33 return (1, self.nextTemporaryPinID) 34 35 def GetTemporaryRouteID(self): 36 self.nextTemporaryRouteID += 1 37 return (2, self.nextTemporaryRouteID) 38 39 def GetLinksAttachedToPin(self, pinID): 40 if pinID not in self.linksByPin: 41 return [] 42 return self.linksByPin[pinID] 43 44 def SetColonyData(self, newData): 45 BaseColony.SetColonyData(self, newData) 46 47 def PostValidateCreatePin(self, charID, typeID, latitude, longitude): 48 skillsSvc = sm.GetService('skills') 49 if evetypes.GetGroupID(typeID) != appConst.groupCommandPins: 50 basePrice = evetypes.GetBasePrice(typeID) 51 totalIskCost = self.cumulativePinCreationCost + basePrice 52 currentBalance = sm.GetService('wallet').GetWealth() 53 if totalIskCost > currentBalance: 54 raise UserError('CannotBuildNotEnoughCash', {'cost': FmtISK(basePrice)}) 55 self.cumulativePinCreationCost += basePrice 56 else: 57 planetRows = sm.GetService('planetSvc').GetMyPlanets() 58 if len(planetRows) > 0 and skillsSvc.GetEffectiveLevel(appConst.typeOmnipotent) is None: 59 deploymentSkillLevel = skillsSvc.GetEffectiveLevel(appConst.typeInterplanetaryConsolidation) 60 if deploymentSkillLevel is None: 61 raise UserError('CannotPlaceCommandCenterNotEnoughSkill', {'maxPlanets': 1}) 62 elif deploymentSkillLevel < len(planetRows): 63 raise UserError('CannotPlaceCommandCenterNotEnoughSkill', {'maxPlanets': len(planetRows)}) 64 requiredSkills = sm.GetService('skills').GetRequiredSkills(typeID) 65 lackingSkills = [] 66 for skillTypeID, requiredLevel in requiredSkills.iteritems(): 67 myLevel = skillsSvc.GetEffectiveLevel(skillTypeID) 68 if myLevel < requiredLevel: 69 if requiredLevel: 70 levelTxt = localization.GetByLabel('UI/PI/Common/SkillLevel', skillLevel=requiredLevel) 71 else: 72 levelTxt = '' 73 lacked = localization.GetByLabel('UI/PI/Common/SkillNameAndLevel', skillName=evetypes.GetName(skillTypeID), skillLevel=levelTxt) 74 lackingSkills.append(lacked) 75 76 if len(lackingSkills) > 0: 77 raise UserError('CannotPlacePinNotEnoughSkill', {'requiredSkills': ', '.join(lackingSkills), 78 'itemName': evetypes.GetName(typeID)}) 79 80 def PostValidateRemovePin(self, charID, pinID): 81 pin = self.GetPin(pinID) 82 typeID = pin.typeID 83 if evetypes.GetGroupID(typeID) == appConst.groupExtractorPins: 84 self.cumulativePinCreationCost -= evetypes.GetBasePrice(typeID) 85 86 def PostValidateCommandCenterUpgrade(self, level): 87 skillLevel = sm.GetService('skills').GetEffectiveLevel(appConst.typeCommandCenterUpgrade) 88 if level > skillLevel: 89 raise UserError('CantUpgradeCommandCenterSkillRequired', {'skillName': (appConst.UE_TYPEID, appConst.typeCommandCenterUpgrade), 90 'currentLevel': skillLevel, 91 'requestedLevel': level}) 92 cost = planetCommon.GetUpgradeCost(self.colonyData.level, level) 93 self.cumulativeUpgradeCost += cost 94 95 def PostValidateInstallProgram(self, pinID, typeID, headRadius): 96 pin = self.GetPin(pinID) 97 if not pin.inEditMode: 98 currentTime = blue.os.GetWallclockTime() 99 pin.CanInstallProgram(currentTime) 100 101 def ValidateAddExtractorHead(self, pinID, headID): 102 if self.colonyData is None: 103 raise RuntimeError('Unable to validate new extractor head - no colony data') 104 pin = self.GetPin(pinID) 105 if not pin: 106 raise UserError('PinDoesNotExist') 107 if not pin.IsExtractor(): 108 raise UserError('PinDoesNotHaveHeads') 109 if pin.FindHead(headID) is not None: 110 raise UserError('CannotAddHeadAlreadyExists') 111 if len(pin.heads) > planetCommon.ECU_MAX_HEADS: 112 raise UserError('CannotPlaceHeadLimitReached') 113 cpuDelta = pin.GetCpuUsage(numHeads=len(pin.heads) + 1) - pin.GetCpuUsage() 114 powerDelta = pin.GetPowerUsage(numHeads=len(pin.heads) + 1) - pin.GetPowerUsage() 115 if cpuDelta + self.colonyData.GetColonyCpuUsage() > self.colonyData.GetColonyCpuSupply(): 116 raise UserError('CannotAddToColonyCPUUsageExceeded', {'typeName': localization.GetByLabel('UI/PI/Common/ExtractorHead')}) 117 if powerDelta + self.colonyData.GetColonyPowerUsage() > self.colonyData.GetColonyPowerSupply(): 118 raise UserError('CannotAddToColonyPowerUsageExceeded', {'typeName': localization.GetByLabel('UI/PI/Common/ExtractorHead')}) 119 120 def OnPinRemoved(self, pinID): 121 BaseColony.OnPinRemoved(self, pinID) 122 123 def GetTypeAttribute(self, typeID, attributeID): 124 return sm.GetService('godma').GetTypeAttribute2(typeID, attributeID) 125 126 def Dijkstra(self, sourcePin, destinationPin): 127 D = {} 128 P = {} 129 Q = planetCommon.priority_dict() 130 Q[sourcePin] = 0.0 131 while len(Q) > 0: 132 vPin = Q.smallest() 133 D[vPin] = Q[vPin] 134 if vPin == destinationPin: 135 break 136 Q.pop_smallest() 137 for wDestinationID in self.colonyData.GetLinksForPin(vPin.id): 138 wLink = self.GetLink(vPin.id, wDestinationID) 139 wPin = self.GetPin(wDestinationID) 140 vwLength = D[vPin] + self._GetLinkWeight(wLink, wPin, vPin) 141 if wPin in D: 142 if vwLength < D[wPin]: 143 raise ValueError('Dijkstra: found better path to already-final vertex') 144 elif wPin not in Q or vwLength < Q[wPin]: 145 Q[wPin] = vwLength 146 P[wPin] = vPin 147 148 return (D, P) 149 150 def _GetLinkWeight(self, link, pinA, pinB): 151 spA = SurfacePoint(radius=1.0, theta=pinA.longitude, phi=pinA.latitude) 152 spB = SurfacePoint(radius=1.0, theta=pinB.longitude, phi=pinB.latitude) 153 return spA.GetDistanceToOther(spB) 154 155 def FindShortestPath(self, sourcePin, destinationPin): 156 if sourcePin is None or destinationPin is None: 157 return 158 if sourcePin == destinationPin: 159 return [] 160 distanceDict, predecessorDict = self.Dijkstra(sourcePin, destinationPin) 161 if destinationPin not in distanceDict or destinationPin not in predecessorDict: 162 return [] 163 path = [] 164 currentPin = destinationPin 165 while currentPin is not None: 166 path.append(currentPin.id) 167 if currentPin is sourcePin: 168 break 169 if currentPin not in predecessorDict: 170 raise RuntimeError("CurrentPin not in predecessor dict. There's no path. How did we get here?!") 171 currentPin = predecessorDict[currentPin] 172 173 path.reverse() 174 if path[0] != sourcePin.id: 175 return [] 176 return path 177 178 def FindShortestPathIDs(self, sourcePinID, destinationPinID): 179 return self.FindShortestPath(self.GetPin(sourcePinID), self.GetPin(destinationPinID))