class EntityEvents(object): __slots__ = ('_eventManager', '_debugger') def __init__(self): self._eventManager = EventManager() self._debugger = None return def _createEvent(self): return SafeEvent(self._eventManager) def _createSynchronousEvent(self): return SynchronousEvent(self._eventManager) def _createUnsafeEvent(self): return Event(self._eventManager) def _createContextEvent(self): return ContextEvent(self._eventManager) def clear(self): self._eventManager.clear() def destroy(self): self.clear() def debugEvents(self): self._debugger = EventsDebugger(self)
class TimerService(GameServiceBase): def __init__(self): super(TimerService, self).__init__() self.__manager = EventManager() self.eUpdate1Sec = Event(self.__manager) self.eUpdate = Event(self.__manager) self.__updateCallback = None self.__update1SecCallback = None return def afterLinking(self): self.__updateCallback = BigWorld.callback(0.1, self.__update) self.__update1SecCallback = BigWorld.callback(1.0, self.__update1Sec) def doLeaveWorld(self): BigWorld.cancelCallback(self.__update1SecCallback) BigWorld.cancelCallback(self.__updateCallback) def __update1Sec(self): self.eUpdate1Sec() self.__update1SecCallback = BigWorld.callback(1.0, self.__update1Sec) def __update(self): self.eUpdate() self.__updateCallback = BigWorld.callback(0.1, self.__update) def destroy(self): self.__manager.clear()
class AbstractContextMenuHandler(object): __metaclass__ = ABCMeta def __init__(self, cmProxy, ctx=None, handlers=None): self._eManager = EventManager() self.onContextMenuHide = Event(self._eManager) super(AbstractContextMenuHandler, self).__init__() self.__cmProxy = weakref.proxy(cmProxy) self.__handlers = handlers or {} self._initFlashValues(ctx) @property def app(self): return self.__cmProxy.app def fini(self): self._eManager.clear() self.__handlers = None self.__cmProxy = None self._clearFlashValues() def getOptions(self, ctx=None): return self._generateOptions(ctx) def onOptionSelect(self, optionId): if optionId in self.__handlers: return getattr(self, self.__handlers[optionId])() LOG_WARNING('Unknown context menu option', self, self.__cmProxy, optionId) def _dispatchChanges(self, options): if self.__cmProxy is not None: self.__cmProxy._onOptionsChanged(options) @classmethod def _makeItem(cls, optId, optLabel=None, optInitData=None, optSubMenu=None): return { 'id': optId, 'label': optLabel, 'initData': optInitData, 'submenu': optSubMenu } def _makeSeparator(self): return self._makeItem(_SEPARATOR_ID) @abstractmethod def _generateOptions(self, ctx=None): raise NotImplementedError def _initFlashValues(self, ctx): pass def _clearFlashValues(self): pass
class AbstractContextMenuHandler(object): __metaclass__ = ABCMeta def __init__(self, cmProxy, ctx = None, handlers = None): self._eManager = EventManager() self.onContextMenuHide = Event(self._eManager) super(AbstractContextMenuHandler, self).__init__() self.__cmProxy = weakref.proxy(cmProxy) self.__handlers = handlers or {} self._initFlashValues(ctx) @property def app(self): return self.__cmProxy.app def fini(self): self._eManager.clear() self.__handlers = None self.__cmProxy = None self._clearFlashValues() return def getOptions(self, ctx = None): return self._generateOptions(ctx) def onOptionSelect(self, optionId): if optionId in self.__handlers: return getattr(self, self.__handlers[optionId])() LOG_WARNING('Unknown context menu option', self, self.__cmProxy, optionId) def _dispatchChanges(self, options): if self.__cmProxy is not None: self.__cmProxy._onOptionsChanged(options) return @classmethod def _makeItem(cls, optId, optLabel = None, optInitData = None, optSubMenu = None): return {'id': optId, 'label': optLabel, 'initData': optInitData, 'submenu': optSubMenu} def _makeSeparator(self): return self._makeItem(_SEPARATOR_ID) @abstractmethod def _generateOptions(self, ctx = None): raise NotImplementedError def _initFlashValues(self, ctx): pass def _clearFlashValues(self): pass
class GameActionsManagerProxy(object): def __init__(self): self._entity = None self._subscription = None self._eManager = EventManager() self.eWaveAdded = Event(self._eManager) self.eWaveRemoved = Event(self._eManager) self.eWaveStateChanged = Event(self._eManager) self.eBomberStateChanged = Event(self._eManager) return @property def activeASWaves(self): if self._entity: return self._entity.activeASWaves return [] def onManagerEnterWorld(self, entity): raise not self._entity or AssertionError('Attempt to override registered manager, old = {0}, new = {1}'.format(self._entity, entity)) self._entity = entity self._subscribeOn(entity) def onManagerLeaveWorld(self, entity): raise self._entity is entity or AssertionError('Attempt to unregister unknown manager: {0}, registered: {1}'.format(entity, self._entity)) self._unsubscribe() self._entity = None return def cleanup(self): self._eManager.clear() def _subscribeOn(self, entity): raise self._subscription is None or AssertionError('Attempt to override subscription') self._subscription = CompositeSubscription(EventSubscription(entity.eWaveAdded, self.eWaveAdded), EventSubscription(entity.eWaveRemoved, self.eWaveRemoved), EventSubscription(entity.eWaveStateChanged, self.eWaveStateChanged), EventSubscription(entity.eBomberStateChanged, self.eBomberStateChanged)) self._subscription.subscribe() return def _unsubscribe(self): raise self._subscription or AssertionError('Subscription is None') self._subscription.unsubscribe() self._subscription = None return
class CalendarComponent(CalendarMeta): def __init__(self): super(CalendarComponent, self).__init__() self.__em = EventManager() self.onMonthChangedEvent = Event(self.__em) self.onDateSelectedEvent = Event(self.__em) def onMonthChanged(self, timestamp): self.onMonthChangedEvent(timestamp) def onDateSelected(self, timestamp): self.onDateSelectedEvent(timestamp) def formatYMHeader(self, rawDate): return BigWorld.wg_getYMDateFormat(rawDate) def _dispose(self): self.__em.clear() super(CalendarComponent, self)._dispose()
class BasePublishPlatform(IPublishPlatform): __slots__ = ('__eventMgr', 'onPayment', 'onOverlay') def __init__(self): super(BasePublishPlatform, self).__init__() self.__eventMgr = EventManager() self.onPayment = Event(self.__eventMgr) self.onOverlay = Event(self.__eventMgr) def init(self): pass def fini(self): self.__eventMgr.clear() def isInited(self): return False def isConnected(self): return False
class VehicleGroupBuilder(_EventsBlockBuilder): def __init__(self): super(VehicleGroupBuilder, self).__init__() self.__em = EventManager() self.onBlocksDataChanged = Event(self.__em) def init(self): super(VehicleGroupBuilder, self).init() g_currentVehicle.onChanged += self.__onVehicleChanged def clear(self): super(VehicleGroupBuilder, self).clear() g_currentVehicle.onChanged -= self.__onVehicleChanged self.__em.clear() def _getDefaultBlocks(self): return [_VehicleQuestsBlockInfo()] def __onVehicleChanged(self): self.onBlocksDataChanged()
class VehicleGroupFinder(_EventsBlockBuilder): """ Build and collect block with server events data for current vehicle tab on mission page """ def __init__(self): super(VehicleGroupFinder, self).__init__() self.__em = EventManager() self.onBlocksDataChanged = Event(self.__em) def init(self): super(VehicleGroupFinder, self).init() g_currentVehicle.onChanged += self.__onVehicleChanged def clear(self): super(VehicleGroupFinder, self).init() g_currentVehicle.onChanged -= self.__onVehicleChanged self.__em.clear() def _getDefaultBlocks(self): return [_VehicleQuestsBlockInfo()] def __onVehicleChanged(self): self.onBlocksDataChanged()
class ScaleformTutorialManager(TutorialManagerMeta): def __init__(self): super(ScaleformTutorialManager, self).__init__() self.__eventMgr = EventManager() self.onComponentFoundEvent = Event(self.__eventMgr) self.onComponentDisposedEvent = Event(self.__eventMgr) self.onTriggerActivatedEvent = Event(self.__eventMgr) self.onEffectCompletedEvent = Event(self.__eventMgr) def _dispose(self): self.__eventMgr.clear() super(ScaleformTutorialManager, self)._dispose() def onComponentFound(self, componentId, viewTutorialId): self.onComponentFoundEvent(componentId, viewTutorialId) def onTriggerActivated(self, componentId, triggerId, state): self.onTriggerActivatedEvent(componentId, triggerId, state) def onComponentDisposed(self, componentId): self.onComponentDisposedEvent(componentId) def onEffectCompleted(self, componentId, effectType): self.onEffectCompletedEvent(componentId, effectType)
class TeamObject(BigWorld.Entity, ControllerManager, CollidableObject): def __init__(self): ControllerManager.__init__(self) CollidableObject.__init__(self) self._logger = BWLogging.getLogger(self) self.filter = BigWorld.AvatarFilter() self._settings = None self.alignToGround = False self.__addedToArena = False self.__teamObjectArenaData = None self.vscriptStarted = False self.syncedRandom = SyncedRandom() return def updateLocalizedName(self): self.localizedName = localizeObject(self._settings.name) def onMapEntryCreated(self, mapEntry): pass @property def mapMatrix(self): return self.matrix def onEnterWorld(self, prereqs): self.setGameTeamIndex(self.teamIndex) self._initDBSettings() self.prepareMatrices() self.__createEvents() self._createControllers() movementStrategy = self.controllers.get('movementStrategy', None) if hasattr(self._settings, 'alignToGround'): self.alignToGround = self._settings.alignToGround if movementStrategy and movementStrategy.matrixProvider: self.filter = movementStrategy.createFilter() elif self.alignToGround: self.filter = BigWorld.AvatarDropFilter() self.filter.alignToGround = True elif self.filter.__class__ != BigWorld.PredictionFilter: self.filter = BigWorld.PredictionFilter() self.updateLocalizedName() self._checkStateSettings() self._notifyModelManipulatorOwnerChanged(self) self.controllers['modelManipulator'].updatePartsFlags(self.partFlags) self.controllers['modelManipulator'].updateStatesNet( self.partStates, True) self.eTeamIndexChanged += self.updateCompoundColour self.controllers[ 'modelManipulator'].eCompoundLoaded += self.updateCompoundColour self.updateCompoundColour() self.eOnTeamObjectEnterWorld(self) debug_observable.startObserv(self) return def _notifyModelManipulatorOwnerChanged(self, owner): modelManipulator = self.controllers.get('modelManipulator') if modelManipulator: modelManipulator.onOwnerChanged(owner) def __createEvents(self): self._eventManager = EventManager() self.ePartStateChanged = Event(self._eventManager) self.eHealthChanged = Event(self._eventManager) self.eTeamIndexChanged = Event(self._eventManager) self.eOnEntityStateChanged = Event(self._eventManager) self.eOnTeamObjectEnterWorld = Event(self._eventManager) self.eOnTeamObjectLeaveWorld = Event(self._eventManager) def _createControllers(self): controllersData = GameEnvironment.getClientArena( ).createTeamObjectControllers(self.id, self._settings, self, self.partTypes, self.partStates) modelManipulator = controllersData['modelManipulator'] self._registerController('modelManipulator', modelManipulator) self.model = modelManipulator.getRootModel() self.model.delMotor(self.model.motors[0]) self.model.addMotor(BigWorld.Servo(self.resMatrix)) modelManipulator.setMatrixProvider(self.resMatrix) turretsLogic = controllersData.get('turretsLogic', None) if turretsLogic: turretsLogic.setOwner(self) self._registerController('turretsLogic', turretsLogic) self.ePartStateChanged += turretsLogic.onPartStateChanged if self.scenarioName != '': if not self.scenarioName.endswith( '.xml') and not self.scenarioName.endswith('.plan'): scenarioData = db.DBLogic.g_instance.getScenario( self.scenarioName) if scenarioData: scenarioController = TeamObjectScenarioController( self, scenarioData) self._registerController('scenarioController', scenarioController) else: LOG_ERROR("Can't find scenario", self.scenarioName) soundController = controllersData['soundController'] self._registerController('soundController', soundController) return def isPlayer(self): return False def getSuperiorityPointsByGroupPartId(self, groupID): return getattr(self._settings, 'superiorityPointsGroup%d' % groupID, 0) def set_partFlags(self, changesData): self.controllers['modelManipulator'].updatePartsFlags(self.partFlags) self.controllers['soundController'].updatePartsFlags(self.partFlags) def setNested_partStates(self, path, value): item = self.partStates[path[0]] part = TODummyPart(self._settings.partsSettings, item[0], item[1]) self.ePartStateChanged(part) if self.__addedToArena: isDead = self.__isPartDead(part.partTypeData, item[1]) GameEnvironment.g_instance.eTOPartChanged(self.id, item[0], isDead) self.set_partStates(None) return def set_partStates(self, oldPartStates): modelManipulator = self.controllers.get('modelManipulator', None) if modelManipulator: modelManipulator.velocity = self.getWorldVector() modelManipulator.updateStatesNet(self.partStates, True) if EntityStates.inState(self, EntityStates.GAME_CONTROLLED): player = BigWorld.player() if self.lastDamagerID == player.id and self.teamIndex != player.teamIndex and self.teamIndex <= 1: for partID, partState in self.partStates: if partID == self.lastDamagedPartID: if partState >= 4: reportedIDs = player.reportedDamagedPartsByEntity.get( self.id, None) if reportedIDs: if self.lastDamagedPartID in reportedIDs and reportedIDs[ self.lastDamagedPartID] == partState: break else: reportedIDs[ self.lastDamagedPartID] = partState else: player.reportedDamagedPartsByEntity[ self.id] = { self.lastDamagedPartID: partState } break self.__collisionStateUpdate(True) if oldPartStates is not None: for partID, partState in self.partStates: GameEnvironment.g_instance.eTOPartChanged( self.id, partID, False) return def _checkStateSettings(self, transtitionActions=False): if self.inWorld: self.setGameState(self.state) self.controllers['modelManipulator'].setState( self.state, transtitionActions) if EntityStates.inState(self, EntityStates.CREATED): self.onRespawn() elif EntityStates.inState(self, EntityStates.DESTROYED): if transtitionActions: LOG_DEBUG( 'TeamObject::_checkStateSettings - For object %s set effects %s to self.position' % (self._settings.name, self._settings.damageEffects.destroy)) EffectManager.g_instance.createWorldEffect( Effects.getEffectId( self._settings.damageEffects.destroy), self.position, {}) self._clearFromArena(False) if EntityStates.inState(self, EntityStates.GAME | EntityStates.WAIT_START): self._addToArena() self.controllers['modelManipulator'].setVisible(True) self.__collisionStateUpdate(True) if EntityStates.inState(self, EntityStates.GAME) and not self.vscriptStarted: self.vscriptStarted = True BigWorld.startEntityScripts(self) if self.vscriptStarted and not EntityStates.inState( self, EntityStates.GAME): self.vscriptStarted = False BigWorld.stopEntityScripts(self) def __collisionStateUpdate(self, inWorld): needCollision = not EntityStates.inState( self, EntityStates.CREATED) and self.inWorld and inWorld if needCollision: self.startCollisionDetection() else: self.stopCollisionDetection() def onRespawn(self): LOG_TRACE('TeamObject: onRespawn', self.id) self.controllers['modelManipulator'].setVisible(False) self._clearFromArena(False) def set_state(self, oldValue): self._checkStateSettings(True) self.eOnEntityStateChanged(self.id, oldValue, self.state) def getWorldVector(self): return Math.Vector3() def getSpeed(self): return 0.0 def prepareMatrices(self): scaleMatrix = Math.Matrix() scaleMatrix.setScale( (self._settings.modelScaling, self._settings.modelScaling, self._settings.modelScaling)) self.modelTranslationsMatrix = Math.Matrix() productMatrix = Math.MatrixProduct() productMatrix.a = scaleMatrix productMatrix.b = None self.resMatrix = productMatrix self.targetMatrix = productMatrix return def setupMP(self, mp): self.resMatrix.b = mp def onLeaveWorld(self): self.eTeamIndexChanged -= self.updateCompoundColour self.controllers[ 'modelManipulator'].eCompoundLoaded -= self.updateCompoundColour self._notifyModelManipulatorOwnerChanged(None) self._eventManager.clear() self._clearFromArena(True) modelManipulator = self.controllers.get('modelManipulator', None) modelManipulator.setMatrixProvider(None) self._unregisterController('modelManipulator') turretsLogic = self.controllers.get('turretsLogic', None) if turretsLogic: turretsLogic.setOwner(None) self._unregisterController('turretsLogic') self._unregisterController('soundController') self._destroyControllers() self.model = None debug_observable.endObserv(self) self.__collisionStateUpdate(False) self.eOnTeamObjectLeaveWorld(BigWorld.player(), self.id, self) return def _addToArena(self): if not self.__addedToArena: self.__addedToArena = True GameEnvironment.g_instance.eAvatarAdded(self) def _clearFromArena(self, isLeaveWorld): if self.__addedToArena: self.__addedToArena = False GameEnvironment.g_instance.eAvatarRemoved(self, isLeaveWorld) def _directionOnCurrentEnemy(self): entity = BigWorld.entities.get(self.lastDamagerID, None) if entity: vector = entity.position - self.position vector.normalise() return vector else: return Math.Vector3(0, 1, 0) return def set_health(self, oldValue): if oldValue > self.health: GameEnvironment.g_instance.eAvatarHealthChange(self, oldValue) self.eHealthChanged(self.id, self.health, self.lastDamagerID, oldValue, self.maxHealth) def getMapTexture(self): if self._settings.turretName: return HUD_MINIMAP_ENTITY_TYPE_TURRET if self._settings.type == TYPE_TEAM_OBJECT.BIG: return HUD_MINIMAP_ENTITY_TYPE_TEAM_OBJECT_BASE return self._settings.type == TYPE_TEAM_OBJECT.TURRET and HUD_MINIMAP_ENTITY_TYPE_TURRET or HUD_MINIMAP_ENTITY_TYPE_TEAM_OBJECT def _initDBSettings(self): arenaSettings = db.DBLogic.g_instance.getArenaData( BigWorld.player().arenaType) self.__teamObjectArenaData = arenaSettings.getTeamObjectData( self.arenaObjID) if self.__teamObjectArenaData: modelStrID = self.__teamObjectArenaData['modelID'] self._settings = db.DBLogic.g_instance.getEntityDataByName( db.DBLogic.DBEntities.BASES, modelStrID) if self._settings: self.initPartsMap(self.settings.partsSettings) else: LOG_ERROR("Can't find settings for teamObject", modelStrID) else: LOG_ERROR("Can't find data for object", self.arenaObjID) @property def settings(self): return self._settings def set_isTurretFiring(self, oldValue): turretsLogic = self.controllers.get('turretsLogic', None) if turretsLogic: turretsLogic.onChangeFiring(self.isTurretFiring) return def set_turretShootSync(self, oldValue): LOG_DEBUG(' set_turretTest TO') turretsLogic = self.controllers.get('turretsLogic', None) if turretsLogic: turretsLogic.onChangeShootingSync(self.turretShootSync) return def addBullet(self, startPos, endPos, bulletSpeed, time, gun, explosionEffect, delay=0, gunID=0, dPos=None): explosionF = None if explosionEffect: explosionF = partial(onBulletExplosion, explosionEffect, startPos) shellEffect = gun.shellPath != '' if shellEffect: tm = BigWorld.time() if tm - gun.shellSyncTime < gun.shellOutInterval: shellEffect = False else: gun.shellSyncTime = tm turretShotStartPos = self.controllers['modelManipulator'].onAddBullet( gunID, delay, shellEffect) bulletId = BigWorld.addBullet( startPos if turretShotStartPos is None else turretShotStartPos, endPos, bulletSpeed, time, gun.shootInfo.bulletRenderType, BULLET_PARAM.FOREIGN, explosionF) return bulletId def addInvisibleBullet(self, startPos, endPos, bulletSpeed, time, gun, explosionEffect): if explosionEffect: explosionF = partial(onBulletExplosion, explosionEffect, startPos) return BigWorld.addBullet(startPos, endPos, bulletSpeed, time, gun.shootInfo.bulletRenderType, BULLET_PARAM.INVISIBLE, explosionF) def updateTurretsRotations(self, gunners): modelManipulator = self.controllers.get('modelManipulator', None) if modelManipulator: modelManipulator.setAxisValue(TURRET_TRACKER_AXIS, gunners) return def set_turretTargetID(self, oldData): turretsLogic = self.controllers.get('turretsLogic', None) if turretsLogic is not None: turretsLogic.eTurretTargetChanged(self.turretTargetID) soundController = self.controllers.get('soundController', None) if soundController: for gunnerId, _ in turretsLogic.gunners.iteritems(): soundController.onTurretTargetChanged(gunnerId, self.turretTargetID) return def set_timelinesTime(self, oldValue): """transfer timeLines state from Cell ScenarioControllerMaster to Client ScenarioControllerSlave""" scenarioController = self.controllers.get('scenarioController', None) if scenarioController: scenarioController.refreshTimelines(self.timelinesTime) return def set_curStrategyStartTime(self, prevValue): movementStrategy = self.controllers.get('movementStrategy', None) if movementStrategy: movementStrategy.setStartTime(self.curStrategyStartTime) return def set_curStrategyPausedAt(self, prevValue): movementStrategy = self.controllers.get('movementStrategy', None) if movementStrategy: movementStrategy.setPauseTime(self.curStrategyPausedAt) return def getDebugInfo(self): matrix = Math.Matrix(self.matrix) compoundID = self.controllers.get('modelManipulator', None).compoundID data = [('ID', self.id), ('Name', self.objectName), ('arenaObjID', self.arenaObjID), ('HP', str(self.health) + '/' + str(self.maxHealth)), ('typeName', self._settings.typeName), ('LOD', CompoundSystem.getCompoundLOD(compoundID)), ('Vis/Prim', '{0}/{1}'.format(self.model.visuals, self.model.primitives)), ('DistanceBW', (BigWorld.camera().position - Math.Matrix(self.matrix).translation).length), ('Class', self.__class__.__name__), ('Parts', '{0}|{1}'.format( len(self.partStates), ','.join([ '{0}:{1}'.format(pID, pValue) for pID, pValue in self.partStates ]))), ('State', EntityStates.getStateName(self.state)), ('YPR,S', '({0:.2},{1:.2},{2:.2}),{3:.3}'.format( math.degrees(matrix.yaw), math.degrees(matrix.pitch), math.degrees(matrix.roll), math.pow(matrix.determinant, 1.0 / 3.0))), ('ACType', SETTINGS.GROUND_OBJECT_TYPE.getName(self.areaConquestType))] if self.__teamObjectArenaData['DsName']: data.append(('DsName', self.__teamObjectArenaData['DsName'])) if self.scenarioName: timeLineData = '{0}[{1}]'.format( self.scenarioName, ','.join([ '{0}:{1}'.format( i, int(BigWorld.serverTime() - time) if time != -1 else 'N') for i, time in enumerate(self.timelinesTime) ])) data.append(('scenarioName', timeLineData)) return data def getDebugMarkerCaption(self): if not hasattr(self, 'teamIndex'): return '\\cFFFFFFCC; BAD OBJECT:\n NOT TEAM INDEX\n {id}'.format( id=self.id) healthText = '{health}/{maxHealth}'.format(health=int(self.health), maxHealth=int( self.maxHealth)) if self.teamIndex == BigWorld.player().teamIndex: return '\\c0000FFCC; Friendly ground\n {id}\n{health}'.format( id=self.id, health=healthText) elif self.teamIndex == TEAM_ID.TEAM_2: return '\\cAA9900CC; Neutral ground\n {id}\n{health}'.format( id=self.id, health=healthText) else: return '\\cFF0000CC; Enemy ground\n {id}\n{health}'.format( id=self.id, health=healthText) def useCollisionModel(self): return False def getPartsTypeData(self, pID=None, isConsiderDead=False): partsData = list() if self.settings is not None: partStates = dict(self.partStates) for partTuple in self.settings.partsSettings.getPartsList(): upgrade = None partID = partTuple[0] if pID is not None and pID != partID: continue partDB = partTuple[1] for it in self.partTypes: if it['key'] == partID: upgrade = partDB.getPartType(it['value']) break if not upgrade: upgrade = partDB.getFirstPartType() if upgrade.bboxes.list: isArmored = False for bbox in upgrade.bboxes.list: if bbox.absorption < 1: isArmored = True break partState = partStates.get(partID, 1) if partState in upgrade.states: isDead = self.__isPartDead(upgrade, partState) if not isDead or isConsiderDead: partsData.append({ 'isDead': isDead, 'partId': partID, 'isFiring': upgrade.componentType == 'Gunner', 'isArmored': isArmored }) else: LOG_WARNING( 'getPartsTypeData - partState not in states', partID, partState, upgrade.states, partStates) else: LOG_ERROR('getPartsTypeData - settings is not loaded', self.id) return partsData def useAutoAimMode(self): return TEAM_OBJECT_AUTO_AIMING_ENABLED def __isPartDead(self, upgrade, partState): return upgrade.states[partState].stateHelthCfc == 0 def isPartStateAimable(self, presentPartsMap, partID, state): return presentPartsMap[partID].states[state].stateHelthCfc > 0 def sendCustomEventToCell(self, eventName, planName, paramList): self.cell.customEventFromClient(eventName, planName, paramList) def customEventFromCell(self, eventName, planName, paramList): BigWorld.passEventToVisualScript(self, eventName, planName, paramList) def globalEventFromCell(self, eventName, channelList, paramList, aspectsList): pass def updateCompoundColour(self, *args, **kwargs): """Update compound colour based on team index. Called on enter world, on ModelManipulator3.eCompoundLoaded and on TeamObject.eTeamIndexChanged events """ self._logger.debug('updateCompoundColour: teamIndex={0}'.format( self.teamIndex)) modelManipulator = self.controllers.get('modelManipulator') if not modelManipulator: self._logger.warning( 'updateCompoundColour: modelManipulator not found') return compoundID = modelManipulator.compoundID if not CompoundSystem.isHandleValid(compoundID): self._logger.debug( 'updateCompoundColour: invalid compoundID'.format( self.teamIndex)) return if self.teamIndex == TEAM_ID.TEAM_2: pick = SETTINGS.TEAM_OBJECTS_PAINTING.NEUTRAL_INDEX else: player = BigWorld.player() if self.teamIndex == player.teamIndex: pick = SETTINGS.TEAM_OBJECTS_PAINTING.ALLY_INDEX else: pick = SETTINGS.TEAM_OBJECTS_PAINTING.ENEMY_INDEX tilesCount = SETTINGS.TEAM_OBJECTS_PAINTING.TILES_COUNT CompoundSystem.setCompoundPick(compoundID, tilesCount, pick) def set_teamIndex(self, oldValue): self.eTeamIndexChanged(self.teamIndex) self.setGameTeamIndex(self.teamIndex)
class _CachedVehicle(object): def __init__(self): self._eManager = EventManager() self.onChanged = Event(self._eManager) self.onChangeStarted = Event(self._eManager) self.__changeCallbackID = None return def init(self): self._addListeners() def destroy(self): self._eManager.clear() self._clearChangeCallback() self._removeListeners() def selectVehicle(self, vehID): raise NotImplementedError def selectNoVehicle(self): raise NotImplementedError def isPresent(self): return self.item is not None def onInventoryUpdate(self, invDiff): raise NotImplementedError def refreshModel(self): raise NotImplementedError @property def item(self): raise NotImplementedError @property def invID(self): raise NotImplementedError @property def hangarSpace(self): return _getHangarSpace() def _addListeners(self): g_clientUpdateManager.addCallbacks({'inventory': self.onInventoryUpdate}) def _removeListeners(self): g_clientUpdateManager.removeObjectCallbacks(self) def _changeDone(self): self._clearChangeCallback() if isPlayerAccount(): self.onChanged() Waiting.hide('updateCurrentVehicle') def _setChangeCallback(self): if not self.__changeCallbackID: self.__changeCallbackID = BigWorld.callback(0.2, self._changeDone) def _clearChangeCallback(self): if self.__changeCallbackID is not None: BigWorld.cancelCallback(self.__changeCallbackID) self.__changeCallbackID = None return def _selectVehicle(self, vehID): raise NotImplementedError
class _PreDefinedHostList(object): def __init__(self): super(_PreDefinedHostList, self).__init__() self._eManager = EventManager() self.onCsisQueryStart = Event(self._eManager) self.onCsisQueryComplete = Event(self._eManager) self._hosts = [] self._urlMap = {} self._nameMap = {} self._peripheryMap = {} self._isDataLoaded = False self._isCSISQueryInProgress = False self.__pingResult = {} self.__csisUrl = '' self.__csisResponse = {} self.__lastRoamingHosts = [] self.__csisCallbackID = None self.__lastCsisUpdateTime = 0 self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self.__recommended = [] self.__setPingCallback = False try: BigWorld.WGPinger.setOnPingCallback(self.__onPingPerformed) self.__setPingCallback = True except AttributeError: LOG_CURRENT_EXCEPTION() return def fini(self): self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() self._isDataLoaded = False self.__pingResult.clear() self.__csisResponse.clear() self.__csisUrl = '' self.__lastCsisUpdateTime = None self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self._eManager.clear() self.__setPingCallback = False self.__cleanCsisTimerCallback() try: BigWorld.WGPinger.clearOnPingCallback() except AttributeError: LOG_CURRENT_EXCEPTION() return @property def lastRoamingHosts(self): return self.__lastRoamingHosts def startCSISUpdate(self): if len(self.hosts()) > 1: self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__sendCsisQuery() def stopCSISUpdate(self): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__cleanCsisTimerCallback() def autoLoginQuery(self, callback): if callback is None: LOG_WARNING('Callback is not defined.') return elif self.__autoLoginQueryState != AUTO_LOGIN_QUERY_STATE.DEFAULT: LOG_WARNING('Auto login query in process.') return elif len(self._hosts) < 2: callback(self.first()) return else: peripheryID, expired = self.readPeripheryTL() if peripheryID > 0 and expired > 0: if expired > time.time(): host = self.periphery(peripheryID) if host is not None: LOG_DEBUG('Recommended host taken from cache', host) callback(host) return if len(self.__recommended): LOG_DEBUG('Gets recommended from previous query', self.__recommended) host = self.__choiceFromRecommended() LOG_DEBUG('Recommended host', host) callback(host) return self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.START self.__queryCallback = callback self.__ping() self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__sendCsisQuery() return def resetQueryResult(self): self.__recommended = [] self.__pingResult.clear() def savePeripheryTL(self, peripheryID, delta = STORED_AS_RECOMMEND_DELTA): if not AUTO_LOGIN_QUERY_ENABLED or not peripheryID: return else: try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: value = base64.b64encode(pickle.dumps((peripheryID, time.time() + delta))) loginSec.writeString('peripheryLifeTime', value) Settings.g_instance.save() except Exception: LOG_CURRENT_EXCEPTION() return def readPeripheryTL(self): if not AUTO_LOGIN_QUERY_ENABLED: return (0, 0) else: result = (0, 0) try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: value = loginSec.readString('peripheryLifeTime') if len(value): value = pickle.loads(base64.b64decode(value)) if len(value) > 1: result = value except Exception: result = ('', 0) LOG_CURRENT_EXCEPTION() return result def clearPeripheryTL(self): if not AUTO_LOGIN_QUERY_ENABLED: return else: try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: loginSec.writeString('peripheryLifeTime', '') Settings.g_instance.save() except Exception: LOG_CURRENT_EXCEPTION() return def readScriptConfig(self, dataSection): if self._isDataLoaded or dataSection is None: return else: self.__csisUrl = dataSection.readString('csisUrl') self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() loginSection = dataSection['login'] if loginSection is None: return for name, subSec in loginSection.items(): name = subSec.readString('name') shortName = subSec.readString('short_name') urls = _LoginAppUrlIterator(subSec.readStrings('url')) host = urls.primary if host is not None: if not len(name): name = host keyPath = subSec.readString('public_key_path') if not len(keyPath): keyPath = None areaID = subSec.readString('game_area_id') if not len(areaID): areaID = None app = self._makeHostItem(name, shortName, host, urlToken=subSec.readString('url_token'), urlIterator=urls if len(urls) > 1 else None, keyPath=keyPath, areaID=areaID, peripheryID=subSec.readInt('periphery_id', 0)) idx = len(self._hosts) url = app.url if url in self._urlMap: LOG_ERROR('Host url is already added. This host is ignored', url) continue self._urlMap[url] = idx urlToken = app.urlToken if len(urlToken): if urlToken in self._urlMap: LOG_ERROR('Alternative host url is already added. This url is ignored', app.url) else: self._urlMap[urlToken] = idx self._nameMap[app.name] = idx if app.peripheryID: self._peripheryMap[app.peripheryID] = idx self._hosts.append(app) self._isDataLoaded = True return def predefined(self, url): return url in self._urlMap def roaming(self, url): return url in [ p.url for p in self.roamingHosts() ] def first(self): if len(self._hosts): return self._hosts[0] return self._makeHostItem('', '', '') def byUrl(self, url): result = self._makeHostItem('', '', url) index = self._urlMap.get(url, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.url == url: result = host return result def byName(self, name): result = self._makeHostItem(name, '', '') index = self._nameMap.get(name, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.name == name: result = host return result def hosts(self): return self._hosts[:] def shortList(self): result = self.getSimpleHostsList(self._hosts) if AUTO_LOGIN_QUERY_ENABLED and len(result) > 1 and len(self.peripheries()) > 1: result.insert(0, (AUTO_LOGIN_QUERY_URL, i18n.makeString('#menu:login/auto'), HOST_AVAILABILITY.IGNORED, None)) return result def getSimpleHostsList(self, hosts): result = [] defAvail = HOST_AVAILABILITY.getDefault() predefined = tuple((host.url for host in self.peripheries())) isInProgress = self._isCSISQueryInProgress csisResGetter = self.__csisResponse.get for item in hosts: if item.url not in predefined: status = HOST_AVAILABILITY.IGNORED else: status = defAvail if isInProgress else csisResGetter(item.peripheryID, defAvail) result.append((item.url, item.name, status, item.peripheryID)) return result def urlIterator(self, primary): result = None index = self._urlMap.get(primary, -1) if index > -1: result = self._hosts[index].urlIterator return result def periphery(self, peripheryID): if peripheryID in self._peripheryMap: index = self._peripheryMap[peripheryID] return self._hosts[index] else: roamingHosts = dict(((host.peripheryID, host) for host in self.roamingHosts())) if peripheryID in roamingHosts: return roamingHosts[peripheryID] return None def peripheries(self): return filter(lambda app: app.peripheryID, self._hosts) def roamingHosts(self): p = BigWorld.player() result = [] if hasattr(p, 'serverSettings'): for peripheryID, name, shortName, host, keyPath in p.serverSettings['roaming'][3]: result.append(self._makeHostItem(name, shortName, host, keyPath=keyPath, peripheryID=peripheryID)) self.__lastRoamingHosts = sorted(result, key=operator.itemgetter(0)) return self.__lastRoamingHosts def hostsWithRoaming(self): predefined = tuple((host.url for host in self.peripheries())) hosts = self.peripheries() for h in self.roamingHosts(): if h.url not in predefined: hosts.append(h) return hosts def isRoamingPeriphery(self, peripheryID): return peripheryID not in [ p.peripheryID for p in self.peripheries() ] def _makeHostItem(self, name, shortName, url, urlToken = '', urlIterator = None, keyPath = None, areaID = None, peripheryID = 0): if not len(shortName): shortName = name return _HostItem(name, shortName, url, urlToken, urlIterator, keyPath, areaID, peripheryID) def _determineRecommendHost(self): defAvail = HOST_AVAILABILITY.NOT_AVAILABLE pResGetter = self.__pingResult.get csisResGetter = self.__csisResponse.get queryResult = map(lambda host: (host, pResGetter(host.url, -1), csisResGetter(host.peripheryID, defAvail)), self.peripheries()) self.__recommended = filter(lambda item: item[2] == HOST_AVAILABILITY.RECOMMENDED, queryResult) if not len(self.__recommended): self.__recommended = filter(lambda item: item[2] == HOST_AVAILABILITY.NOT_RECOMMENDED, queryResult) recommendLen = len(self.__recommended) if not recommendLen: if len(queryResult) > 1: LOG_DEBUG('List of recommended is empty. Gets host by ping') self.__recommended = self.__filterRecommendedByPing(queryResult) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() else: LOG_DEBUG('Gets first as recommended') result = self.first() else: LOG_DEBUG('Recommended by CSIS', self.__recommended) if recommendLen > 1: self.__recommended = self.__filterRecommendedByPing(self.__recommended) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() return result def __ping(self): if not self.__setPingCallback: self.__onPingPerformed([]) return try: peripheries = map(lambda host: host.url, self.peripheries()) LOG_DEBUG('Ping starting', peripheries) BigWorld.WGPinger.ping(peripheries) except (AttributeError, TypeError): LOG_CURRENT_EXCEPTION() self.__onPingPerformed([]) def __onPingPerformed(self, result): LOG_DEBUG('Ping performed', result) try: self.__pingResult = dict(result) self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.PING_PERFORMED) except Exception: LOG_CURRENT_EXCEPTION() self.__pingResult = {} def __startCsisTimer(self): self.__cleanCsisTimerCallback() self.__csisCallbackID = BigWorld.callback(CSIS_REQUEST_TIMER, self.__onCsisTimer) def __cleanCsisTimerCallback(self): if self.__csisCallbackID: BigWorld.cancelCallback(self.__csisCallbackID) self.__csisCallbackID = None return def __onCsisTimer(self): self.__csisCallbackID = None self.__sendCsisQuery() return def __sendCsisQuery(self): if len(self.__csisUrl): if not self._isCSISQueryInProgress: timeFromLastUpdate = time.time() - self.__lastCsisUpdateTime if timeFromLastUpdate >= CSIS_REQUEST_TIMER: self._isCSISQueryInProgress = True self.onCsisQueryStart() allHosts = self.hosts() peripheries = map(lambda host: host.peripheryID, allHosts) LOG_DEBUG('CSIS query sending', peripheries) _CSISRequestWorker(self.__csisUrl, self.__receiveCsisResponse, peripheries).start() else: self.__finishCsisQuery() else: LOG_DEBUG('CSIS url is not defined - ignore') self._isCSISQueryInProgress = False self.stopCSISUpdate() self.__finishCsisQuery() self.__lastCsisUpdateTime = 0 def __receiveCsisResponse(self, response): LOG_DEBUG('CSIS query received', response) self._isCSISQueryInProgress = False self.__csisResponse = response self.__lastCsisUpdateTime = time.time() self.__finishCsisQuery() def __finishCsisQuery(self): if self.__csisAction & CSIS_ACTION.AUTO_LOGIN_REQUEST: self.__receiveAutoLoginCSISResponse(self.__csisResponse) if self.__csisAction & CSIS_ACTION.UPDATE_ON_TIME: self.__startCsisTimer() self.onCsisQueryComplete(self.__csisResponse) def __receiveAutoLoginCSISResponse(self, response): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.CSIS_RESPONSE_RECEIVED) def __autoLoginQueryCompleted(self, state): if not self.__autoLoginQueryState & state: self.__autoLoginQueryState |= state if self.__autoLoginQueryState == AUTO_LOGIN_QUERY_STATE.COMPLETED: host = self._determineRecommendHost() LOG_DEBUG('Recommended host', host) self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__queryCallback(host) self.__queryCallback = None return def __filterRecommendedByPing(self, recommended): result = recommended filtered = filter(lambda item: item[1] > -1, recommended) if len(filtered): minPingTime = min(filtered, key=lambda item: item[1])[1] maxPingTime = 1.2 * minPingTime result = filter(lambda item: item[1] < maxPingTime, filtered) return result def __choiceFromRecommended(self): recommended = random.choice(self.__recommended) self.__recommended = filter(lambda item: item != recommended, self.__recommended) return recommended[0]
class QuestProgressController(IArenaPeriodController, IArenaVehiclesController): eventsCache = dependency.descriptor(IEventsCache) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(QuestProgressController, self).__init__() self._period = ARENA_PERIOD.IDLE self._endTime = 0 self._length = 0 self._callbackID = None self.__storage = {} self.__selectedQuest = None self.__eManager = EventManager() self.__battleCtx = None self.__isInited = False self.__inProgressQuests = {} self.__needToShowAnimation = False self.onConditionProgressUpdate = Event(self.__eManager) self.onHeaderProgressesUpdate = Event(self.__eManager) self.onFullConditionsUpdate = Event(self.__eManager) self.onQuestProgressInited = Event(self.__eManager) self.onShowAnimation = Event(self.__eManager) self.__lastSelectedQuestID = 0 return def getInProgressQuests(self): return self.__inProgressQuests def hasQuestsToPerform(self): return bool(self.__inProgressQuests) def getSelectedQuest(self): return self.__selectedQuest def isInited(self): return self.__isInited def selectQuest(self, missionID): self.__selectedQuest = self.__inProgressQuests.get(missionID) AccountSettings.setSettings(LAST_SELECTED_PM_BRANCH, self.__selectedQuest.getPMType().branch) if self.__selectedQuest: self.__needToShowAnimation = self.__lastSelectedQuestID != self.__selectedQuest.getID() self.onFullConditionsUpdate() def invalidateArenaInfo(self): isPersonalMissionsEnabled = self.lobbyContext.getServerSettings().isPersonalMissionsEnabled if not self.__isInited: lastSelectedBranch = AccountSettings.getSettings(LAST_SELECTED_PM_BRANCH) personalMissions = self.eventsCache.getPersonalMissions() selectedMissionsIDs = self.__battleCtx.getSelectedQuestIDs() selectedMissionsInfo = self.__battleCtx.getSelectedQuestInfo() or {} if selectedMissionsIDs: missions = personalMissions.getAllQuests() for missionID in selectedMissionsIDs: mission = missions.get(missionID) if mission and not mission.isDisabled() and isPersonalMissionsEnabled(mission.getQuestBranch()): pqState = selectedMissionsInfo.get(missionID, (0, PM_STATE.NONE))[1] mission.updatePqStateInBattle(pqState) self.__inProgressQuests[missionID] = mission generalQuestID = mission.getGeneralQuestID() if mission.getPMType().branch == lastSelectedBranch: self.__selectedQuest = mission self.__storage[generalQuestID] = BattleProgressStorage(generalQuestID, mission.getConditionsConfig(), mission.getConditionsProgress(), mission.isOneBattleQuest()) if self.__selectedQuest is None: self.__selectedQuest = first(self.__inProgressQuests.itervalues()) self.__updateTimerConditions(sendDiff=False) self.__isInited = True if self.__selectedQuest: self.__lastSelectedQuestID = self.__selectedQuest.getID() self.onQuestProgressInited() return def startControl(self, battleCtx, arenaVisitor): self.__battleCtx = battleCtx def areQuestsEnabledForArena(self): return self.__battleCtx.areQuestsEnabledForArena() def stopControl(self): self._period = ARENA_PERIOD.IDLE self._endTime = 0 self._length = 0 self.__selectedQuest = None self.__battleCtx = None self.__storage.clear() self.__eManager.clear() self.__clearCallback() self.__inProgressQuests.clear() self.__isInited = False return def setPeriodInfo(self, period, endTime, length, additionalInfo): self.__updatePeriodInfo(period, endTime, length) def invalidatePeriodInfo(self, period, endTime, length, additionalInfo): self.__updatePeriodInfo(period, endTime, length) def getQuestFullData(self): selectedQuest = self.__selectedQuest if selectedQuest: formatter = self.__getFormatter(selectedQuest) return {'questName': selectedQuest.getUserName(), 'questID': selectedQuest.getID(), 'questIndexStr': str(selectedQuest.getInternalID()), 'questIcon': RES_ICONS.getAllianceGoldIcon(selectedQuest.getMajorTag()), 'headerProgress': formatter.headerFormat(), 'bodyProgress': formatter.bodyFormat()} return {} def getQuestShortInfoData(self): selectedQuest = self.__selectedQuest return {'questName': selectedQuest.getUserName(), 'questIndexStr': str(selectedQuest.getInternalID()), 'questIcon': RES_ICONS.getAllianceGoldIcon(selectedQuest.getMajorTag())} if selectedQuest else {} def getQuestHeaderProgresses(self): formatter = self.__getFormatter(self.__selectedQuest) return formatter.headerFormat() def updateQuestProgress(self, questID, info): if questID in self.__storage: self.__storage[questID].update(info) else: _logger.error('Storage for quest:%s is not found.', questID) selectedQuest = self.__selectedQuest if selectedQuest is not None: storage = self.__storage[selectedQuest.getGeneralQuestID()] needHeaderResync = False for headerProgress in storage.getHeaderProgresses().itervalues(): if headerProgress.isChanged(): needHeaderResync = True headerProgress.markAsVisited() if needHeaderResync: self.onHeaderProgressesUpdate() for progressID, condProgress in storage.getChangedConditions().iteritems(): condProgress.markAsVisited() self.onConditionProgressUpdate(progressID, condProgress.getProgress()) return def getControllerID(self): return BATTLE_CTRL_ID.QUEST_PROGRESS def getCtrlScope(self): return _SCOPE.PERIOD | _SCOPE.VEHICLES def showQuestProgressAnimation(self): if self.__needToShowAnimation: self.onShowAnimation() self.__needToShowAnimation = False if self.__selectedQuest: self.__lastSelectedQuestID = self.__selectedQuest.getID() def __updatePeriodInfo(self, period, endTime, length): self._period = period self._endTime = endTime self._length = length self.__clearCallback() if self._period == ARENA_PERIOD.BATTLE: self.__setCallback() def __setCallback(self): self._callbackID = None battleEndLeftTime = self._endTime - BigWorld.serverTime() tickInterval = 1 if battleEndLeftTime > 1 else 0 self.__updateTimerConditions() self._callbackID = BigWorld.callback(tickInterval, self.__setCallback) return def __clearCallback(self): if self._callbackID is not None: BigWorld.cancelCallback(self._callbackID) self._callbackID = None return def __updateTimerConditions(self, sendDiff=True): selectedQuest = self.__selectedQuest if self._period == ARENA_PERIOD.BATTLE and selectedQuest: startTime = self._endTime - self._length timesGoneFromStart = BigWorld.serverTime() - startTime timerConditions = self.__storage[selectedQuest.getGeneralQuestID()].getTimerConditions() for progressID, condProgress in timerConditions.iteritems(): secondsLeft = max(condProgress.getCountDown() - timesGoneFromStart, 0) isChanged = condProgress.setTimeLeft(secondsLeft) if isChanged and sendDiff: self.onConditionProgressUpdate(progressID, condProgress.getProgress()) def __getFormatter(self, selectedQuest): return DetailedProgressFormatter(self.__storage.get(selectedQuest.getGeneralQuestID()), selectedQuest)
class BuyBoosterMeta(I18nConfirmDialogMeta): goodiesCache = dependency.descriptor(IGoodiesCache) def __init__(self, boosterID, balance): super(BuyBoosterMeta, self).__init__('buyConfirmation', scope=ScopeTemplates.LOBBY_SUB_SCOPE) self.__booster = self.goodiesCache.getBooster(boosterID) self.__balance = balance self._eManager = EventManager() self.onInvalidate = Event(self._eManager) g_clientUpdateManager.addCallbacks({'stats': self.__onStatsChanged}) self.__boosterBuyPricesSum = self.__booster.buyPrices.getSum() def getEventType(self): return events.ShowDialogEvent.SHOW_CONFIRM_BOOSTER def getBoosterID(self): return self.__booster.boosterID def getBooster(self): return self.__booster def destroy(self): self.__booster = None self.__balance = None self._eManager.clear() g_clientUpdateManager.removeObjectCallbacks(self) return def getMaxAvailableItemsCount(self): """ Returns tuple that contains max counts of booster that the user can buy for the current balance. Currency index in the tuple corresponds to the default order (see Currency.ALL). :return: CurrencyCollection(namedtuple) """ buyPrice = self.__boosterBuyPricesSum.price return CurrencyCollection(*(self.__getMaxCount(buyPrice, currency) for currency in Currency.ALL)) def getActionVO(self): if self.__boosterBuyPricesSum.isActionPrice(): return packActionTooltipData(ACTION_TOOLTIPS_TYPE.BOOSTER, str(self.__booster.boosterID), True, self.__boosterBuyPricesSum.price, self.__boosterBuyPricesSum.defPrice) else: return None def getCurrency(self): """ Returns the original buy currency, see Currency enum. :return: string """ return self.__booster.getBuyPrice(preferred=True).getCurrency( byWeight=True) def getPrices(self): """ Returns all set currencies(prices) for buying the booster. Right now booster's price can be defined only in one currency (in the same time any booster can have an alternative price). So sum the original and the alternative price to have all set currencies in one place. Note that such logic will not work with compound prices (multi-currency price). :return: ItemPrices """ return self.__booster.buyPrices @process('buyItem') def submit(self, count, currency): result = yield BoosterBuyer(self.__booster, count, currency).request() if len(result.userMsg): SystemMessages.pushI18nMessage(result.userMsg, type=result.sysMsgType) def __onStatsChanged(self, stats): newValues = Money.extractMoneyDict(stats) if newValues: self.__balance = self.__balance.replaceAll(newValues) self.onInvalidate() def __getMaxCount(self, boosterPrice, currency): result = 0 if boosterPrice.get(currency, 0) > 0: result = math.floor( self.__balance.get(currency, 0) / boosterPrice.get(currency)) return min(result, MAX_BOOSTERS_FOR_OPERATION)
class RefSystem(IRefSystemController): eventsCache = dependency.descriptor(IEventsCache) def __init__(self): super(RefSystem, self).__init__() self.__referrers = [] self.__referrals = [] self.__quests = [] self.__xpPoolOfDeletedRals = 0 self.__totalXP = 0 self.__isTotallyCompleted = False self.__posByXPinTeam = 0 self.__eventMgr = EventManager() self.onUpdated = Event(self.__eventMgr) self.onQuestsUpdated = Event(self.__eventMgr) self.onPlayerBecomeReferrer = Event(self.__eventMgr) self.onPlayerBecomeReferral = Event(self.__eventMgr) @storage_getter('users') def usersStorage(self): return None def fini(self): self.__referrers = None self.__referrals = None self.__eventMgr.clear() self.__clearQuestsData() super(RefSystem, self).fini() return def onLobbyStarted(self, ctx): g_clientUpdateManager.addCallbacks({'stats.refSystem': self.__onRefStatsUpdated}) self.eventsCache.onSyncCompleted += self.__onEventsUpdated g_playerEvents.onShopResync += self.__onShopUpdated self.__update(g_itemsCache.items.stats.refSystem) self.__updateQuests() def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def getReferrers(self): return self.__referrers def getReferrals(self): return self.__referrals def getQuests(self): return self.__quests def isTotallyCompleted(self): return self.__isTotallyCompleted def getPosByXPinTeam(self): return self.__posByXPinTeam def getTotalXP(self): return self.__totalXP def getReferralsXPPool(self): result = self.__xpPoolOfDeletedRals for i in self.getReferrals(): result += i.getXPPool() return result def getAvailableReferralsCount(self): return _getMaxNumberOfReferrals() - len(self.__referrals) def showTankmanAwardWindow(self, tankman, completedQuestIDs): LOG_DEBUG('Referrer has been get tankman award', tankman, completedQuestIDs) curXp, nextXp, _ = self.__getAwardParams(completedQuestIDs) shared_events.showAwardWindow(TankmanAward(tankman, curXp, nextXp)) def showVehicleAwardWindow(self, vehicle, completedQuestIDs): LOG_DEBUG('Referrer has been get vehicle award', vehicle, completedQuestIDs) curXp, nextXp, isBoughtVehicle = self.__getAwardParams(completedQuestIDs) shared_events.showAwardWindow(VehicleAward(vehicle, isBoughtVehicle, curXp)) def showCreditsAwardWindow(self, creditsValue, completedQuestIDs): if creditsValue > 0: LOG_DEBUG('Referrer has been get credits award', creditsValue, completedQuestIDs) shared_events.showAwardWindow(CreditsAward(creditsValue)) @classmethod def getRefPeriods(cls): return _getRefSystemPeriods() @classmethod def getMaxReferralXPPool(cls): return _getMaxReferralXPPool() @classmethod def getMaxNumberOfReferrals(cls): return _getMaxNumberOfReferrals() @classmethod def isReferrer(cls): refSystemStats = g_itemsCache.items.stats.refSystem return refSystemStats.get('activeInvitations', 0) > 0 or len(refSystemStats.get('referrals', {})) > 0 def showReferrerIntroWindow(self, invitesCount): g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.REFERRAL_REFERRER_INTRO_WINDOW, ctx={'invitesCount': invitesCount}), EVENT_BUS_SCOPE.LOBBY) self.onPlayerBecomeReferrer() def showReferralIntroWindow(self, nickname, isNewbie = False): g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.REFERRAL_REFERRALS_INTRO_WINDOW, ctx={'referrerName': nickname, 'newbie': isNewbie}), EVENT_BUS_SCOPE.LOBBY) self.onPlayerBecomeReferral() def __stop(self): g_playerEvents.onShopResync -= self.__onShopUpdated self.eventsCache.onSyncCompleted -= self.__onEventsUpdated g_clientUpdateManager.removeObjectCallbacks(self) def __getAwardParams(self, completedQuestIDs): completedQuestID = completedQuestIDs.pop() if len(completedQuestIDs) else -1 currentXP = nextXP = None for xp, quests in reversed(self.getQuests()): if completedQuestID in map(methodcaller('getID'), quests): currentXP = xp break else: nextXP = xp return (currentXP, nextXP, self.getReferralsXPPool() < self.getTotalXP()) def __clearQuestsData(self): self.__quests = [] self.__isTotallyCompleted = False self.__totalXP = 0 def __update(self, data): self.__referrers = [] self.__referrals = [] self.__xpPoolOfDeletedRals = 0 self.__posByXPinTeam = g_itemsCache.items.shop.refSystem['posByXPinTeam'] storage = self.usersStorage userGetter = storage.getUser userSetter = storage.addUser storage.removeTags({USER_TAG.REFERRER, USER_TAG.REFERRAL}) def updateUser(item, tags): dbID = item.getAccountDBID() user = userGetter(dbID) if user: user.addTags(tags) if USER_TAG.INVALID_NAME in user.getTags(): user.update(name=item.getNickName()) else: userSetter(SharedUserEntity(dbID, name=item.getNickName(), tags=tags, clanInfo=ClanInfo(abbrev=item.getClanAbbrev()))) for referrer in self.__buildReferrers(data): self.__referrers.append(referrer) updateUser(referrer, {USER_TAG.REFERRER}) for referral in self.__buildReferrals(data): self.__referrals.append(referral) updateUser(referral, {USER_TAG.REFERRAL}) self.onUpdated() g_messengerEvents.users.onUsersListReceived({USER_TAG.REFERRER, USER_TAG.REFERRAL}) @classmethod def __makeRefItem(cls, dbID, **data): try: return _RefItem(dbID, **data) except: LOG_ERROR('There is error while building ref system item') LOG_CURRENT_EXCEPTION() def __buildReferrers(self, data): for key, item in (data.get('referrers') or {}).iteritems(): referrer = self.__makeRefItem(key, **item) if referrer is not None: yield referrer return def __buildReferrals(self, data): for key, item in (data.get('referrals') or {}).iteritems(): if key == 'xpPoolOfDeletedRals': self.__xpPoolOfDeletedRals = item else: referral = self.__makeRefItem(key, **item) if referral is not None: yield referral return def __updateQuests(self): self.__clearQuestsData() refSystemQuests = self.eventsCache.getHiddenQuests(lambda x: x.getType() == EVENT_TYPE.REF_SYSTEM_QUEST) if refSystemQuests: self.__quests = self.__mapQuests(refSystemQuests.values()) self.__totalXP, _ = self.__quests[-1] notCompleted = findFirst(lambda q: not q.isCompleted(), refSystemQuests.values()) self.__isTotallyCompleted = notCompleted is None self.onQuestsUpdated() return @classmethod def __mapQuests(cls, events): result = defaultdict(list) for event in sorted(events, key=methodcaller('getID')): result[event.accountReqs.getConditions().find('refSystemRalXPPool').getValue()].append(event) return sorted(result.iteritems(), key=itemgetter(0)) def __onRefStatsUpdated(self, diff): self.__update(g_itemsCache.items.stats.refSystem) def __onEventsUpdated(self): self.__updateQuests() def __onShopUpdated(self): self.__update(g_itemsCache.items.stats.refSystem) self.__updateQuests()
class DisposableEntity(object): def __init__(self): super(DisposableEntity, self).__init__() self.__eManager = EventManager() self.onCreate = Event(self.__eManager) self.onCreated = Event(self.__eManager) self.onDispose = Event(self.__eManager) self.onDisposed = Event(self.__eManager) self.__lcState = EntityState.UNDEFINED self.__postponedState = EntityState.UNDEFINED def getState(self): return self.__lcState def create(self): if self.__lcState in (EntityState.UNDEFINED, EntityState.DISPOSED): self.__changeStateTo(EntityState.CREATING) self.onCreate(self) self._populate() self.__changeStateTo(EntityState.CREATED) self.onCreated(self) self.__invalidatePostponedState() elif self.__lcState == EntityState.DISPOSING: LOG_DEBUG( 'Create call is postponed for {} object. Disposing is in progress.' .format(self)) self.__postponedState = EntityState.CREATING else: LOG_DEBUG('Entity {} is already created! Current state {}.'.format( self, self.__lcState)) def validate(self, *args, **kwargs): if self.__lcState == EntityState.CREATED: self.__changeStateTo(EntityState.CREATING) self._invalidate(*args, **kwargs) self.__changeStateTo(EntityState.CREATED) self.__invalidatePostponedState() elif self.__lcState in (EntityState.UNDEFINED, EntityState.DISPOSING, EntityState.DISPOSED): LOG_DEBUG( 'Invalidate call is skipped because object {} is destroyed or has not been created yet. Current state {}.' .format(self, self.__lcState)) else: LOG_DEBUG( 'Invalidate call is skipped because initialization of object {} is in progress.' .format(self)) def destroy(self): if self.__lcState in (EntityState.UNDEFINED, EntityState.CREATED): needToBeDisposed = self.__lcState == EntityState.CREATED self.__changeStateTo(EntityState.DISPOSING) self.onDispose(self) if needToBeDisposed: self._dispose() self._destroy() self.__changeStateTo(EntityState.DISPOSED) self.onDisposed(self) self.__eManager.clear() self.__invalidatePostponedState() elif self.__lcState == EntityState.CREATING: LOG_DEBUG( 'Destroy call is postponed for {} object. Initialization is in progress' .format(self)) self.__postponedState = EntityState.DISPOSING else: LOG_DEBUG( 'Entity {} is already destroyed! Current state {}.'.format( self, self.__lcState)) def isDisposed(self): return self.__lcState in (EntityState.DISPOSING, EntityState.DISPOSED) def isCreated(self): return self.__lcState in (EntityState.CREATING, EntityState.CREATED) def _populate(self): pass def _invalidate(self, *args, **kwargs): pass def _dispose(self): pass def _destroy(self): pass def __changeStateTo(self, state): self.__lcState = state def __invalidatePostponedState(self): if self.__postponedState in (EntityState.DISPOSING, EntityState.DISPOSED): LOG_DEBUG('Call postponed destroy call for {}'.format(self)) self.destroy() elif self.__postponedState in (EntityState.CREATING, EntityState.CREATED): LOG_DEBUG('Call postponed create call for {}'.format(self)) self.create() self.__postponedState = EntityState.UNDEFINED
class _EventsCache(object): USER_QUESTS = (EVENT_TYPE.BATTLE_QUEST, EVENT_TYPE.TOKEN_QUEST, EVENT_TYPE.FORT_QUEST, EVENT_TYPE.PERSONAL_QUEST, EVENT_TYPE.POTAPOV_QUEST) SYSTEM_QUESTS = (EVENT_TYPE.REF_SYSTEM_QUEST,) def __init__(self): self.__waitForSync = False self.__invalidateCbID = None self.__cache = defaultdict(dict) self.__potapovHidden = {} self.__actionsCache = defaultdict(lambda : defaultdict(dict)) self.__questsDossierBonuses = defaultdict(set) self.__random = RandomPQController() self.__fallout = FalloutPQController() self.__potapovComposer = _PotapovComposer(self.__random, self.__fallout) self.__questsProgress = QuestsProgressRequester() self.__companies = CompanyBattleController(self) self.__em = EventManager() self.onSyncStarted = Event(self.__em) self.onSyncCompleted = Event(self.__em) self.onSelectedQuestsChanged = Event(self.__em) self.onSlotsCountChanged = Event(self.__em) self.onProgressUpdated = Event(self.__em) return def init(self): self.__random.init() self.__fallout.init() def fini(self): self.__fallout.fini() self.__random.fini() self.__em.clear() self.__clearInvalidateCallback() def start(self): self.__companies.start() def stop(self): self.__companies.stop() def clear(self): self.stop() quests_caches.clearNavInfo() @property def waitForSync(self): return self.__waitForSync @property def falloutQuestsProgress(self): return self.__fallout.questsProgress @property def randomQuestsProgress(self): return self.__random.questsProgress @property def random(self): return self.__random @property def fallout(self): return self.__fallout @property def questsProgress(self): return self.__questsProgress @property def potapov(self): return self.__potapovComposer @property def companies(self): return self.__companies @async @process def update(self, diff = None, callback = None): if diff is not None: if diff.get('eventsData', {}).get(EVENT_CLIENT_DATA.INGAME_EVENTS): self.__companies.setNotificators() yield self.falloutQuestsProgress.request() yield self.randomQuestsProgress.request() yield self.__questsProgress.request() isNeedToInvalidate = True isNeedToClearItemsCaches = False def _cbWrapper(*args): self.__random.update(self, diff) self.__fallout.update(self, diff) callback(*args) if diff is not None: isQPUpdated = 'quests' in diff isEventsDataUpdated = ('eventsData', '_r') in diff or diff.get('eventsData', {}) isNeedToInvalidate = isQPUpdated or isEventsDataUpdated hasVehicleUnlocks = False for intCD in diff.get('stats', {}).get('unlocks', set()): if getTypeOfCompactDescr(intCD) == GUI_ITEM_TYPE.VEHICLE: hasVehicleUnlocks = True break isNeedToClearItemsCaches = 'inventory' in diff and GUI_ITEM_TYPE.VEHICLE in diff['inventory'] or hasVehicleUnlocks if isNeedToInvalidate: self.__invalidateData(_cbWrapper) return else: if isNeedToClearItemsCaches: self.__clearQuestsItemsCache() _cbWrapper(True) return def getQuests(self, filterFunc = None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return not q.isHidden() and filterFunc(q) return self._getQuests(userFilterFunc) def getGroups(self, filterFunc = None): svrGroups = self._getQuestsGroups(filterFunc) svrGroups.update(self._getActionsGroups(filterFunc)) return svrGroups def getHiddenQuests(self, filterFunc = None): filterFunc = filterFunc or (lambda a: True) def hiddenFilterFunc(q): return q.isHidden() and filterFunc(q) return self._getQuests(hiddenFilterFunc) def getAllQuests(self, filterFunc = None, includePotapovQuests = False): return self._getQuests(filterFunc, includePotapovQuests) def getActions(self, filterFunc = None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return filterFunc(q) and q.getType() != EVENT_TYPE.GROUP return self._getActions(userFilterFunc) def getEventBattles(self): battles = self.__getEventBattles() if len(battles): return EventBattles(battles.get('vehicleTags', set()), battles.get('vehicles', []), bool(battles.get('enabled', 0)), battles.get('arenaTypeID')) else: return EventBattles(set(), [], 0, None) return None def isEventEnabled(self): return len(self.__getEventBattles()) > 0 def getEventVehicles(self): from gui.shared import g_itemsCache result = [] for v in g_eventsCache.getEventBattles().vehicles: item = g_itemsCache.items.getItemByCD(v) if item.isInInventory: result.append(item) return sorted(result) def getEvents(self, filterFunc = None): svrEvents = self.getQuests(filterFunc) svrEvents.update(self.getActions(filterFunc)) return svrEvents def getCurrentEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() <= 0 < q.getFinishTimeLeft()) def getFutureEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() > 0) def getCompanyBattles(self): battle = self.__getCompanyBattlesData() startTime = battle.get('startTime', 0.0) finishTime = battle.get('finishTime', 0.0) return CompanyBattles(startTime=None if startTime is None else float(startTime), finishTime=None if finishTime is None else float(finishTime), peripheryIDs=battle.get('peripheryIDs', set())) def getFalloutConfig(self, battleType): return makeTupleByDict(FalloutConfig, self.__getFallout().get(battleType, {})) def getItemAction(self, item, isBuying = True, forCredits = False): result = [] type = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][type].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][type].get(itemTypeID, {}).get(15, []) for (key, value), actionID in values: if item.isPremium and key in ('creditsPrice', 'creditsPriceMultiplier') and not forCredits: continue result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][type].get(itemTypeID, {}).get(intCD, tuple())) return result def getRentAction(self, item, rentPackage): result = [] type = ACTION_MODIFIER_TYPE.RENT itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][type].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][type].get(itemTypeID, {}).get(15, []) for (key, value), actionID in values: result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][type].get(itemTypeID, {}).get((intCD, rentPackage), tuple())) return result def getEconomicsAction(self, name): result = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get(name, []) resultMult = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get('%sMultiplier' % name, []) return tuple(result + resultMult) def getCamouflageAction(self, vehicleIntCD): return tuple(self.__actionsCache[ACTION_SECTION_TYPE.CUSTOMIZATION][ACTION_MODIFIER_TYPE.DISCOUNT].get(vehicleIntCD, tuple())) def getEmblemsAction(self, group): return tuple(self.__actionsCache[ACTION_SECTION_TYPE.CUSTOMIZATION][ACTION_MODIFIER_TYPE.DISCOUNT].get(group, tuple())) def getQuestsDossierBonuses(self): return self.__questsDossierBonuses def getQuestsByTokenRequirement(self, token): result = [] for q in self._getQuests(includePotapovQuests=True).itervalues(): if token in map(lambda t: t.getID(), q.accountReqs.getTokens()): result.append(q) return result def getQuestsByTokenBonus(self, token): result = [] for q in self._getQuests(includePotapovQuests=True).itervalues(): for t in q.getBonuses('tokens'): if token in t.getTokens().keys(): result.append(q) break return result def _getQuests(self, filterFunc = None, includePotapovQuests = False): result = {} groups = {} filterFunc = filterFunc or (lambda a: True) for qID, q in self.__getCommonQuestsIterator(): if q.getType() == EVENT_TYPE.GROUP: groups[qID] = q continue if q.getDestroyingTimeLeft() <= 0: continue if not filterFunc(q): continue result[qID] = q if includePotapovQuests: for qID, q in self.potapov.getQuests().iteritems(): if filterFunc(q): result[qID] = q for gID, group in groups.iteritems(): for qID in group.getGroupEvents(): if qID in result: result[qID].setGroupID(gID) children, parents = self._makeQuestsRelations(result) for qID, q in result.iteritems(): if qID in children: q.setChildren(children[qID]) if qID in parents: q.setParents(parents[qID]) return result def _getQuestsGroups(self, filterFunc = None): filterFunc = filterFunc or (lambda a: True) result = {} for qID, q in self.__getCommonQuestsIterator(): if q.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(q): continue result[qID] = q return result def _getActions(self, filterFunc = None): filterFunc = filterFunc or (lambda a: True) actions = self.__getActionsData() result = {} groups = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) actionID = a.getID() if a.getType() == EVENT_TYPE.GROUP: groups[actionID] = a continue if not filterFunc(a): continue result[actionID] = a for gID, group in groups.iteritems(): for aID in group.getGroupEvents(): if aID in result: result[aID].setGroupID(gID) return result def _getActionsGroups(self, filterFunc = None): actions = self.__getActionsData() filterFunc = filterFunc or (lambda a: True) result = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) if a.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(a): continue result[a.getID()] = a return result def _onResync(self, *args): self.__invalidateData() def _makeQuest(self, qID, qData, maker = _defaultQuestMaker, **kwargs): storage = self.__cache['quests'] if qID in storage: return storage[qID] q = storage[qID] = maker(qID, qData, self.__questsProgress, **kwargs) return q def _makeAction(self, aID, aData): storage = self.__cache['actions'] if aID in storage: return storage[aID] a = storage[aID] = createAction(aData.get('type', 0), aID, aData) return a @classmethod def _makeQuestsRelations(cls, quests): makeTokens = defaultdict(list) needTokens = defaultdict(list) for qID, q in quests.iteritems(): if q.getType() != EVENT_TYPE.GROUP: tokens = q.getBonuses('tokens') if len(tokens): for t in tokens[0].getTokens(): makeTokens[t].append(qID) for t in q.accountReqs.getTokens(): needTokens[qID].append(t.getID()) children = defaultdict(dict) for parentID, tokensIDs in needTokens.iteritems(): for tokenID in tokensIDs: children[parentID][tokenID] = makeTokens.get(tokenID, []) parents = defaultdict(dict) for parentID, tokens in children.iteritems(): for tokenID, chn in tokens.iteritems(): for childID in chn: parents[childID][tokenID] = [parentID] return (children, parents) def __invalidateData(self, callback = lambda *args: None): self.__clearCache() self.__clearInvalidateCallback() self.__waitForSync = True self.onSyncStarted() def mergeValues(a, b): result = list(a) result.extend(b) return result for action in self.getActions().itervalues(): for modifier in action.getModifiers(): section = modifier.getSection() type = modifier.getType() itemType = modifier.getItemType() values = modifier.getValues(action) currentSection = self.__actionsCache[section][type] if itemType is not None: currentSection = currentSection.setdefault(itemType, {}) for k in values: if k in currentSection: currentSection[k] = mergeValues(currentSection[k], values[k]) else: currentSection[k] = values[k] rareAchieves = set() invalidateTimeLeft = sys.maxint for q in self.getCurrentEvents().itervalues(): dossierBonuses = q.getBonuses('dossier') if len(dossierBonuses): storage = self.__questsDossierBonuses[q.getID()] for bonus in dossierBonuses: records = bonus.getRecords() storage.update(records) rareAchieves |= set((r for r in records if r[0] == ACHIEVEMENT_BLOCK.RARE)) timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is not None: isAvailable, errorMsg = q.isAvailable() if not isAvailable: if errorMsg in ('invalid_weekday', 'invalid_time_interval'): invalidateTimeLeft = min(invalidateTimeLeft, timeLeftInfo[0]) else: intervalBeginTimeLeft, (intervalStart, intervalEnd) = timeLeftInfo invalidateTimeLeft = min(invalidateTimeLeft, intervalBeginTimeLeft + intervalEnd - intervalStart) else: invalidateTimeLeft = min(invalidateTimeLeft, q.getFinishTimeLeft()) g_rareAchievesCache.request(rareAchieves) for q in self.getFutureEvents().itervalues(): timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is None: startTime = q.getStartTimeLeft() else: startTime = timeLeftInfo[0] invalidateTimeLeft = min(invalidateTimeLeft, startTime) if invalidateTimeLeft != sys.maxint: self.__loadInvalidateCallback(invalidateTimeLeft) self.__waitForSync = False self.onSyncCompleted() callback(True) from gui.shared import g_eventBus g_eventBus.handleEvent(events.LobbySimpleEvent(events.LobbySimpleEvent.EVENTS_UPDATED)) return def __clearQuestsItemsCache(self): for qID, q in self._getQuests().iteritems(): q.accountReqs.clearItemsCache() q.vehicleReqs.clearItemsCache() @classmethod def __getEventsData(cls, eventsTypeName): try: if isPlayerAccount(): if eventsTypeName in BigWorld.player().eventsData: return pickle.loads(zlib.decompress(BigWorld.player().eventsData[eventsTypeName])) return {} LOG_ERROR('Trying to get quests data from not account player', eventsTypeName, BigWorld.player()) except Exception: LOG_CURRENT_EXCEPTION() return {} def __getQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.QUEST) def __getFortQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.FORT_QUEST) def __getPersonalQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.PERSONAL_QUEST) def __getActionsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION) def __getEventBattles(self): return self.__getEventsData(EVENT_CLIENT_DATA.INGAME_EVENTS).get('eventBattles', {}) def __getCompanyBattlesData(self): return self.__getEventsData(EVENT_CLIENT_DATA.INGAME_EVENTS).get('eventCompanies', {}) def __getFallout(self): return self.__getEventsData(EVENT_CLIENT_DATA.FALLOUT) def __getCommonQuestsIterator(self): questsData = self.__getQuestsData() questsData.update(self.__getFortQuestsData()) questsData.update(self.__getPersonalQuestsData()) questsData.update(self.__getPotapovHiddenQuests()) for qID, qData in questsData.iteritems(): yield (qID, self._makeQuest(qID, qData)) currentESportSeasonID = g_lobbyContext.getServerSettings().eSportCurrentSeason.getID() eSportQuests = clubs_quests.g_cache.getLadderQuestsBySeasonID(currentESportSeasonID) or [] for questDescr in eSportQuests: yield (questDescr.questID, self._makeQuest(questDescr.questID, questDescr.questData, maker=_clubsQuestMaker, seasonID=currentESportSeasonID, questDescr=questDescr)) def __loadInvalidateCallback(self, duration): LOG_DEBUG('load quest window invalidation callback (secs)', duration) self.__clearInvalidateCallback() self.__invalidateCbID = BigWorld.callback(math.ceil(duration), self.__invalidateData) def __clearInvalidateCallback(self): if self.__invalidateCbID is not None: BigWorld.cancelCallback(self.__invalidateCbID) self.__invalidateCbID = None return def __clearCache(self): self.__questsDossierBonuses.clear() self.__actionsCache.clear() for storage in self.__cache.itervalues(): storage.clear() def __getPotapovHiddenQuests(self): if not self.__potapovHidden: xmlPath = _POTAPOV_QUEST_XML_PATH + '/tiles.xml' for quest in readQuestsFromFile(xmlPath, EVENT_TYPE.TOKEN_QUEST): self.__potapovHidden[quest[0]] = quest[3] return self.__potapovHidden.copy()
class EventListener(object): cursorType = property(lambda self: self.__cursorType) isBrowserPlayingAudio = False def __init__(self, browser): self.__cursorTypes = { CURSOR_TYPES.Hand: CursorManager.HAND, CURSOR_TYPES.Pointer: CursorManager.ARROW, CURSOR_TYPES.IBeam: CursorManager.IBEAM, CURSOR_TYPES.Grab: CursorManager.DRAG_OPEN, CURSOR_TYPES.Grabbing: CursorManager.DRAG_CLOSE, CURSOR_TYPES.ColumnResize: CursorManager.MOVE } self.__cursorType = None self.__eventMgr = EventManager() self.onLoadStart = Event(self.__eventMgr) self.onLoadEnd = Event(self.__eventMgr) self.onLoadingStateChange = Event(self.__eventMgr) self.onCursorUpdated = Event(self.__eventMgr) self.onDOMReady = Event(self.__eventMgr) self.onReady = Event(self.__eventMgr) self.onJsHostQuery = Event(self.__eventMgr) self.onTitleChange = Event(self.__eventMgr) self.onDestroy = Event(self.__eventMgr) self.onAudioStatusChanged = Event(self.__eventMgr) self.onConsoleMessage = Event(self.__eventMgr) self.__urlFailed = False self.__browserProxy = weakref.proxy(browser) return def clear(self): self.__eventMgr.clear() def newNavigation(self): self.__urlFailed = False def onChangeCursor(self, cursorType): self.__cursorType = self.__cursorTypes.get( cursorType) or CursorManager.ARROW self.onCursorUpdated() def onChangeTitle(self, title): _logger.debug('onChangeTitle %s', title) self.onTitleChange(title) def ready(self, success): self.onReady(success) def destroy(self): self.onDestroy() def onBeginLoadingFrame(self, frameId, isMainFrame, url): if isMainFrame: _logger.debug('onBeginLoadingFrame(isMainFrame) %s', url) self.onLoadStart(url) if self.__urlFailed: self.onLoadEnd(url, False) def onFailLoadingFrame(self, frameId, isMainFrame, url, errorCode, errorDesc): if isMainFrame: _logger.debug( 'onFailLoadingFrame(isMainFrame) %s, error: %r, text: %r', url, errorCode, errorDesc) self.__urlFailed = True self.onLoadEnd(url, not self.__urlFailed, errorDesc=errorDesc) def onFinishLoadingFrame(self, frameId, isMainFrame, url, httpStatusCode): if isMainFrame: _logger.debug( 'onFinishLoadingFrame(isMainFrame) %s, httpStatusCode: %r', url, httpStatusCode) self.onLoadEnd(url, not self.__urlFailed, httpStatusCode) def onBrowserLoadingStateChange(self, isLoading): _logger.debug('onBrowserLoadingStateChange isLoading: %r', isLoading) self.onLoadingStateChange(isLoading) def onDocumentReady(self, url): _logger.debug('onDocumentReady %s', url) self.onDOMReady(url) def onAddConsoleMessage(self, level, message, lineNumber, source, viewId): self.onConsoleMessage(level, message, lineNumber, source, viewId) def onFilterNavigation(self, url): return self.__browserProxy.filterNavigation(url) def onResourceLoadRequest(self, method, url): _logger.debug('requested %s %s', method, url) return self.__browserProxy.onResourceLoadRequest(url) def onResourceLoadComplete(self, method, url): _logger.debug('completed %s %s', method, url) def onResourceLoadError(self, method, url): _logger.warn('failed %s %s', method, url) def onWhitelistMiss(self, isMainFrame, failedURL, httpStatusCode=None): if isMainFrame: self.onLoadStart(failedURL) self.onLoadEnd(failedURL, False, httpStatusCode) def onShowCreatedWebView(self, url, isPopup): _logger.debug('onShowCreatedWebView %s isPopup: %r', url, isPopup)
class EventListener(): cursorType = property(lambda self: self.__cursorType) def __init__(self, browser): self.__cursorTypes = { CURSOR_TYPES.Hand: 'Cursor.HAND', CURSOR_TYPES.Pointer: 'Cursor.ARROW', CURSOR_TYPES.IBeam: 'Cursor.IBEAM', CURSOR_TYPES.Grab: 'Cursor.DRAG_OPEN', CURSOR_TYPES.Grabbing: 'Cursor.DRAG_CLOSE', CURSOR_TYPES.ColumnResize: 'Cursor.MOVE' } self.__cursorType = 'Cursor.ARROW' self.__eventMgr = EventManager() self.onLoadStart = Event(self.__eventMgr) self.onLoadEnd = Event(self.__eventMgr) self.onLoadingStateChange = Event(self.__eventMgr) self.onCursorUpdated = Event(self.__eventMgr) self.onDOMReady = Event(self.__eventMgr) self.onReady = Event(self.__eventMgr) self.onJsHostQuery = Event(self.__eventMgr) self.onTitleChange = Event(self.__eventMgr) self.__urlFailed = False self.__browserProxy = weakref.proxy(browser) def clear(self): self.__eventMgr.clear() def newNavigation(self): self.__urlFailed = False def onChangeCursor(self, cursorType): self.__cursorType = self.__cursorTypes.get( cursorType) or 'Cursor.ARROW' self.onCursorUpdated() def onChangeTitle(self, title): LOG_BROWSER('onChangeTitle "{}"'.format(title)) self.onTitleChange(title) def ready(self, success): self.onReady(success) def onBeginLoadingFrame(self, frameId, isMainFrame, url): if isMainFrame: LOG_BROWSER('onBeginLoadingFrame(isMainFrame) "{}"'.format(url)) self.onLoadStart(url) if self.__urlFailed: self.onLoadEnd(url, False) def onFailLoadingFrame(self, frameId, isMainFrame, url, errorCode, errorDesc): if isMainFrame: LOG_BROWSER( 'onFailLoadingFrame(isMainFrame) "{}", errorCode:{}, errorDesc:{}' .format(url, errorCode, errorDesc)) self.__urlFailed = True def onFinishLoadingFrame(self, frameId, isMainFrame, url, httpStatusCode): if isMainFrame: LOG_BROWSER( 'onFinishLoadingFrame(isMainFrame) "{}" status:{}'.format( url, httpStatusCode)) self.onLoadEnd(url, not self.__urlFailed, httpStatusCode) def onBrowserLoadingStateChange(self, isLoading): LOG_BROWSER( 'onBrowserLoadingStateChange() isLoading:{}'.format(isLoading)) self.onLoadingStateChange(isLoading) def onDocumentReady(self, url): LOG_BROWSER('onDocumentReady "{}"'.format(url)) self.onDOMReady(url) def onAddConsoleMessage(self, message, lineNumber, source): pass def onFilterNavigation(self, url): """ This event occurs before frame navigations. You can use this to block or log navigations for each frame of a WebView. :param url: The URL that the frame wants to navigate to. :return: True to block a navigation. Return False to let it continue. """ return self.__browserProxy.filterNavigation(url) def onWhitelistMiss(self, isMainFrame, failedURL): if isMainFrame: LOG_BROWSER('onWhitelistMiss(isMainFrame) "{}"'.format(failedURL)) self.onLoadStart(failedURL) self.onLoadEnd(failedURL, False) def onShowCreatedWebView(self, url, isPopup): LOG_BROWSER('onShowCreatedWebView "{}" isPopup:{}'.format( url, isPopup))
class WebBrowserImpl(object): _WOWP_CLIENT_PARAM_NAME = 'wowp_client_param' url = property(lambda self: ('' if self.__browser is None else self.__browser.url)) isFocused = property(lambda self: self.__isFocused) hasBrowser = property(lambda self: self.__browser is not None) isSuccessfulLoad = property(lambda self: self.__successfulLoad) skipEscape = property(lambda self: self.__skipEscape) ignoreKeyEvents = property(lambda self: self.__ignoreKeyEvents) useSpecialKeys = property(lambda self: self.__useSpecialKeys) allowMouseWheel = property(lambda self: self.__allowMouseWheel) @skipEscape.setter def skipEscape(self, value): LOG_BROWSER('skipEscape set %s (was: %s)' % (value, self.__skipEscape)) self.__skipEscape = value @ignoreKeyEvents.setter def ignoreKeyEvents(self, value): LOG_BROWSER('ignoreKeyEvents set %s (was: %s)' % (value, self.__ignoreKeyEvents)) self.__ignoreKeyEvents = value @useSpecialKeys.setter def useSpecialKeys(self, value): LOG_BROWSER('useSpecialKeys set %s (was: %s)' % (value, self.__useSpecialKeys)) self.__useSpecialKeys = value @allowMouseWheel.setter def allowMouseWheel(self, value): LOG_BROWSER('allowMouseWheel set %s (was: %s)' % (value, self.__allowMouseWheel)) self.__allowMouseWheel = value def __init__(self, browser_id, width, height, sfMovieClip, sfResourceName, url): self.__width = width self.__height = height self.__sfMovieClip = weakref.ref(sfMovieClip) self.__sfResourceName = sfResourceName self.__browserId = browser_id self.__browser = None self.__isFocused = False self.__isReady = False self.__baseUrl = url self.__navigationFilters = set() self.__skipEscape = True self.__ignoreKeyEvents = False self.__useSpecialKeys = True self.__allowMouseWheel = True self.__disableKeyHandlers = [] self.__loadStartTime = BigWorld.time() self.__enableUpdate = False self.__isMouseDown = False self.__isWaitingForUnfocus = False self.__allowAutoLoadingScreenChange = True self.__isNavigationComplete = False self.__successfulLoad = False self.__delayedUrls = [] self.__isCloseTriggered = False self.__specialKeyHandlers = None self.__browserKeyHandlers = None self.__eventMgr = EventManager() self.onLoadStart = Event(self.__eventMgr) self.onLoadEnd = Event(self.__eventMgr) self.onLoadingStateChange = Event(self.__eventMgr) self.onReadyToShowContent = Event(self.__eventMgr) self.onNavigate = Event(self.__eventMgr) self.onReady = Event(self.__eventMgr) self.onJsHostQuery = Event(self.__eventMgr) self.onTitleChange = Event(self.__eventMgr) self.onFailedCreation = Event(self.__eventMgr) self.onCanCreateNewBrowser = Event(self.__eventMgr) self.onCursorUpdated = Event(self.__eventMgr) return def create(self): LOG_BROWSER('Create id:{}'.format(self.__browserId)) clientLanguage = '' self.__browser = BigWorld.createBrowser(self.__browserId, clientLanguage) if self.__browser is None: LOG_BROWSER('create() NO BROWSER WAS CREATED') return False else: self.__browser.script = EventListener(self) self.__browser.script.onLoadStart += self.__onLoadStart self.__browser.script.onLoadEnd += self.__onLoadEnd self.__browser.script.onLoadingStateChange += self.__onLoadingStateChange self.__browser.script.onDOMReady += self.__onReadyToShowContent self.__browser.script.onCursorUpdated += self.__onCursorUpdated self.__browser.script.onReady += self.__onReady self.__browser.script.onJsHostQuery += self.__onJsHostQuery self.__browser.script.onTitleChange += self.__onTitleChange def injectBrowserKeyEvent(me, e): if _BROWSER_KEY_LOGGING: LOG_BROWSER( 'injectBrowserKeyEvent key:{} isKeyDown:{} isAltDown:{} isShiftDown:{} isCtrlDown:{}' .format(e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown())) me.__browser.injectKeyEvent(e) def injectKeyDown(me, e): injectBrowserKeyEvent(me, e) def injectKeyUp(me, e): injectBrowserKeyEvent(me, e) def resetBit(value, bitMask): return value & ~bitMask self.__specialKeyHandlers = ( (Keys.KEY_LEFTARROW, True, True, None, None, lambda me, _: me.__browser.goBack()), (Keys.KEY_RIGHTARROW, True, True, None, None, lambda me, _: me.__browser.goForward()), (Keys.KEY_F5, True, None, None, None, lambda me, _: me.__browser.reload())) self.__browserKeyHandlers = ( (Keys.KEY_LSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition, 0))), (Keys.KEY_RSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition, 0))), (Keys.KEY_LCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition, 0))), (Keys.KEY_RCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition, 0))), (None, True, None, None, None, lambda me, e: injectKeyDown(me, e)), (None, False, None, None, None, lambda me, e: injectKeyUp(me, e))) self.__disableKeyHandlers = [] return True def setDisabledKeys(self, keys): self.__disableKeyHandlers = [] for key, isKeyDown, isAltDown, isShiftDown, isCtrlDown in keys: self.__disableKeyHandlers.append( (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown, lambda me, e: None)) def ready(self, success): LOG_BROWSER('ready: id:{}, status:{}'.format( self.__browserId, 'success' if success else '')) self.__successfulLoad = False self.__enableUpdate = True self.__isMouseDown = False self.__isFocused = False self.__isWaitingForUnfocus = False if success: if self.__sfMovieClip(): self.__browser.setScaleformRender(self.__sfMovieClip(), self.__sfResourceName, self.__width, self.__height) self.__browser.activate(True) self.__browser.loadURL(self.__baseUrl) self.__isReady = True self.focus(True) self.onReady(self.__browser.url, success) else: self.__isNavigationComplete = True self.onFailedCreation(self.__baseUrl) def __processDelayedNavigation(self): if self.__isNavigationComplete and self.__delayedUrls: self.doNavigate(self.__delayedUrls.pop(0)) return True return False def destroy(self): LOG_BROWSER('fini id:{}'.format(self.__browserId)) self.__eventMgr.clear() self.__eventMgr = None if self.__browser is not None: self.__browser.script.clear() self.__browser.script = None if self.__sfMovieClip(): self.__browser.resetScaleformRender(self.__sfMovieClip(), self.__sfResourceName) BigWorld.removeBrowser(self.__browserId) self.__browser = None self.__navigationFilters = None self.onCursorUpdated('Cursor.ARROW') return def focus(self, focus): if self.hasBrowser: if focus and not self.__isFocused: self.__browser.focus() self.__isFocused = True self.onCursorUpdated(self.__browser.script.cursorType) elif not focus and self.__isFocused: self.__browser.unfocus() self.__isFocused = False self.__isWaitingForUnfocus = False def refresh(self, ignoreCache=True): if BigWorld.time() - self.__loadStartTime < 0.5: LOG_BROWSER('refresh - called too soon') return if self.hasBrowser: self.__browser.reload() self.onNavigate(self.__browser.url) def navigate(self, url): lastIsSame = self.__delayedUrls and self.__delayedUrls[-1] == url if not lastIsSame: self.__delayedUrls.append(url) self.__processDelayedNavigation() def sendMessage(self, message): if self.hasBrowser: self.__browser.sendMessage(message) def doNavigate(self, url): LOG_BROWSER('doNavigate: {}'.format(url)) self.__baseUrl = url if self.hasBrowser: self.__browser.script.newNavigation() self.__browser.loadURL(url) self.onNavigate(url) def navigateBack(self): if self.hasBrowser: self.__browser.goBack(self.url) def navigateForward(self): if self.hasBrowser: self.__browser.goForward(self.url) def navigateStop(self): if BigWorld.time() - self.__loadStartTime < 0.5: LOG_BROWSER('navigateStop - called too soon') return if self.hasBrowser: self.__browser.stop() self.__onLoadEnd(self.__browser.url) def __getBrowserKeyHandler(self, key, isKeyDown, isAltDown, isShiftDown, isCtrlDown): from itertools import izip params = (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown) matches = lambda t: t[0] is None or t[0] == t[1] browserKeyHandlers = tuple( self.__disableKeyHandlers) + self.__browserKeyHandlers if self.useSpecialKeys: browserKeyHandlers = self.__specialKeyHandlers + browserKeyHandlers for values in browserKeyHandlers: if reduce(lambda a, b: a and matches(b), izip(values, params), True): return values[-1] return None def handleKeyEvent(self, event): if not (self.hasBrowser and self.__enableUpdate): return False e = event keyState = (e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown()) if not self.skipEscape and e.key == Keys.KEY_ESCAPE and e.isKeyDown(): self.__getBrowserKeyHandler(*keyState)(self, e) return True if not self.isFocused: self.__browser.injectKeyModifiers(e) return False if _BROWSER_KEY_LOGGING: LOG_BROWSER('handleKeyEvent {}'.format(keyState)) if self.ignoreKeyEvents: return False if e.key in (Keys.KEY_ESCAPE, Keys.KEY_SYSRQ, Keys.KEY_LEFTMOUSE, Keys.KEY_RIGHTMOUSE): return False if e.key in (Keys.KEY_RETURN, Keys.KEY_NUMPADENTER) and e.isAltDown(): return False self.__getBrowserKeyHandler(*keyState)(self, e) return True def browserMove(self, x, y, z): if not (self.hasBrowser and self.__enableUpdate and self.isFocused): return if z != 0: if self.allowMouseWheel: self.__browser.injectMouseWheelEvent(z * 20) return self.__browser.injectMouseMoveEvent(x, y) def browserDown(self, x, y, z): if not (self.hasBrowser and self.__enableUpdate): return elif self.__isMouseDown: return else: if not self.isFocused: self.focus(True) self.__isMouseDown = True self.browserUp(x, y, z) self.browserMove(x, y, z) self.__isMouseDown = True self.__browser.injectKeyEvent( BigWorld.KeyEvent(Keys.KEY_LEFTMOUSE, 0, 0, None, (x, y), 0)) return def browserUp(self, x, y, z): if not (self.hasBrowser and self.__enableUpdate): return elif not self.__isMouseDown: return else: self.__isMouseDown = False self.__browser.injectKeyEvent( BigWorld.KeyEvent(Keys.KEY_LEFTMOUSE, -1, 0, None, (x, y), 0)) if self.__isWaitingForUnfocus: self.focus(False) return def browserFocusOut(self): if self.isFocused and self.__isMouseDown: self.__isWaitingForUnfocus = True return self.focus(False) def browserAction(self, action): if self.hasBrowser and self.__enableUpdate: if action == 'reload' and self.__isNavigationComplete: self.refresh() elif action == 'loading' and not self.__isNavigationComplete: self.navigateStop() def onBrowserShow(self, needRefresh): self.__enableUpdate = True if needRefresh and self.__baseUrl != self.url: self.navigate(self.url) self.focus(True) def onBrowserHide(self): self.navigate(self.__baseUrl) self.__enableUpdate = False self.focus(False) def addFilter(self, handler): if handler in self.__navigationFilters: LOG_ERROR_BROWSER( 'Navigation filter is already added {}'.format(handler)) else: self.__navigationFilters.add(handler) def removeFilter(self, handler): if handler in self.__navigationFilters: self.__navigationFilters.discard(handler) else: LOG_ERROR_BROWSER( "Trying to delete navigation filter which doesn't exist {}". format(handler)) def filterNavigation(self, url): query = urlparse.urlparse(url).query tags = urlparse.parse_qs(query).get(self._WOWP_CLIENT_PARAM_NAME, []) stopNavigation = False closeBrowser = False for handler in self.__navigationFilters: try: result = handler(url, tags) stopNavigation |= result.stopNavigation closeBrowser |= result.closeBrowser if result.stopNavigation: LOG_BROWSER( 'Navigation filter triggered navigation stop: {}'. format(handler)) if result.closeBrowser: LOG_BROWSER( 'Navigation filter triggered browser close: {}'.format( handler)) except: LOG_CURRENT_EXCEPTION() self.__isCloseTriggered = closeBrowser return stopNavigation def setLoadingScreenVisible(self, visible): LOG_BROWSER('setLoadingScreenVisible {}'.format(visible)) self.onLoadingStateChange(visible, True) def setAllowAutoLoadingScreen(self, enabled): LOG_BROWSER('setAllowAutoLoadingScreen {}'.format(enabled)) self.__allowAutoLoadingScreenChange = enabled def changeTitle(self, title): self.onTitleChange(title) def __onLoadStart(self, url): if url == self.__browser.url: self.__isNavigationComplete = False self.__loadStartTime = BigWorld.time() LOG_BROWSER('onLoadStart {}'.format(self.__browser.url)) self.onLoadStart(self.__browser.url) self.__successfulLoad = False def __onLoadEnd(self, url, isLoaded=True, httpStatusCode=None): if url == self.__browser.url: self.__isNavigationComplete = True self.__successfulLoad = isLoaded if not self.__processDelayedNavigation(): LOG_BROWSER('onLoadEnd {} {} {}'.format( self.__browser.url, isLoaded, httpStatusCode)) self.onLoadEnd(self.__browser.url, isLoaded, httpStatusCode) def __onLoadingStateChange(self, isLoading): LOG_BROWSER('onLoadingStateChange {} {}'.format( isLoading, self.__allowAutoLoadingScreenChange)) self.onLoadingStateChange(isLoading, self.__allowAutoLoadingScreenChange) if self.__isCloseTriggered: pass elif not isLoading: self.onCanCreateNewBrowser() def __onReadyToShowContent(self, url): if url == self.__browser.url: LOG_BROWSER('onReadyToShowContent {}'.format(self.__browser.url)) self.onReadyToShowContent(self.__browser.url) def __isValidTitle(self, title): if self.__browser.url.startswith('about:'): return False if self.__browser.url.endswith(title): return False if self.__browser.url.endswith('/'): secondtest = self.__browser.url[:-1] if secondtest.endswith(title): return False if self.__baseUrl == title or self.__baseUrl.endswith(title): return False return True def __onTitleChange(self, title): if self.hasBrowser and self.__isValidTitle(title): LOG_BROWSER('onTitleChange {} {}'.format(title, self.__browser.url)) self.onTitleChange(title) def __onCursorUpdated(self): if self.hasBrowser and self.isFocused: self.onCursorUpdated(self.__browser.script.cursorType) def __onReady(self, success): self.ready(success) def __onJsHostQuery(self, command): self.onJsHostQuery(command) def executeJavascript(self, script, frame): if self.hasBrowser: self.__browser.executeJavascript(script, frame)
class BuyBoosterMeta(I18nConfirmDialogMeta): def __init__(self, boosterID, balance): super(BuyBoosterMeta, self).__init__('buyConfirmation', scope=ScopeTemplates.LOBBY_SUB_SCOPE) self.__booster = g_goodiesCache.getBooster(boosterID) self.__balance = balance self._eManager = EventManager() self.onInvalidate = Event(self._eManager) g_clientUpdateManager.addCallbacks({'stats': self.__onStatsChanged}) def getEventType(self): return events.ShowDialogEvent.SHOW_CONFIRM_BOOSTER def getBoosterID(self): return self.__booster.boosterID def getBooster(self): return self.__booster def destroy(self): self.__booster = None self.__balance = None self._eManager.clear() g_clientUpdateManager.removeObjectCallbacks(self) return def getMaxAvailableItemsCount(self): return (self.__getMaxCount(Currency.CREDITS), self.__getMaxCount(Currency.GOLD)) def getActionVO(self): buyPrice = self.__booster.buyPrice defaultPrice = self.__booster.defaultPrice if buyPrice != defaultPrice: return packActionTooltipData(ACTION_TOOLTIPS_TYPE.BOOSTER, str(self.__booster.boosterID), True, buyPrice, defaultPrice) else: return None def getCurrency(self): return self.__booster.getBuyPriceCurrency() def getPrice(self): return self.__booster.buyPrice @process('buyItem') def submit(self, count, currency): result = yield BoosterBuyer(self.__booster, count, currency == Currency.GOLD).request() if len(result.userMsg): SystemMessages.g_instance.pushI18nMessage(result.userMsg, type=result.sysMsgType) def __onStatsChanged(self, stats): if 'credits' in stats: self.__balance = self.__balance.replace(Currency.CREDITS, stats['credits']) self.onInvalidate() if 'gold' in stats: self.__balance = self.__balance.replace(Currency.GOLD, stats['gold']) self.onInvalidate() def __getMaxCount(self, currency): result = 0 boosterPrice = self.__booster.buyPrice if boosterPrice.get(currency) > 0: result = math.floor(self.__balance.get(currency) / boosterPrice.get(currency)) return min(result, MAX_BOOSTERS_FOR_OPERATION)
class _PreDefinedHostList(object): def __init__(self): super(_PreDefinedHostList, self).__init__() self._eManager = EventManager() self.onCsisQueryStart = Event(self._eManager) self.onCsisQueryComplete = Event(self._eManager) self.onPingPerformed = Event(self._eManager) self._hosts = [] self._urlMap = {} self._nameMap = {} self._peripheryMap = {} self._isDataLoaded = False self._isCSISQueryInProgress = False self.__csisUrl = '' self.__csisResponse = {} self.__lastRoamingHosts = [] self.__csisCallbackID = None self.__lastCsisUpdateTime = 0 self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self.__recommended = [] self.__pingRequester = _PingRequester(self.__onPingPerformed) return def fini(self): self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() self._isDataLoaded = False self.__csisResponse.clear() self.__csisUrl = '' self.__lastCsisUpdateTime = None self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self._eManager.clear() self.__pingRequester.fini() self.__cleanCsisTimerCallback() return @property def lastRoamingHosts(self): return self.__lastRoamingHosts def startCSISUpdate(self): if len(self.hosts()) > 1: self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__sendCsisQuery() def stopCSISUpdate(self): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__cleanCsisTimerCallback() def requestPing(self, forced=False): self.__pingRequester.request(self._hosts, forced) def getPingResult(self): return self.__pingRequester.result() def getHostPingData(self, host): return self.getPingResult().get(host, _DEFAULT_PING_DATA) def autoLoginQuery(self, callback): if callback is None: LOG_WARNING('Callback is not defined.') return elif self.__autoLoginQueryState != AUTO_LOGIN_QUERY_STATE.DEFAULT: LOG_WARNING('Auto login query in process. Current state: {}'.format(self.__autoLoginQueryState)) return elif len(self._hosts) < 2: callback(self.first()) return elif self.__recommended: LOG_DEBUG('Gets recommended from previous query', self.__recommended) host = self.__choiceFromRecommended() LOG_DEBUG('Recommended host', host) callback(host) return else: self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.START self.__queryCallback = callback self.__pingRequester.request(self.peripheries()) self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__sendCsisQuery() return def resetQueryResult(self): self.__recommended = [] self.__pingRequester.clear() def readScriptConfig(self, dataSection, userDataSection=None): if self._isDataLoaded or dataSection is None: return else: def _readSvrList(section, nodeName): return section[nodeName].items() if section is not None and section.has_key(nodeName) else [] self.__csisUrl = dataSection.readString('csisUrl') self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() svrList = _readSvrList(dataSection, 'login') + _readSvrList(userDataSection, 'development/login') for name, subSec in svrList: name = subSec.readString('name') shortName = subSec.readString('short_name') urls = _LoginAppUrlIterator(subSec.readStrings('url')) host = urls.primary if host is not None: if not name: name = host keyPath = subSec.readString('public_key_path') if not keyPath: keyPath = None areaID = subSec.readString('game_area_id') if not areaID: areaID = None app = self._makeHostItem(name, shortName, host, urlToken=subSec.readString('url_token'), urlIterator=urls if len(urls) > 1 else None, keyPath=keyPath, areaID=areaID, peripheryID=subSec.readInt('periphery_id', 0)) idx = len(self._hosts) url = app.url if url in self._urlMap: LOG_WARNING('Host url is already added. This host is ignored', url) continue self._urlMap[url] = idx urlToken = app.urlToken if urlToken: if urlToken in self._urlMap: LOG_WARNING('Alternative host url is already added. This url is ignored', app.url) else: self._urlMap[urlToken] = idx self._nameMap[app.name] = idx self._peripheryMap[app.peripheryID] = idx self._hosts.append(app) self._isDataLoaded = True return def predefined(self, url): return url in self._urlMap def roaming(self, url): return url in [ p.url for p in self.roamingHosts() ] def first(self): return self._hosts[0] if self._hosts else self._makeHostItem('', '', '') def byUrl(self, url): result = self._makeHostItem('', '', url) index = self._urlMap.get(url, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.url == url: result = host return result def byName(self, name): result = self._makeHostItem(name, '', '') index = self._nameMap.get(name, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.name == name: result = host return result def hosts(self): return self._hosts[:] def shortList(self): result = self.getSimpleHostsList(self._hosts) if AUTO_LOGIN_QUERY_ENABLED and len(result) > 1 and len(self.peripheries()) > 1: result.insert(0, (AUTO_LOGIN_QUERY_URL, i18n.makeString('#menu:login/auto'), HOST_AVAILABILITY.IGNORED, None)) return result def getSimpleHostsList(self, hosts, withShortName=False): result = [] defAvail = self.getDefaultCSISStatus() predefined = tuple((host.url for host in self.peripheries())) isInProgress = self._isCSISQueryInProgress csisResGetter = self.__csisResponse.get for item in hosts: if item.url not in predefined: status = HOST_AVAILABILITY.IGNORED else: status = defAvail if isInProgress else csisResGetter(item.peripheryID, defAvail) if withShortName: result.append((item.url, item.name, item.shortName, status, item.peripheryID)) result.append((item.url, item.name, status, item.peripheryID)) return result def getDefaultCSISStatus(self): from gui import GUI_SETTINGS if not self.__csisUrl: defAvail = HOST_AVAILABILITY.IGNORED elif GUI_SETTINGS.csisRequestRate == REQUEST_RATE.NEVER: defAvail = HOST_AVAILABILITY.IGNORED elif len(g_preDefinedHosts.hosts()) > 1: defAvail = HOST_AVAILABILITY.REQUESTED else: defAvail = HOST_AVAILABILITY.IGNORED return defAvail def urlIterator(self, primary): result = None index = self._urlMap.get(primary, -1) if index > -1: result = self._hosts[index].urlIterator return result def periphery(self, peripheryID, useRoaming=True): if peripheryID in self._peripheryMap: index = self._peripheryMap[peripheryID] return self._hosts[index] else: if useRoaming: roamingHosts = dict(((host.peripheryID, host) for host in self.roamingHosts())) if peripheryID in roamingHosts: return roamingHosts[peripheryID] return None def peripheries(self): return [ app for app in self._hosts if app.peripheryID ] def roamingHosts(self): p = BigWorld.player() result = [] if hasattr(p, 'serverSettings'): for peripheryID, name, shortName, host, keyPath in p.serverSettings['roaming'][3]: result.append(self._makeHostItem(name, shortName, host, keyPath=keyPath, peripheryID=peripheryID)) self.__lastRoamingHosts = sorted(result, key=operator.itemgetter(0)) return self.__lastRoamingHosts def hostsWithRoaming(self): predefined = tuple((host.url for host in self.peripheries())) hosts = self.peripheries() for h in self.roamingHosts(): if h.url not in predefined: hosts.append(h) return hosts def isRoamingPeriphery(self, peripheryID): return peripheryID not in [ p.peripheryID for p in self.peripheries() ] def _makeHostItem(self, name, shortName, url, urlToken='', urlIterator=None, keyPath=None, areaID=None, peripheryID=0): if not shortName: shortName = name return _HostItem(name, shortName, url, urlToken, urlIterator, keyPath, areaID, peripheryID) def _determineRecommendHost(self): defAvail = HOST_AVAILABILITY.NOT_AVAILABLE csisResGetter = self.__csisResponse.get queryResult = [ (host, self.getHostPingData(host.url).value, csisResGetter(host.peripheryID, defAvail)) for host in self.peripheries() ] self.__recommended = [ item for item in queryResult if item[2] == HOST_AVAILABILITY.RECOMMENDED ] if not self.__recommended: self.__recommended = [ item for item in queryResult if item[2] == HOST_AVAILABILITY.NOT_RECOMMENDED ] recommendLen = len(self.__recommended) if not recommendLen: if len(queryResult) > 1: LOG_DEBUG('List of recommended is empty. Gets host by ping') self.__recommended = self.__filterRecommendedByPing(queryResult) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() else: LOG_DEBUG('Gets first as recommended') result = self.first() else: LOG_DEBUG('Recommended by CSIS', self.__recommended) if recommendLen > 1: self.__recommended = self.__filterRecommendedByPing(self.__recommended) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() return result def __startCsisTimer(self): self.__cleanCsisTimerCallback() self.__csisCallbackID = BigWorld.callback(CSIS_REQUEST_TIMER, self.__onCsisTimer) def __cleanCsisTimerCallback(self): if self.__csisCallbackID: BigWorld.cancelCallback(self.__csisCallbackID) self.__csisCallbackID = None return def __onCsisTimer(self): self.__csisCallbackID = None self.__sendCsisQuery() return def __sendCsisQuery(self): isReplay = _isReplay('CSIS') if not isReplay and self.__csisUrl: if not self._isCSISQueryInProgress: timeFromLastUpdate = time.time() - self.__lastCsisUpdateTime if timeFromLastUpdate >= CSIS_REQUEST_TIMER: self._isCSISQueryInProgress = True self.onCsisQueryStart() allHosts = self.hosts() peripheries = [ host.peripheryID for host in allHosts if host.peripheryID ] LOG_DEBUG('CSIS query sending', peripheries) worker = _getCSISWorker(self.__csisUrl, self.__receiveCsisResponse, peripheries) worker.start() else: self.__finishCsisQuery() else: if not isReplay: LOG_DEBUG('CSIS url is not defined - ignore') self._isCSISQueryInProgress = False self.stopCSISUpdate() self.__finishCsisQuery() self.__lastCsisUpdateTime = 0 def __receiveCsisResponse(self, response): LOG_DEBUG('CSIS query received', response) self._isCSISQueryInProgress = False self.__csisResponse = response self.__lastCsisUpdateTime = time.time() self.__finishCsisQuery() def __finishCsisQuery(self): if self.__csisAction & CSIS_ACTION.AUTO_LOGIN_REQUEST: self.__receiveAutoLoginCSISResponse(self.__csisResponse) if self.__csisAction & CSIS_ACTION.UPDATE_ON_TIME: self.__startCsisTimer() self.onCsisQueryComplete(self.__csisResponse) def __onPingPerformed(self, result): self.onPingPerformed(result) if self.__autoLoginQueryState & AUTO_LOGIN_QUERY_STATE.START: self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.PING_PERFORMED) def __receiveAutoLoginCSISResponse(self, response): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.CSIS_RESPONSE_RECEIVED) def __autoLoginQueryCompleted(self, state): if not self.__autoLoginQueryState & state: self.__autoLoginQueryState |= state if self.__autoLoginQueryState == AUTO_LOGIN_QUERY_STATE.COMPLETED: host = self._determineRecommendHost() LOG_DEBUG('Recommended host', host) self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__queryCallback(host) self.__queryCallback = None return def __filterRecommendedByPing(self, recommended): result = recommended filtered = [ item for item in recommended if item[1] > UNDEFINED_PING_VAL ] if filtered: minPingTime = min(filtered, key=lambda item: item[1])[1] maxPingTime = 1.2 * minPingTime result = [ item for item in filtered if item[1] < maxPingTime ] return result def __choiceFromRecommended(self): recommended = random.choice(self.__recommended) self.__recommended = [ item for item in self.__recommended if item != recommended ] return recommended[0]
class WebBrowser(object): hasBrowser = property(lambda self: self.__browser is not None) intializationUrl = property(lambda self: self.__baseUrl) baseUrl = property(lambda self: ('' if self.__browser is None else self.__baseUrl)) url = property(lambda self: ('' if self.__browser is None else self.__browser.url)) width = property(lambda self: (0 if self.__browser is None else self.__browser.width)) height = property(lambda self: (0 if self.__browser is None else self.__browser.height)) isNavigationComplete = property(lambda self: self.__isNavigationComplete) isFocused = property(lambda self: self.__isFocused) updateInterval = 0.01 isSuccessfulLoad = property(lambda self: self.__successfulLoad) skipEscape = property(lambda self: self.__skipEscape) ignoreKeyEvents = property(lambda self: self.__ignoreKeyEvents) useSpecialKeys = property(lambda self: self.__useSpecialKeys) allowRightClick = property(lambda self: self.__allowRightClick) allowMouseWheel = property(lambda self: self.__allowMouseWheel) @skipEscape.setter def skipEscape(self, value): LOG_BROWSER('skipEscape set %s (was: %s)' % (value, self.__skipEscape)) self.__skipEscape = value @ignoreKeyEvents.setter def ignoreKeyEvents(self, value): LOG_BROWSER('ignoreKeyEvents set %s (was: %s)' % (value, self.__ignoreKeyEvents)) self.__ignoreKeyEvents = value @useSpecialKeys.setter def useSpecialKeys(self, value): LOG_BROWSER('useSpecialKeys set %s (was: %s)' % (value, self.__useSpecialKeys)) self.__useSpecialKeys = value @allowRightClick.setter def allowRightClick(self, value): LOG_BROWSER('allowRightClick set %s (was: %s)' % (value, self.__allowRightClick)) self.__allowRightClick = value @allowMouseWheel.setter def allowMouseWheel(self, value): LOG_BROWSER('allowMouseWheel set %s (was: %s)' % (value, self.__allowMouseWheel)) self.__allowMouseWheel = value def __init__(self, browserID, uiObj, texName, size, url='about:blank', isFocused=False, handlers=None): """ :param browserID: id of the browser will be created :param uiObj: must be an object inherited from gui.Flash, which SWF should contain necessary callbacks (browserDown, browserUp, browserUp) :param texName: name of exported texture from SWF attached to uiObj :param size: tuple(width, height) of mapped texture in pixels :param url: optioal initial URL to open :param isFocused: initial value for isFocused attribute :param handlers: list of callable functions that will be called for each URL clicked on the browser page """ self.__browserID = browserID self.__cbID = None self.__baseUrl = url self.__uiObj = uiObj self.__texName = texName self.__browserSize = size self.__startFocused = isFocused self.__browser = None self.__delayedUrls = [] self.__isNavigationComplete = False self.__isFocused = False self.__navigationFilters = handlers or set() self.__skipEscape = True self.__ignoreKeyEvents = False self.__useSpecialKeys = True self.__allowRightClick = False self.__allowMouseWheel = True self.__allowAutoLoadingScreenChange = True self.__isCloseTriggered = False self.__eventMgr = EventManager() self.onLoadStart = Event(self.__eventMgr) self.onLoadEnd = Event(self.__eventMgr) self.onLoadingStateChange = Event(self.__eventMgr) self.onReadyToShowContent = Event(self.__eventMgr) self.onNavigate = Event(self.__eventMgr) self.onReady = Event(self.__eventMgr) self.onJsHostQuery = Event(self.__eventMgr) self.onTitleChange = Event(self.__eventMgr) self.onFailedCreation = Event(self.__eventMgr) self.onCanCreateNewBrowser = Event(self.__eventMgr) self.onUserRequestToClose = Event(self.__eventMgr) LOG_BROWSER('INIT ', self.__baseUrl, texName, size, self.__browserID) return def create(self): LOG_BROWSER('CREATE ', self.__baseUrl, self.__browserID) clientLanguage = helpers.getClientLanguage() self.__browser = BigWorld.createBrowser(self.__browserID, clientLanguage) if self.__browser is None: LOG_BROWSER('create() NO BROWSER WAS CREATED', self.__baseUrl) return False else: self.__browser.script = EventListener(self) self.__browser.script.onLoadStart += self.__onLoadStart self.__browser.script.onLoadEnd += self.__onLoadEnd self.__browser.script.onLoadingStateChange += self.__onLoadingStateChange self.__browser.script.onDOMReady += self.__onReadyToShowContent self.__browser.script.onCursorUpdated += self.__onCursorUpdated self.__browser.script.onReady += self.__onReady self.__browser.script.onJsHostQuery += self.__onJsHostQuery self.__browser.script.onTitleChange += self.__onTitleChange def injectBrowserKeyEvent(me, e): if _BROWSER_KEY_LOGGING: LOG_BROWSER('injectBrowserKeyEvent', (e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown())) me.__browser.injectKeyEvent(e) def injectKeyDown(me, e): injectBrowserKeyEvent(me, e) def injectKeyUp(me, e): injectBrowserKeyEvent(me, e) def resetBit(value, bitMask): return value & ~bitMask self.__specialKeyHandlers = ( (Keys.KEY_LEFTARROW, True, True, None, None, lambda me, _: me.__browser.goBack()), (Keys.KEY_RIGHTARROW, True, True, None, None, lambda me, _: me.__browser.goForward()), (Keys.KEY_F5, True, None, None, None, lambda me, _: me.__browser.reload())) self.__browserKeyHandlers = ( (Keys.KEY_LSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition))), (Keys.KEY_RSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition))), (Keys.KEY_LCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition))), (Keys.KEY_RCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition))), (None, True, None, None, None, lambda me, e: injectKeyDown(me, e)), (None, False, None, None, None, lambda me, e: injectKeyUp(me, e))) self.__disableKeyHandlers = [] return True def setDisabledKeys(self, keys): self.__disableKeyHandlers = [] for key, isKeyDown, isAltDown, isShiftDown, isCtrlDown in keys: self.__disableKeyHandlers.append( (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown, lambda me, e: None)) def ready(self, success): LOG_BROWSER('READY ', success, self.__baseUrl, self.__browserID) self.__ui = weakref.ref(self.__uiObj) self.__readyToShow = False self.__successfulLoad = False self.enableUpdate = True self.__isMouseDown = False self.__isFocused = False self.__isWaitingForUnfocus = False if success: browserSize = self.__browserSize self.__browser.setScaleformRender(self.__uiObj.movie, self.__texName, browserSize[0], browserSize[1]) self.__browser.activate(True) self.__browser.focus() self.__browser.loadURL(self.__baseUrl) if self.__startFocused: self.focus() self.update() g_mgr.addBrowser(self) self.onReady(self.__browser.url, success) else: self.__isNavigationComplete = True LOG_BROWSER(' FAILED ', self.__baseUrl, self.__browserID) self.onFailedCreation(self.__baseUrl) def updateSize(self, size): self.__browserSize = size if self.hasBrowser: self.__browser.resize(size[0], size[1]) def __processDelayedNavigation(self): if self.__isNavigationComplete and self.__delayedUrls: self.doNavigate(self.__delayedUrls.pop(0)) return True return False def destroy(self): self.__eventMgr.clear() self.__eventMgr = None if self.__browser is not None: LOG_BROWSER('DESTROYED ', self.__baseUrl, self.__browserID) self.__browser.script.clear() self.__browser.script = None self.__browser.resetScaleformRender(self.__uiObj.movie, self.__texName) BigWorld.removeBrowser(self.__browserID) self.__browser = None if self.__cbID is not None: BigWorld.cancelCallback(self.__cbID) self.__cbID = None self.__ui = None self.__navigationFilters = None if self.__uiObj is not None: self.__uiObj.cursorMgr.setCursorForced(Cursor.ARROW) g_mgr.delBrowser(self) return def focus(self): if self.hasBrowser and not self.isFocused: self.__browser.focus() self.__isFocused = True ui = self.__ui() if ui: ui.cursorMgr.setCursorForced(self.__browser.script.cursorType) def unfocus(self): if self.hasBrowser and self.isFocused: self.__browser.unfocus() self.__isFocused = False self.__isWaitingForUnfocus = False def refresh(self, ignoreCache=True): if BigWorld.time() - self.__loadStartTime < 0.5: LOG_BROWSER('refresh - called too soon') return if self.hasBrowser: self.__browser.reload() self.onNavigate(self.__browser.url) def navigate(self, url): lastIsSame = self.__delayedUrls and self.__delayedUrls[-1] == url if not lastIsSame: self.__delayedUrls.append(url) self.__processDelayedNavigation() def sendMessage(self, message): if self.hasBrowser: self.__browser.sendMessage(message) def doNavigate(self, url): LOG_BROWSER('doNavigate', url) self.__baseUrl = url if self.hasBrowser: self.__browser.script.newNavigation() self.__browser.loadURL(url) self.onNavigate(url) def navigateBack(self): if self.hasBrowser: self.__browser.goBack(self.url) def navigateForward(self): if self.hasBrowser: self.__browser.goForward(self.url) def navigateStop(self): if BigWorld.time() - self.__loadStartTime < 0.5: LOG_BROWSER('navigateStop - called too soon') return if self.hasBrowser: self.__browser.stop() self.__onLoadEnd(self.__browser.url) def update(self): self.__cbID = BigWorld.callback(self.updateInterval, self.update) def __getBrowserKeyHandler(self, key, isKeyDown, isAltDown, isShiftDown, isCtrlDown): from itertools import izip params = (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown) matches = lambda t: t[0] is None or t[0] == t[1] browserKeyHandlers = tuple( self.__disableKeyHandlers) + self.__browserKeyHandlers if self.useSpecialKeys: browserKeyHandlers = self.__specialKeyHandlers + browserKeyHandlers for values in browserKeyHandlers: if reduce(lambda a, b: a and matches(b), izip(values, params), True): return values[-1] return None def handleKeyEvent(self, event): e = event keyState = (e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown()) if not (self.hasBrowser and self.enableUpdate): return False if not self.allowRightClick and e.key == Keys.KEY_RIGHTMOUSE: return False if not self.skipEscape and e.key == Keys.KEY_ESCAPE and e.isKeyDown(): self.__getBrowserKeyHandler(*keyState)(self, e) return True if not self.isFocused: self.__browser.injectKeyModifiers(e) return False if _BROWSER_KEY_LOGGING: LOG_BROWSER('handleKeyEvent', keyState) if self.ignoreKeyEvents and e.key not in (Keys.KEY_LEFTMOUSE, Keys.KEY_RIGHTMOUSE): return False if e.key in (Keys.KEY_ESCAPE, Keys.KEY_SYSRQ): return False if e.key in (Keys.KEY_RETURN, Keys.KEY_NUMPADENTER) and e.isAltDown(): return False self.__getBrowserKeyHandler(*keyState)(self, e) return True def browserMove(self, x, y, z): if not (self.hasBrowser and self.enableUpdate and self.isFocused): return if z != 0: if self.allowMouseWheel: self.__browser.injectMouseWheelEvent(z * 20) return self.__browser.injectMouseMoveEvent(x, y) def browserDown(self, x, y, z): if not (self.hasBrowser and self.enableUpdate): return if self.__isMouseDown: return if not self.isFocused: self.focus() self.__isMouseDown = True self.browserUp(x, y, z) self.browserMove(x, y, z) self.__isMouseDown = True def browserUp(self, x, y, z): if not (self.hasBrowser and self.enableUpdate): return if not self.__isMouseDown: return self.__isMouseDown = False if self.__isWaitingForUnfocus: self.unfocus() def browserFocusOut(self): if self.isFocused and self.__isMouseDown: self.__isWaitingForUnfocus = True return self.unfocus() def browserAction(self, action): if self.hasBrowser and self.enableUpdate: if action == 'reload' and self.isNavigationComplete: self.refresh() elif action == 'loading' and not self.isNavigationComplete: self.navigateStop() def onBrowserShow(self, needRefresh): self.enableUpdate = True if needRefresh and self.baseUrl != self.url: self.navigate(self.url) self.focus() def onBrowserHide(self): self.navigate(self.__baseUrl) self.enableUpdate = False self.unfocus() def addFilter(self, handler): if handler in self.__navigationFilters: LOG_ERROR('Navigation filter is already added', handler) else: self.__navigationFilters.add(handler) def removeFilter(self, handler): if handler in self.__navigationFilters: self.__navigationFilters.discard(handler) else: LOG_ERROR("Trying to delete navigation filter which doesn't exist", handler) def filterNavigation(self, url): query = urlparse.urlparse(url).query tags = urlparse.parse_qs(query).get(_WOT_CLIENT_PARAM_NAME, []) stopNavigation = False closeBrowser = False for handler in self.__navigationFilters: try: result = handler(url, tags) stopNavigation |= result.stopNavigation closeBrowser |= result.closeBrowser if result.stopNavigation: LOG_DEBUG('Navigation filter triggered navigation stop:', handler) if result.closeBrowser: LOG_DEBUG('Navigation filter triggered browser close:', handler) except: LOG_CURRENT_EXCEPTION() self.__isCloseTriggered = closeBrowser return stopNavigation def setLoadingScreenVisible(self, visible): LOG_BROWSER('setLoadingScreenVisible', visible) self.onLoadingStateChange(visible, True) def setAllowAutoLoadingScreen(self, enabled): LOG_BROWSER('setAllowAutoLoadingScreen', enabled) self.__allowAutoLoadingScreenChange = enabled def changeTitle(self, title): """ Changes title. Is used by BrowserController @param title: @return: """ self.onTitleChange(title) def __onLoadStart(self, url): if url == self.__browser.url: self.__isNavigationComplete = False self.__loadStartTime = BigWorld.time() LOG_BROWSER('onLoadStart', self.__browser.url) self.onLoadStart(self.__browser.url) self.__readyToShow = False self.__successfulLoad = False def __onLoadEnd(self, url, isLoaded=True, httpStatusCode=None): if url == self.__browser.url: self.__isNavigationComplete = True self.__successfulLoad = isLoaded if not self.__processDelayedNavigation(): LOG_BROWSER('onLoadEnd', self.__browser.url, isLoaded, httpStatusCode) self.onLoadEnd(self.__browser.url, isLoaded, httpStatusCode) def __onLoadingStateChange(self, isLoading): LOG_BROWSER('onLoadingStateChange', isLoading, self.__allowAutoLoadingScreenChange) self.onLoadingStateChange(isLoading, self.__allowAutoLoadingScreenChange) if self.__isCloseTriggered: event_dispatcher.hideWebBrowser(self.__browserID) elif not isLoading: self.onCanCreateNewBrowser() def __onReadyToShowContent(self, url): if url == self.__browser.url: LOG_BROWSER('onReadyToShowContent', self.__browser.url) self.__readyToShow = True self.onReadyToShowContent(self.__browser.url) def __isValidTitle(self, title): if self.__browser.url.startswith('about:'): return False if self.__browser.url.endswith(title): return False if self.__browser.url.endswith('/'): secondtest = self.__browser.url[:-1] if secondtest.endswith(title): return False if self.__baseUrl == title or self.__baseUrl.endswith(title): return False return True def __onTitleChange(self, title): if self.__isValidTitle(title): LOG_BROWSER('onTitleChange', title, self.__browser.url) self.onTitleChange(title) def __onCursorUpdated(self): if self.hasBrowser and self.isFocused: ui = self.__ui() if ui: ui.cursorMgr.setCursorForced(self.__browser.script.cursorType) def __onReady(self, success): self.ready(success) def __onJsHostQuery(self, command): self.onJsHostQuery(command) def executeJavascript(self, script, frame): if self.hasBrowser: self.__browser.executeJavascript(script, frame)
class WebBrowser(object): hasBrowser = property(lambda self: self.__browser is not None) initializationUrl = property(lambda self: self.__baseUrl) baseUrl = property(lambda self: '' if self.__browser is None else self.__baseUrl) url = property(lambda self: '' if self.__browser is None else self.__browser.url) width = property(lambda self: 0 if self.__browser is None else self.__browser.width) height = property(lambda self: 0 if self.__browser is None else self.__browser.height) isNavigationComplete = property(lambda self: self.__isNavigationComplete) isFocused = property(lambda self: self.__isFocused) isAudioPlaying = property(lambda self: self.__isAudioPlaying) textureUrl = property(lambda self: self.__textureUrl) updateInterval = 0.01 isSuccessfulLoad = property(lambda self: self.__successfulLoad) skipEscape = property(lambda self: self.__skipEscape) ignoreKeyEvents = property(lambda self: self.__ignoreKeyEvents) ignoreAltKey = property(lambda self: self.__ignoreAltKey) ignoreCtrlClick = property(lambda self: self.__ignoreCtrlClick) ignoreShiftClick = property(lambda self: self.__ignoreShiftClick) useSpecialKeys = property(lambda self: self.__useSpecialKeys) allowMiddleClick = property(lambda self: self.__allowMiddleClick) allowRightClick = property(lambda self: self.__allowRightClick) allowMouseWheel = property(lambda self: self.__allowMouseWheel) @skipEscape.setter def skipEscape(self, value): _logger.debug('skipEscape set %s (was: %s)', value, self.__skipEscape) self.__skipEscape = value @ignoreKeyEvents.setter def ignoreKeyEvents(self, value): _logger.debug('ignoreKeyEvents set %s (was: %s)', value, self.__ignoreKeyEvents) self.__ignoreKeyEvents = value @ignoreAltKey.setter def ignoreAltKey(self, value): _logger.debug('ignoreAltKey set %s (was: %s)', value, self.__ignoreAltKey) self.__ignoreAltKey = value @ignoreCtrlClick.setter def ignoreCtrlClick(self, value): _logger.debug('ignoreCtrlClick set %s (was: %s)', value, self.__ignoreCtrlClick) self.__ignoreCtrlClick = value @ignoreShiftClick.setter def ignoreShiftClick(self, value): _logger.debug('ignoreShiftClick set %s (was: %s)', value, self.__ignoreShiftClick) self.__ignoreShiftClick = value @useSpecialKeys.setter def useSpecialKeys(self, value): _logger.debug('useSpecialKeys set %s (was: %s)', value, self.__useSpecialKeys) self.__useSpecialKeys = value @allowMiddleClick.setter def allowMiddleClick(self, value): _logger.debug('allowMiddleClick set %s (was: %s)', value, self.__allowMiddleClick) self.__allowMiddleClick = value @allowRightClick.setter def allowRightClick(self, value): _logger.debug('allowRightClick set %s (was: %s)', value, self.__allowRightClick) self.__allowRightClick = value @allowMouseWheel.setter def allowMouseWheel(self, value): _logger.debug('allowMouseWheel set %s (was: %s)', value, self.__allowMouseWheel) self.__allowMouseWheel = value def __init__(self, browserID, uiObj, size, url='about:blank', isFocused=False, handlers=None): self.__browserID = browserID self.__cbID = None self.__baseUrl = url self.__uiObj = uiObj self.__browserSize = size + (1.0, ) self.__startFocused = isFocused self.__browser = None self.__isNavigationComplete = False self.__loadStartTime = None self.__isFocused = False self.__isAudioPlaying = False self.__navigationFilters = handlers or set() self.__skipEscape = True self.__ignoreKeyEvents = False self.__ignoreAltKey = False self.__ignoreCtrlClick = True self.__ignoreShiftClick = True self.__useSpecialKeys = True self.__allowMiddleClick = False self.__allowRightClick = False self.__allowMouseWheel = True self.__allowAutoLoadingScreenChange = True self.__isCloseTriggered = False self.__isAudioMutable = False self.__ctrlDown = False self.__shiftDown = False self.__textureUrl = '' self.__eventMgr = EventManager() self.onLoadStart = Event(self.__eventMgr) self.onLoadEnd = Event(self.__eventMgr) self.onLoadingStateChange = Event(self.__eventMgr) self.onReadyToShowContent = Event(self.__eventMgr) self.onNavigate = Event(self.__eventMgr) self.onReady = Event(self.__eventMgr) self.onJsHostQuery = Event(self.__eventMgr) self.onTitleChange = Event(self.__eventMgr) self.onFailedCreation = Event(self.__eventMgr) self.onCanCreateNewBrowser = Event(self.__eventMgr) self.onUserRequestToClose = Event(self.__eventMgr) self.onAudioStatusChanged = Event(self.__eventMgr) _logger.info('INIT %s size %s, id: %s', self.__baseUrl, size, self.__browserID) levelSetting = Settings.g_instance.engineConfig['webBrowser'][ 'logVerbosity'].asString levelSettingEnum = LogSeverity[levelSetting] _webAppLogger.setLevel( _LOG_SEVERITY_TO_LOG_LEVEL_MAP[levelSettingEnum]) return def create(self): _logger.info('CREATE %s id: %s', self.__baseUrl, self.__browserID) self.__browser = BigWorld.createWebView(self.__browserID) if self.__browser is None: _logger.error('create() NO BROWSER WAS CREATED: %s', self.__baseUrl) return False else: self.__browser.script = EventListener(self) self.__browser.script.onLoadStart += self.__onLoadStart self.__browser.script.onLoadEnd += self.__onLoadEnd self.__browser.script.onLoadingStateChange += self.__onLoadingStateChange self.__browser.script.onDOMReady += self.__onReadyToShowContent self.__browser.script.onCursorUpdated += self.__onCursorUpdated self.__browser.script.onReady += self.__onReady self.__browser.script.onJsHostQuery += self.__onJsHostQuery self.__browser.script.onTitleChange += self.__onTitleChange self.__browser.script.onDestroy += self.__onDestroy self.__browser.script.onAudioStatusChanged += self.__onAudioStatusChanged self.__browser.script.onConsoleMessage += self.__onConsoleMessage self.__browser.script.isBrowserPlayingAudio = False def injectBrowserKeyEvent(me, e): if _BROWSER_KEY_LOGGING: _logger.debug('injectBrowserKeyEvent: %s', (e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown())) me.__browser.injectKeyEvent(e) def injectKeyDown(me, e): injectBrowserKeyEvent(me, e) def injectKeyUp(me, e): injectBrowserKeyEvent(me, e) def resetBit(value, bitMask): return value & ~bitMask self.__specialKeyHandlers = ( (Keys.KEY_LEFTARROW, True, True, None, None, lambda me, _: me.__browser.goBack()), (Keys.KEY_RIGHTARROW, True, True, None, None, lambda me, _: me.__browser.goForward()), (Keys.KEY_F5, True, None, None, None, lambda me, _: me.__browser.reload())) self.__browserKeyHandlers = ( (Keys.KEY_LSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition))), (Keys.KEY_RSHIFT, False, None, True, None, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 1), None, e. cursorPosition))), (Keys.KEY_LCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition))), (Keys.KEY_RCONTROL, False, None, None, True, lambda me, e: injectKeyUp( me, BigWorld.KeyEvent(e.key, e.repeatCount, resetBit(e.modifiers, 2), None, e. cursorPosition))), (None, True, None, None, None, injectKeyDown), (None, False, None, None, None, injectKeyUp)) self.__disableKeyHandlers = [] return True def setDisabledKeys(self, keys): self.__disableKeyHandlers = [] for key, isKeyDown, isAltDown, isShiftDown, isCtrlDown in keys: self.__disableKeyHandlers.append( (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown, lambda me, e: None)) def ready(self, success): _logger.info('READY success: %r %s id: %s', success, self.__baseUrl, self.__browserID) self.__ui = weakref.ref(self.__uiObj) self.__readyToShow = False self.__successfulLoad = False self.enableUpdate = True self.__isMouseDown = False self.__isFocused = False self.__isWaitingForUnfocus = False if success: browserSize = self.__browserSize self.__textureUrl = self.__browser.setScaleformRender( str(self.__browserID), browserSize[0], browserSize[1], browserSize[2]) _logger.info('READY scaleform texture url: %s', self.__textureUrl) self.__browser.activate(True) self.__browser.focus() self.__browser.loadURL(self.__baseUrl) if self.__startFocused: self.focus() g_mgr.addBrowser(self) self.onReady(self.__browser.url, success) self.onCanCreateNewBrowser() else: self.__isNavigationComplete = True _logger.error(' FAILED %s id: %s', self.__baseUrl, self.__browserID) self.onFailedCreation(self.__baseUrl) def invalidateView(self): if self.hasBrowser: self.__browser.invalidate() def updateSize(self, size): self.__browserSize = size if self.hasBrowser: self.__browser.resize(size[0], size[1], size[2]) def destroy(self): if self.__eventMgr is not None: self.__eventMgr.clear() self.__eventMgr = None if self.__browser is not None: _logger.info('DESTROYED %s id: %s', self.__baseUrl, self.__browserID) self.__onAudioStatusChanged(isPlaying=False) self.__browser.script.clear() self.__browser.script = None self.__browser.resetScaleformRender() BigWorld.destroyWebView(self.__browserID) self.__browser = None if self.__cbID is not None: BigWorld.cancelCallback(self.__cbID) self.__cbID = None self.__ui = None self.__navigationFilters = None self.__setUICursor(self.__uiObj, CursorManager.ARROW) g_mgr.delBrowser(self) return def focus(self): if self.hasBrowser and not self.isFocused: self.__browser.focus() self.__isFocused = True self.__setUICursor(self.__ui(), self.__browser.script.cursorType) def unfocus(self): if self.hasBrowser and self.isFocused: self.__browser.unfocus() self.__isFocused = False self.__isWaitingForUnfocus = False def refresh(self, ignoreCache=True): if self.__loadStartTime is None or BigWorld.time( ) - self.__loadStartTime < 0.5: _logger.debug('refresh - called too soon') return else: if self.hasBrowser: self.__browser.reload() self.onNavigate(self.__browser.url) return def navigate(self, url): _logger.debug('navigate %s', url) self.__baseUrl = url if self.hasBrowser: self.__browser.script.newNavigation() self.__browser.loadURL(url) self.onNavigate(url) def sendMessage(self, message): if self.hasBrowser: self.__browser.sendMessage(message) def sendEvent(self, webEvent): if self.hasBrowser: self.__browser.sendEvent(webEvent) def navigateBack(self): if self.hasBrowser: self.__browser.goBack(self.url) def navigateForward(self): if self.hasBrowser: self.__browser.goForward(self.url) def navigateStop(self): if self.__loadStartTime is None or BigWorld.time( ) - self.__loadStartTime < 0.5: _logger.debug('navigateStop - called too soon') return else: if self.hasBrowser: self.__browser.stop() self.__onLoadEnd(self.__browser.url) return def __getBrowserKeyHandler(self, key, isKeyDown, isAltDown, isShiftDown, isCtrlDown): from itertools import izip params = (key, isKeyDown, isAltDown, isShiftDown, isCtrlDown) def matches(t): return t[0] is None or t[0] == t[1] browserKeyHandlers = tuple( self.__disableKeyHandlers) + self.__browserKeyHandlers if self.useSpecialKeys: browserKeyHandlers = self.__specialKeyHandlers + browserKeyHandlers for values in browserKeyHandlers: if functools.reduce(lambda a, b: a and matches(b), izip(values, params), True): return values[-1] return None def handleKeyEvent(self, event): e = event keyState = (e.key, e.isKeyDown(), e.isAltDown(), e.isShiftDown(), e.isCtrlDown()) toolTipMgr = self.__uiObj.getToolTipMgr() if toolTipMgr and toolTipMgr.isReadyToHandleKey(event): return False if e.key in (Keys.KEY_LCONTROL, Keys.KEY_RCONTROL): self.__ctrlDown = e.isKeyDown() if self.__ignoreCtrlClick and self.__ctrlDown and e.key == Keys.KEY_LEFTMOUSE: return False if e.key in (Keys.KEY_LSHIFT, Keys.KEY_RSHIFT): self.__shiftDown = e.isKeyDown() if self.__ignoreShiftClick and self.__shiftDown and e.key == Keys.KEY_LEFTMOUSE: return False if self.__ignoreAltKey and e.key in (Keys.KEY_LALT, Keys.KEY_RALT): return False if not (self.hasBrowser and self.enableUpdate): return False if not self.allowMiddleClick and e.key == Keys.KEY_MIDDLEMOUSE: return False if not self.allowRightClick and e.key == Keys.KEY_RIGHTMOUSE: return False if not self.skipEscape and e.key == Keys.KEY_ESCAPE and e.isKeyDown(): self.__getBrowserKeyHandler(*keyState)(self, e) return True if not self.isFocused: self.__browser.injectKeyModifiers(e) return False if _BROWSER_KEY_LOGGING: _logger.debug('handleKeyEvent %s', keyState) if self.ignoreKeyEvents and e.key not in (Keys.KEY_LEFTMOUSE, Keys.KEY_RIGHTMOUSE, Keys.KEY_MIDDLEMOUSE): return False if e.key in (Keys.KEY_ESCAPE, Keys.KEY_SYSRQ): return False if e.key in (Keys.KEY_RETURN, Keys.KEY_NUMPADENTER) and e.isAltDown(): return False self.__getBrowserKeyHandler(*keyState)(self, e) return True def browserMove(self, x, y, z): if not (self.hasBrowser and self.enableUpdate and self.isFocused): return if z != 0: if self.allowMouseWheel: self.__browser.injectMouseWheelEvent(z * 20) return self.__browser.injectMouseMoveEvent(x, y) def browserDown(self, x, y, z): if not (self.hasBrowser and self.enableUpdate): return if self.__isMouseDown: return if not self.isFocused: self.focus() self.__isMouseDown = True self.browserUp(x, y, z) self.browserMove(x, y, z) self.__isMouseDown = True def browserUp(self, x, y, z): if not (self.hasBrowser and self.enableUpdate): return if not self.__isMouseDown: return self.__isMouseDown = False if self.__isWaitingForUnfocus: self.unfocus() def browserFocusOut(self): if self.isFocused and self.__isMouseDown: self.__isWaitingForUnfocus = True return self.unfocus() def browserAction(self, action): if self.hasBrowser and self.enableUpdate: if action == 'reload' and self.isNavigationComplete: self.refresh() elif action == 'loading' and not self.isNavigationComplete: self.navigateStop() def onBrowserShow(self, needRefresh): self.enableUpdate = True if needRefresh and self.baseUrl != self.url: self.navigate(self.url) self.focus() def onBrowserHide(self): self.navigate(self.__baseUrl) self.enableUpdate = False self.unfocus() def addFilter(self, handler): if handler in self.__navigationFilters: _logger.error('Navigation filter is already added: %r', handler) else: self.__navigationFilters.add(handler) def removeFilter(self, handler): if handler in self.__navigationFilters: self.__navigationFilters.discard(handler) else: _logger.error( "Trying to delete navigation filter which doesn't exist: %r", handler) def filterNavigation(self, url): query = urlparse.urlparse(url).query tags = urlparse.parse_qs(query).get(_WOT_CLIENT_PARAM_NAME, []) stopNavigation = False closeBrowser = False for handler in self.__navigationFilters: try: result = handler(url, tags) stopNavigation |= result.stopNavigation closeBrowser |= result.closeBrowser if result.stopNavigation: _logger.debug( 'Navigation filter triggered navigation stop: %s', handler) if result.closeBrowser: _logger.debug( 'Navigation filter triggered browser close: %s', handler) except Exception: LOG_CURRENT_EXCEPTION() self.__isCloseTriggered = closeBrowser return stopNavigation def onResourceLoadRequest(self, url): result = urlparse.urlparse(url) return result.netloc + result.path if result.scheme == _WOT_RESOURCE_CUSTOM_SCHEME else _g_webCache.get( url) def setAllowAutoLoadingScreen(self, enabled): _logger.debug('setAllowAutoLoadingScreen %s', enabled) self.__allowAutoLoadingScreenChange = enabled def setIsAudioMutable(self, isAudioMutable): self.__isAudioMutable = isAudioMutable def changeTitle(self, title): self.onTitleChange(title) def __onLoadStart(self, url): if url == self.__browser.url: self.__isNavigationComplete = False self.__loadStartTime = BigWorld.time() _logger.debug('onLoadStart %s', self.__browser.url) self.onLoadStart(self.__browser.url) self.__readyToShow = False self.__successfulLoad = False def __onLoadEnd(self, url, isLoaded=True, httpStatusCode=None, errorDesc=None): if url == self.__browser.url or errorDesc: self.__isNavigationComplete = True self.__successfulLoad = isLoaded if not isLoaded or httpStatusCode and httpStatusCode >= 400 or errorDesc: _logger.error( 'FAILED Url: %s, Http code: %r, Browser error: %s', self.__browser.url, httpStatusCode, errorDesc) self.onLoadEnd(self.__browser.url, isLoaded, httpStatusCode) def __onLoadingStateChange(self, isLoading): _logger.debug('onLoadingStateChange %r %r', isLoading, self.__allowAutoLoadingScreenChange) self.onLoadingStateChange(isLoading, self.__allowAutoLoadingScreenChange) if self.__isCloseTriggered: event_dispatcher.hideWebBrowser(self.__browserID) def __onReadyToShowContent(self, url): if url == self.__browser.url: _logger.debug('onReadyToShowContent %s', self.__browser.url) self.__readyToShow = True self.onReadyToShowContent(self.__browser.url) def __isValidTitle(self, title): if self.__browser.url.startswith('about:'): return False if self.__browser.url.endswith(title): return False if self.__browser.url.endswith('/'): secondtest = self.__browser.url[:-1] if secondtest.endswith(title): return False if self.__baseUrl == title or self.__baseUrl.endswith(title): return False return False if title.startswith('http://') or title.startswith( 'https://') else True def __setUICursor(self, ui, cursorType): if ui and cursorType: ui.cursorMgr.setCursorForced(cursorType) def __onTitleChange(self, title): if self.__isValidTitle(title): _logger.debug('onTitleChange title: %s %s', title, self.__browser.url) self.onTitleChange(title) def __onCursorUpdated(self): if self.hasBrowser and self.isFocused: self.__setUICursor(self.__ui(), self.__browser.script.cursorType) def __onReady(self, success): self.ready(success) def __onDestroy(self): _logger.info('Destroy Web View %s - %r', self.__baseUrl, self.__browserID) self.destroy() def __onJsHostQuery(self, command): self.onJsHostQuery(command) def __onConsoleMessage(self, level, message, lineNumber, source, viewId): try: levelEnum = [l for l in LogSeverity if l.value == level][0] except IndexError: levelEnum = LogSeverity.disable if levelEnum != LogSeverity.disable: _webAppLogger.log(_LOG_SEVERITY_TO_LOG_LEVEL_MAP[levelEnum], '%s, line %s, viewId %s: %s', source, lineNumber, viewId, message) def __onAudioStatusChanged(self, isPlaying): if self.__isAudioMutable: self.__isAudioPlaying = bool(isPlaying) g_mgr.updateGameAudio() def executeJavascript(self, script, frame): if self.hasBrowser: self.__browser.executeJavascript(script, frame)
class EventsCache(IEventsCache): USER_QUESTS = (EVENT_TYPE.BATTLE_QUEST, EVENT_TYPE.TOKEN_QUEST, EVENT_TYPE.PERSONAL_QUEST, EVENT_TYPE.PERSONAL_MISSION) SYSTEM_QUESTS = (EVENT_TYPE.REF_SYSTEM_QUEST,) lobbyContext = dependency.descriptor(ILobbyContext) rareAchievesCache = dependency.descriptor(IRaresCache) linkedSet = dependency.descriptor(ILinkedSetController) def __init__(self): self.__waitForSync = False self.__invalidateCbID = None self.__cache = defaultdict(dict) self.__personalMissionsHidden = {} self.__actionsCache = defaultdict(lambda : defaultdict(dict)) self.__actions2quests = {} self.__quests2actions = {} self.__questsDossierBonuses = defaultdict(set) self.__compensations = {} self.__personalMissions = PersonalMissionsCache() self.__questsProgress = QuestsProgressRequester() self.__em = EventManager() self.__prefetcher = Prefetcher(self) self.onSyncStarted = Event(self.__em) self.onSyncCompleted = Event(self.__em) self.onProgressUpdated = Event(self.__em) self.onMissionVisited = Event(self.__em) self.onEventsVisited = Event(self.__em) self.onProfileVisited = Event(self.__em) self.onPersonalQuestsVisited = Event(self.__em) self.__lockedQuestIds = {} return def init(self): self.__personalMissions.init() self.__prefetcher.init() def fini(self): self.__personalMissions.fini() self.__prefetcher.fini() self.__em.clear() self.__compensations.clear() self.__clearInvalidateCallback() def start(self): self.__lockedQuestIds = BigWorld.player().personalMissionsLock g_playerEvents.onPMLocksChanged += self.__onLockedQuestsChanged self.lobbyContext.getServerSettings().onServerSettingsChange += self.__onServerSettingsChange def stop(self): self.lobbyContext.getServerSettings().onServerSettingsChange -= self.__onServerSettingsChange g_playerEvents.onPMLocksChanged -= self.__onLockedQuestsChanged self.__clearCache() def clear(self): self.stop() quests_caches.clearNavInfo() @property def waitForSync(self): return self.__waitForSync @property def questsProgress(self): return self.__questsProgress def getPersonalMissions(self): return self.__personalMissions @property def prefetcher(self): return self.__prefetcher def getLockedQuestTypes(self, branch): questIDs = set() result = set() allQuests = self.getPersonalMissions().getQuestsForBranch(branch) for lockedList in self.__lockedQuestIds.values(): if lockedList is not None: questIDs.update(lockedList) for questID in questIDs: if questID in allQuests: result.add(allQuests[questID].getMajorTag()) return result @async @process def update(self, diff=None, callback=None): clearModifiersCache() yield self.getPersonalMissions().questsProgressRequest() if not self.getPersonalMissions().isQuestsProgressSynced(): callback(False) return else: yield self.__questsProgress.request() if not self.__questsProgress.isSynced(): callback(False) return isNeedToInvalidate = True isNeedToClearItemsCaches = False def _cbWrapper(*args): callback(*args) self.__personalMissions.update(self, diff) if diff is not None: isQPUpdated = 'quests' in diff or 'tokens' in diff isEventsDataUpdated = ('eventsData', '_r') in diff or diff.get('eventsData', {}) isNeedToInvalidate = isQPUpdated or isEventsDataUpdated hasVehicleUnlocks = False for intCD in diff.get('stats', {}).get('unlocks', set()): if getTypeOfCompactDescr(intCD) == GUI_ITEM_TYPE.VEHICLE: hasVehicleUnlocks = True break isNeedToClearItemsCaches = hasVehicleUnlocks or 'inventory' in diff and GUI_ITEM_TYPE.VEHICLE in diff['inventory'] if isNeedToInvalidate: self.__invalidateData(_cbWrapper) return if isNeedToClearItemsCaches: self.__clearQuestsItemsCache() _cbWrapper(True) return def getQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return not q.isHidden() and filterFunc(q) return self._getQuests(userFilterFunc) def getActiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return False if isLinkedSet(q.getGroupID()) and not self.linkedSet.isLinkedSetEnabled() else q.getFinishTimeLeft() and filterFunc(q) return self.getQuests(userFilterFunc) def getAdvisableQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): if q.getType() == EVENT_TYPE.MOTIVE_QUEST and not q.isAvailable().isValid: return False if q.getType() == EVENT_TYPE.TOKEN_QUEST and isMarathon(q.getID()): return False return False if isLinkedSet(q.getGroupID()) and not q.isAvailable().isValid else filterFunc(q) return self.getActiveQuests(userFilterFunc) def getMotiveQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.MOTIVE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getLinkedSetQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return isLinkedSet(q.getGroupID()) and filterFunc(q) return self.getQuests(userFilterFunc) def getBattleQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return q.getType() == EVENT_TYPE.BATTLE_QUEST and filterFunc(q) return self.getQuests(userFilterFunc) def getGroups(self, filterFunc=None): svrGroups = self._getQuestsGroups(filterFunc) svrGroups.update(self._getActionsGroups(filterFunc)) return svrGroups def getHiddenQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def hiddenFilterFunc(q): return q.isHidden() and filterFunc(q) return self._getQuests(hiddenFilterFunc) def getRankedQuests(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def rankedFilterFunc(q): return q.getType() == EVENT_TYPE.RANKED_QUEST and filterFunc(q) return self._getQuests(rankedFilterFunc) def getAllQuests(self, filterFunc=None, includePersonalMissions=False): return self._getQuests(filterFunc, includePersonalMissions) def getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) def userFilterFunc(q): return filterFunc(q) and q.getType() != EVENT_TYPE.GROUP return self._getActions(userFilterFunc) def getActionEntities(self): return self.__getActionsEntitiesData() def getAnnouncedActions(self): return self.__getAnnouncedActions() def getEventBattles(self): battles = self.__getEventBattles() return EventBattles(battles.get('vehicleTags', set()), battles.get('vehicles', []), bool(battles.get('enabled', 0)), battles.get('arenaTypeID')) if battles else EventBattles(set(), [], 0, None) def isEventEnabled(self): return len(self.__getEventBattles()) > 0 and len(self.getEventVehicles()) > 0 @dependency.replace_none_kwargs(itemsCache=IItemsCache) def getEventVehicles(self, itemsCache=None): result = [] if itemsCache is None: return result else: for v in self.getEventBattles().vehicles: item = itemsCache.items.getItemByCD(v) if item.isInInventory: result.append(item) return sorted(result) def getEvents(self, filterFunc=None): svrEvents = self.getQuests(filterFunc) svrEvents.update(self.getActions(filterFunc)) return svrEvents def getCurrentEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() <= 0 < q.getFinishTimeLeft()) def getFutureEvents(self): return self.getEvents(lambda q: q.getStartTimeLeft() > 0) def getAffectedAction(self, item): actionEntities = self.getActionEntities() if actionEntities: entities = actionEntities[aei.ENTITIES_SECTION_NAME] actions = actionEntities[aei.ACTIONS_SECTION_NAME] steps = actionEntities[aei.STEPS_SECTION_NAME] if item in entities: entity = entities[item] actionNameIdx = entity[aei.ACTION_NAME_IDX] actionName = actions[actionNameIdx] stepNameIdx = entity[aei.ACTION_STEP_IDX] actionStep = steps[stepNameIdx] intersectedActions = entity[aei.AFFECTED_ACTIONS_IDX] return [actionName, actionStep, intersectedActions] return [] def getItemAction(self, item, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(15, []) for (key, value), actionID in values: if item.isPremium and key in ('creditsPrice', 'creditsPriceMultiplier') and not forCredits: continue result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get(itemTypeID, {}).get(intCD, tuple())) return result def getBoosterAction(self, booster, isBuying=True, forCredits=False): result = [] actionType = ACTION_MODIFIER_TYPE.DISCOUNT if isBuying else ACTION_MODIFIER_TYPE.SELLING boosterID = booster.boosterID values = self.__actionsCache[ACTION_SECTION_TYPE.ALL_BOOSTERS][actionType].get(nations.NONE_INDEX, []) for (key, value), actionID in values: if forCredits and key == 'creditsPriceMultiplier': result.append((value, actionID)) if not forCredits and key == 'goldPriceMultiplier': result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.BOOSTER][actionType].get(boosterID, tuple())) return result def getRentAction(self, item, rentPackage): result = [] actionType = ACTION_MODIFIER_TYPE.RENT itemTypeID = item.itemTypeID nationID = item.nationID intCD = item.intCD values = self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(nationID, []) values += self.__actionsCache[ACTION_SECTION_TYPE.ALL][actionType].get(itemTypeID, {}).get(15, []) for (_, value), actionID in values: result.append((value, actionID)) result.extend(self.__actionsCache[ACTION_SECTION_TYPE.ITEM][actionType].get(itemTypeID, {}).get((intCD, rentPackage), tuple())) return result def getEconomicsAction(self, name): result = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get(name, []) resultMult = self.__actionsCache[ACTION_SECTION_TYPE.ECONOMICS][ACTION_MODIFIER_TYPE.DISCOUNT].get('%sMultiplier' % name, []) return tuple(result + resultMult) def isBalancedSquadEnabled(self): return bool(self.__getUnitRestrictions().get('enabled', False)) def getBalancedSquadBounds(self): return (self.__getUnitRestrictions().get('lowerBound', 0), self.__getUnitRestrictions().get('upperBound', 0)) def isSquadXpFactorsEnabled(self): return bool(self.__getUnitXpFactors().get('enabled', False)) def getSquadBonusLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithBonuses', ())) def getSquadPenaltyLevelDistance(self): return set(self.__getUnitXpFactors().get('levelDistanceWithPenalties', ())) def getSquadZeroBonuses(self): return set(self.__getUnitXpFactors().get('zeroBonusesFor', ())) def getQuestsDossierBonuses(self): return self.__questsDossierBonuses def getQuestsByTokenRequirement(self, token): result = [] for q in self._getQuests(includePersonalMissions=True).itervalues(): if token in [ t.getID() for t in q.accountReqs.getTokens() ]: result.append(q) return result def getQuestsByTokenBonus(self, token): result = [] for q in self._getQuests(includePersonalMissions=True).itervalues(): for t in q.getBonuses('tokens'): if token in t.getTokens().keys(): result.append(q) break return result def getCompensation(self, tokenID): return self.__compensations.get(tokenID) def hasQuestDelayedRewards(self, questID): return self.__questsProgress.hasQuestDelayedRewards(questID) def _getQuests(self, filterFunc=None, includePersonalMissions=False): result = {} groups = {} filterFunc = filterFunc or (lambda a: True) for qID, q in self.__getCommonQuestsIterator(): if qID in self.__quests2actions: q.linkedActions = self.__quests2actions[qID] if q.getType() == EVENT_TYPE.GROUP: groups[qID] = q continue if q.getFinishTimeLeft() <= 0: continue if not filterFunc(q): continue result[qID] = q if includePersonalMissions: for qID, q in self.getPersonalMissions().getAllQuests().iteritems(): if filterFunc(q): result[qID] = q for gID, group in groups.iteritems(): for qID in group.getGroupEvents(): if qID in result: result[qID].setGroupID(gID) children, parents, parentsName = self._makeQuestsRelations(result) for qID, q in result.iteritems(): if qID in children: q.setChildren(children[qID]) if qID in parents: q.setParents(parents[qID]) if qID in parentsName: q.setParentsName(parentsName[qID]) return result def _getQuestsGroups(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) result = {} for qID, q in self.__getCommonQuestsIterator(): if q.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(q): continue result[qID] = q return result def _getActions(self, filterFunc=None): filterFunc = filterFunc or (lambda a: True) actions = self.__getActionsData() result = {} groups = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) actionID = a.getID() if actionID in self.__actions2quests: a.linkedQuests = self.__actions2quests[actionID] if a.getType() == EVENT_TYPE.GROUP: groups[actionID] = a continue if not filterFunc(a): continue result[actionID] = a for gID, group in groups.iteritems(): for aID in group.getGroupEvents(): if aID in result: result[aID].setGroupID(gID) return result def _getActionsGroups(self, filterFunc=None): actions = self.__getActionsData() filterFunc = filterFunc or (lambda a: True) result = {} for aData in actions: if 'id' in aData: a = self._makeAction(aData['id'], aData) if a.getType() != EVENT_TYPE.GROUP: continue if not filterFunc(a): continue result[a.getID()] = a return result def _makeQuest(self, qID, qData, maker=_defaultQuestMaker, **kwargs): storage = self.__cache['quests'] if qID in storage: return storage[qID] q = storage[qID] = maker(qID, qData, self.__questsProgress) return q def _makeAction(self, aID, aData): storage = self.__cache['actions'] if aID in storage: return storage[aID] a = storage[aID] = createAction(aData.get('type', 0), aID, aData) return a @classmethod def _makeQuestsRelations(cls, quests): makeTokens = defaultdict(list) needTokens = defaultdict(list) for qID, q in quests.iteritems(): if q.getType() != EVENT_TYPE.GROUP: tokens = q.getBonuses('tokens') if tokens: for t in tokens[0].getTokens(): makeTokens[t].append(qID) for t in q.accountReqs.getTokens(): needTokens[qID].append(t.getID()) children = defaultdict(dict) for parentID, tokensIDs in needTokens.iteritems(): for tokenID in tokensIDs: children[parentID][tokenID] = makeTokens.get(tokenID, []) parents = defaultdict(lambda : defaultdict(list)) parentsName = defaultdict(lambda : defaultdict(list)) for parentID, tokens in children.iteritems(): for tokenID, chn in tokens.iteritems(): for childID in chn: parents[childID][tokenID].append(parentID) parentsName[childID][tokenID].append(quests[parentID].getUserName()) return (children, parents, parentsName) def __invalidateData(self, callback=lambda *args: None): self.__clearCache() self.__clearInvalidateCallback() self.__waitForSync = True self.onSyncStarted() for action in self.getActions().itervalues(): for modifier in action.getModifiers(): section = modifier.getSection() mType = modifier.getType() itemType = modifier.getItemType() values = modifier.getValues(action) currentSection = self.__actionsCache[section][mType] if itemType is not None: currentSection = currentSection.setdefault(itemType, {}) for k in values: if k in currentSection: currentSection[k] += values[k] currentSection[k] = values[k] rareAchieves = set() invalidateTimeLeft = sys.maxint for q in self.getCurrentEvents().itervalues(): dossierBonuses = q.getBonuses('dossier') if dossierBonuses: storage = self.__questsDossierBonuses[q.getID()] for bonus in dossierBonuses: records = bonus.getRecords() storage.update(set(bonus.getRecords().keys())) rareAchieves |= set((rId for r, rId in records.iteritems() if r[0] == ACHIEVEMENT_BLOCK.RARE)) timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is not None: isAvailable, errorMsg = q.isAvailable() if not isAvailable: if errorMsg in ('invalid_weekday', 'invalid_time_interval'): invalidateTimeLeft = min(invalidateTimeLeft, timeLeftInfo[0]) else: intervalBeginTimeLeft, (intervalStart, intervalEnd) = timeLeftInfo invalidateTimeLeft = min(invalidateTimeLeft, intervalBeginTimeLeft + intervalEnd - intervalStart) invalidateTimeLeft = min(invalidateTimeLeft, q.getFinishTimeLeft()) self.rareAchievesCache.request(rareAchieves) for q in self.getFutureEvents().itervalues(): timeLeftInfo = q.getNearestActivityTimeLeft() if timeLeftInfo is None: startTime = q.getStartTimeLeft() else: startTime = timeLeftInfo[0] invalidateTimeLeft = min(invalidateTimeLeft, startTime) if invalidateTimeLeft != sys.maxint: self.__loadInvalidateCallback(invalidateTimeLeft) self.__waitForSync = False self.__prefetcher.ask() self.__syncActionsWithQuests() self.__invalidateCompensations() self.onSyncCompleted() callback(True) return def __invalidateCompensations(self): self.__compensations.clear() for q in self.getHiddenQuests(lambda q: isMarathon(q.getGroupID())).itervalues(): self.__compensations.update(q.getCompensation()) def __clearQuestsItemsCache(self): for _, q in self._getQuests().iteritems(): q.accountReqs.clearItemsCache() q.vehicleReqs.clearItemsCache() def __syncActionsWithQuests(self): self.__actions2quests.clear() self.__quests2actions.clear() quests = self.__cache['quests'] actions = [ item for item in self.__cache['actions'] ] self.__actions2quests = {k:[] for k in actions} for questID, questData in quests.iteritems(): groupId = questData.getGroupID() linkedActionID = getLinkedActionID(groupId, actions) if linkedActionID is not None: self.__actions2quests[linkedActionID].append(questID) self.__convertQuests2actions() return def __convertQuests2actions(self): for action, quests in self.__actions2quests.iteritems(): for quest in quests: if quest in self.__quests2actions: self.__quests2actions[quest].append(action) self.__quests2actions[quest] = [action] @classmethod def __getEventsData(cls, eventsTypeName): try: if isPlayerAccount(): if eventsTypeName in BigWorld.player().eventsData: return pickle.loads(zlib.decompress(BigWorld.player().eventsData[eventsTypeName])) return {} LOG_DEBUG('Trying to get quests data from not account player', eventsTypeName, BigWorld.player()) except Exception: LOG_CURRENT_EXCEPTION() return {} def __getQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.QUEST) def __getPersonalQuestsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.PERSONAL_QUEST) def __getActionsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION) def __getActionsEntitiesData(self): return self.__getEventsData(EVENT_CLIENT_DATA.ACTION_ENTITIES) def __getAnnouncedActions(self): return self.__getEventsData(EVENT_CLIENT_DATA.ANNOUNCED_ACTION_DATA) def __getIngameEventsData(self): return self.__getEventsData(EVENT_CLIENT_DATA.INGAME_EVENTS) def __getEventBattles(self): return self.__getIngameEventsData().get('eventBattles', {}) def __getUnitRestrictions(self): return self.__getUnitData().get('restrictions', {}) def __getUnitXpFactors(self): return self.__getUnitData().get('xpFactors', {}) def __getUnitData(self): return self.__getEventsData(EVENT_CLIENT_DATA.SQUAD_BONUSES) def __getCommonQuestsIterator(self): questsData = self.__getQuestsData() questsData.update(self.__getPersonalQuestsData()) questsData.update(self.__getPersonalMissionsHiddenQuests()) for qID, qData in questsData.iteritems(): yield (qID, self._makeQuest(qID, qData)) motiveQuests = motivation_quests.g_cache.getAllQuests() or [] for questDescr in motiveQuests: yield (questDescr.questID, self._makeQuest(questDescr.questID, questDescr.questData, maker=_motiveQuestMaker)) def __loadInvalidateCallback(self, duration): LOG_DEBUG('load quest window invalidation callback (secs)', duration) self.__clearInvalidateCallback() self.__invalidateCbID = BigWorld.callback(math.ceil(duration), self.__invalidateData) def __clearInvalidateCallback(self): if self.__invalidateCbID is not None: BigWorld.cancelCallback(self.__invalidateCbID) self.__invalidateCbID = None return def __clearCache(self): self.__questsDossierBonuses.clear() self.__actionsCache.clear() for storage in self.__cache.itervalues(): storage.clear() clearModifiersCache() def __getPersonalMissionsHiddenQuests(self): if not self.__personalMissionsHidden: xmlPath = PERSONAL_MISSIONS_XML_PATH + '/tiles.xml' for quest in readQuestsFromFile(xmlPath, EVENT_TYPE.TOKEN_QUEST): self.__personalMissionsHidden[quest[0]] = quest[3] return self.__personalMissionsHidden.copy() def __onLockedQuestsChanged(self): self.__lockedQuestIds = BigWorld.player().personalMissionsLock def __onServerSettingsChange(self, *args, **kwargs): self.__personalMissions.updateDisabledStateForQuests()
class _PreDefinedHostList(object): def __init__(self): super(_PreDefinedHostList, self).__init__() self._eManager = EventManager() self.onCsisQueryStart = Event(self._eManager) self.onCsisQueryComplete = Event(self._eManager) self.onPingPerformed = Event(self._eManager) self._hosts = [] self._urlMap = {} self._nameMap = {} self._peripheryMap = {} self._isDataLoaded = False self._isCSISQueryInProgress = False self.__csisUrl = '' self.__csisResponse = {} self.__lastRoamingHosts = [] self.__csisCallbackID = None self.__lastCsisUpdateTime = 0 self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self.__recommended = [] self.__pingRequester = _PingRequester(self.__onPingPerformed) return def fini(self): self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() self._isDataLoaded = False self.__csisResponse.clear() self.__csisUrl = '' self.__lastCsisUpdateTime = None self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self._eManager.clear() self.__pingRequester.fini() self.__cleanCsisTimerCallback() return @property def lastRoamingHosts(self): return self.__lastRoamingHosts def startCSISUpdate(self): if len(self.hosts()) > 1: self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__sendCsisQuery() def stopCSISUpdate(self): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__cleanCsisTimerCallback() def requestPing(self, forced = False): self.__pingRequester.request(self._hosts, forced) def getPingResult(self): return self.__pingRequester.result() def autoLoginQuery(self, callback): if callback is None: LOG_WARNING('Callback is not defined.') return elif self.__autoLoginQueryState != AUTO_LOGIN_QUERY_STATE.DEFAULT: LOG_WARNING('Auto login query in process. Current state: {}'.format(self.__autoLoginQueryState)) return elif len(self._hosts) < 2: callback(self.first()) return elif len(self.__recommended): LOG_DEBUG('Gets recommended from previous query', self.__recommended) host = self.__choiceFromRecommended() LOG_DEBUG('Recommended host', host) callback(host) return else: self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.START self.__queryCallback = callback self.__pingRequester.request(self.peripheries()) self.__csisAction = CSIS_ACTION.addIfNot(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__sendCsisQuery() return def resetQueryResult(self): self.__recommended = [] self.__pingRequester.clear() def readScriptConfig(self, dataSection, userDataSection = None): if self._isDataLoaded or dataSection is None: return else: def _readSvrList(section, nodeName): if section is not None and section.has_key(nodeName): return section[nodeName].items() else: return [] return self.__csisUrl = dataSection.readString('csisUrl') self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() svrList = _readSvrList(dataSection, 'login') + _readSvrList(userDataSection, 'development/login') for name, subSec in svrList: name = subSec.readString('name') shortName = subSec.readString('short_name') urls = _LoginAppUrlIterator(subSec.readStrings('url')) host = urls.primary if host is not None: if not len(name): name = host keyPath = subSec.readString('public_key_path') if not len(keyPath): keyPath = None areaID = subSec.readString('game_area_id') if not len(areaID): areaID = None app = self._makeHostItem(name, shortName, host, urlToken=subSec.readString('url_token'), urlIterator=urls if len(urls) > 1 else None, keyPath=keyPath, areaID=areaID, peripheryID=subSec.readInt('periphery_id', 0)) idx = len(self._hosts) url = app.url if url in self._urlMap: LOG_WARNING('Host url is already added. This host is ignored', url) continue self._urlMap[url] = idx urlToken = app.urlToken if len(urlToken): if urlToken in self._urlMap: LOG_WARNING('Alternative host url is already added. This url is ignored', app.url) else: self._urlMap[urlToken] = idx self._nameMap[app.name] = idx if app.peripheryID: self._peripheryMap[app.peripheryID] = idx self._hosts.append(app) self._isDataLoaded = True return def predefined(self, url): return url in self._urlMap def roaming(self, url): return url in [ p.url for p in self.roamingHosts() ] def first(self): if len(self._hosts): return self._hosts[0] return self._makeHostItem('', '', '') def byUrl(self, url): result = self._makeHostItem('', '', url) index = self._urlMap.get(url, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.url == url: result = host return result def byName(self, name): result = self._makeHostItem(name, '', '') index = self._nameMap.get(name, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.name == name: result = host return result def hosts(self): return self._hosts[:] def shortList(self): result = self.getSimpleHostsList(self._hosts) if AUTO_LOGIN_QUERY_ENABLED and len(result) > 1 and len(self.peripheries()) > 1: result.insert(0, (AUTO_LOGIN_QUERY_URL, i18n.makeString('#menu:login/auto'), HOST_AVAILABILITY.IGNORED, None)) return result def getSimpleHostsList(self, hosts): result = [] defAvail = self.getDefaultCSISStatus() predefined = tuple((host.url for host in self.peripheries())) isInProgress = self._isCSISQueryInProgress csisResGetter = self.__csisResponse.get for item in hosts: if item.url not in predefined: status = HOST_AVAILABILITY.IGNORED else: status = defAvail if isInProgress else csisResGetter(item.peripheryID, defAvail) result.append((item.url, item.name, status, item.peripheryID)) return result def getDefaultCSISStatus(self): from gui import GUI_SETTINGS if not len(self.__csisUrl): defAvail = HOST_AVAILABILITY.IGNORED elif GUI_SETTINGS.csisRequestRate == REQUEST_RATE.NEVER: defAvail = HOST_AVAILABILITY.IGNORED elif len(g_preDefinedHosts.hosts()) > 1: defAvail = HOST_AVAILABILITY.UNKNOWN else: defAvail = HOST_AVAILABILITY.IGNORED return defAvail def urlIterator(self, primary): result = None index = self._urlMap.get(primary, -1) if index > -1: result = self._hosts[index].urlIterator return result def periphery(self, peripheryID, useRoaming = True): if peripheryID in self._peripheryMap: index = self._peripheryMap[peripheryID] return self._hosts[index] else: if useRoaming: roamingHosts = dict(((host.peripheryID, host) for host in self.roamingHosts())) if peripheryID in roamingHosts: return roamingHosts[peripheryID] return None def peripheries(self): return filter(lambda app: app.peripheryID, self._hosts) def roamingHosts(self): p = BigWorld.player() result = [] if hasattr(p, 'serverSettings'): for peripheryID, name, shortName, host, keyPath in p.serverSettings['roaming'][3]: result.append(self._makeHostItem(name, shortName, host, keyPath=keyPath, peripheryID=peripheryID)) self.__lastRoamingHosts = sorted(result, key=operator.itemgetter(0)) return self.__lastRoamingHosts def hostsWithRoaming(self): predefined = tuple((host.url for host in self.peripheries())) hosts = self.peripheries() for h in self.roamingHosts(): if h.url not in predefined: hosts.append(h) return hosts def isRoamingPeriphery(self, peripheryID): return peripheryID not in [ p.peripheryID for p in self.peripheries() ] def _makeHostItem(self, name, shortName, url, urlToken = '', urlIterator = None, keyPath = None, areaID = None, peripheryID = 0): if not len(shortName): shortName = name return _HostItem(name, shortName, url, urlToken, urlIterator, keyPath, areaID, peripheryID) def _determineRecommendHost(self): defAvail = HOST_AVAILABILITY.NOT_AVAILABLE csisResGetter = self.__csisResponse.get queryResult = map(lambda host: (host, self.__pingRequester.result().get(host.url, -1), csisResGetter(host.peripheryID, defAvail)), self.peripheries()) self.__recommended = filter(lambda item: item[2] == HOST_AVAILABILITY.RECOMMENDED, queryResult) if not len(self.__recommended): self.__recommended = filter(lambda item: item[2] == HOST_AVAILABILITY.NOT_RECOMMENDED, queryResult) recommendLen = len(self.__recommended) if not recommendLen: if len(queryResult) > 1: LOG_DEBUG('List of recommended is empty. Gets host by ping') self.__recommended = self.__filterRecommendedByPing(queryResult) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() else: LOG_DEBUG('Gets first as recommended') result = self.first() else: LOG_DEBUG('Recommended by CSIS', self.__recommended) if recommendLen > 1: self.__recommended = self.__filterRecommendedByPing(self.__recommended) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() return result def __startCsisTimer(self): self.__cleanCsisTimerCallback() self.__csisCallbackID = BigWorld.callback(CSIS_REQUEST_TIMER, self.__onCsisTimer) def __cleanCsisTimerCallback(self): if self.__csisCallbackID: BigWorld.cancelCallback(self.__csisCallbackID) self.__csisCallbackID = None return def __onCsisTimer(self): self.__csisCallbackID = None self.__sendCsisQuery() return def __sendCsisQuery(self): isReplay = _isReplay('CSIS') if not isReplay and len(self.__csisUrl): if not self._isCSISQueryInProgress: timeFromLastUpdate = time.time() - self.__lastCsisUpdateTime if timeFromLastUpdate >= CSIS_REQUEST_TIMER: self._isCSISQueryInProgress = True self.onCsisQueryStart() allHosts = self.hosts() peripheries = map(lambda host: host.peripheryID, allHosts) LOG_DEBUG('CSIS query sending', peripheries) _CSISRequestWorker(self.__csisUrl, self.__receiveCsisResponse, peripheries).start() else: self.__finishCsisQuery() else: if not isReplay: LOG_DEBUG('CSIS url is not defined - ignore') self._isCSISQueryInProgress = False self.stopCSISUpdate() self.__finishCsisQuery() self.__lastCsisUpdateTime = 0 def __receiveCsisResponse(self, response): LOG_DEBUG('CSIS query received', response) self._isCSISQueryInProgress = False self.__csisResponse = response self.__lastCsisUpdateTime = time.time() self.__finishCsisQuery() def __finishCsisQuery(self): if self.__csisAction & CSIS_ACTION.AUTO_LOGIN_REQUEST: self.__receiveAutoLoginCSISResponse(self.__csisResponse) if self.__csisAction & CSIS_ACTION.UPDATE_ON_TIME: self.__startCsisTimer() self.onCsisQueryComplete(self.__csisResponse) def __onPingPerformed(self, result): self.onPingPerformed(result) if self.__autoLoginQueryState & AUTO_LOGIN_QUERY_STATE.START: self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.PING_PERFORMED) def __receiveAutoLoginCSISResponse(self, response): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__autoLoginQueryCompleted(AUTO_LOGIN_QUERY_STATE.CSIS_RESPONSE_RECEIVED) def __autoLoginQueryCompleted(self, state): if not self.__autoLoginQueryState & state: self.__autoLoginQueryState |= state if self.__autoLoginQueryState == AUTO_LOGIN_QUERY_STATE.COMPLETED: host = self._determineRecommendHost() LOG_DEBUG('Recommended host', host) self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__queryCallback(host) self.__queryCallback = None return def __filterRecommendedByPing(self, recommended): result = recommended filtered = filter(lambda item: item[1] > -1, recommended) if len(filtered): minPingTime = min(filtered, key=lambda item: item[1])[1] maxPingTime = 1.2 * minPingTime result = filter(lambda item: item[1] < maxPingTime, filtered) return result def __choiceFromRecommended(self): recommended = random.choice(self.__recommended) self.__recommended = filter(lambda item: item != recommended, self.__recommended) return recommended[0]
class ConnectionManager(object): def __init__(self): self.__connectionData = ConnectionData() self.__connectionUrl = None self.__connectionMethod = CONNECTION_METHOD.BASIC self.__connectionStatus = LOGIN_STATUS.NOT_SET self.__lastLoginName = None self.__hostItem = g_preDefinedHosts._makeHostItem('', '', '') self.__retryConnectionPeriod = _MIN_RECONNECTION_TIMEOUT self.__retryConnectionCallbackID = None g_playerEvents.onKickWhileLoginReceived += self.__processKick g_playerEvents.onLoginQueueNumberReceived += self.__processQueue self.__eManager = EventManager() self.onLoggedOn = Event(self.__eManager) self.onConnected = Event(self.__eManager) self.onRejected = Event(self.__eManager) self.onDisconnected = Event(self.__eManager) self.onKickedFromServer = Event(self.__eManager) self.onKickWhileLoginReceived = Event(self.__eManager) self.onQueued = Event(self.__eManager) return def __del__(self): g_playerEvents.onKickWhileLoginReceived -= self.__processKick g_playerEvents.onLoginQueueNumberReceived -= self.__processQueue self.__eManager.clear() self.stopRetryConnection() def initiateConnection(self, params, password, serverName): self.__setConnectionData(params, password) if serverName == AUTO_LOGIN_QUERY_URL: g_preDefinedHosts.autoLoginQuery(self.__setHostDataAndConnect) else: self.__setHostDataAndConnect(g_preDefinedHosts.byUrl(serverName)) def stopRetryConnection(self): if self.__retryConnectionCallbackID is not None: BigWorld.cancelCallback(self.__retryConnectionCallbackID) self.__retryConnectionPeriod = 0 self.__retryConnectionCallbackID = None return def __connect(self): self.__retryConnectionCallbackID = None if constants.IS_DEVELOPMENT: LOG_DEBUG('Calling BigWorld.connect with params: {0}, serverName: {1}, inactivityTimeout: {2}, publicKeyPath: {3}'.format(self.__connectionData.username, self.__connectionUrl, constants.CLIENT_INACTIVITY_TIMEOUT, self.__connectionData.publicKeyPath)) nextTick(lambda : BigWorld.connect(self.__connectionUrl, self.__connectionData, self.__serverResponseHandler))() if g_preDefinedHosts.predefined(self.__connectionUrl) or g_preDefinedHosts.roaming(self.__connectionUrl): self.__hostItem = g_preDefinedHosts.byUrl(self.__connectionUrl) else: for server in BigWorld.serverDiscovery.servers: if server.serverString == self.__connectionUrl: self.__hostItem = self.__hostItem._replace(name=server.ownerName) break return def __serverResponseHandler(self, stage, status, responseDataJSON): if constants.IS_DEVELOPMENT: LOG_DEBUG('Received server response with stage: {0}, status: {1}, responseData: {2}'.format(stage, status, responseDataJSON)) self.__connectionStatus = status try: responseData = json.loads(responseDataJSON) except ValueError: responseData = {'errorMessage': responseDataJSON} if status == LOGIN_STATUS.LOGGED_ON: if stage == 1: if self.__connectionMethod == CONNECTION_METHOD.TOKEN and 'token2' in responseData: self.__swtichToToken2(responseData['token2']) self.onLoggedOn(responseData) self.onConnected() else: if self.__retryConnectionCallbackID is None: status_ = self.__connectionStatus if responseData.get('errorMessage', '') == _INVALID_PASSWORD_TOKEN2_EXPIRED: status_ = LOGIN_STATUS.SESSION_END self.onRejected(status_, responseData) if status == LOGIN_STATUS.LOGIN_REJECTED_RATE_LIMITED: self.__reconnect() if stage == 6: self.onDisconnected() return def __setConnectionData(self, params, password): self.__lastLoginName = params['login'] self.__connectionMethod = params['auth_method'] params['auth_realm'] = constants.AUTH_REALM m = hashlib.md5() m.update(params['session']) params['session'] = m.hexdigest() if constants.IS_IGR_ENABLED: params['is_igr'] = '1' username_ = json.dumps(params, encoding='utf-8') LOG_NOTE('User authentication method: {0}'.format(params['auth_method'])) if 'token2' in params and params['token2']: password = '' else: password = pwd_token.generate(password) self.__connectionData.username = username_ self.__connectionData.password = password self.__connectionData.inactivityTimeout = constants.CLIENT_INACTIVITY_TIMEOUT self.__connectionData.clientContext = json.dumps({'lang_id': getClientLanguage()}) if constants.IS_DEVELOPMENT and params['auth_method'] == CONNECTION_METHOD.BASIC and params['login'][0] == '@': try: self.__connectionData.username = params['login'][1:] except IndexError: self.__connectionData.username = params['login'] def __swtichToToken2(self, token2): self.__connectionMethod = CONNECTION_METHOD.TOKEN2 params = json.loads(self.__connectionData.username, encoding='utf-8') params.pop('token', None) params['token2'] = token2 params['auth_method'] = CONNECTION_METHOD.TOKEN2 self.__connectionData.username = json.dumps(params, encoding='utf-8') return def __setHostDataAndConnect(self, predefinedHost): self.__connectionData.publicKeyPath = predefinedHost.keyPath self.__connectionUrl = predefinedHost.urlToken if (self.__connectionMethod == CONNECTION_METHOD.TOKEN or self.__connectionMethod == CONNECTION_METHOD.TOKEN2) and predefinedHost.urlToken else predefinedHost.url self.__connect() def __reconnect(self, peripheryID = 0): self.stopRetryConnection() self.__retryConnectionCallbackID = BigWorld.callback(self.__getRetryConnectionPeriod(), self.__connect) def __getRetryConnectionPeriod(self): if self.__retryConnectionPeriod != _MAX_RECONNECTION_TIMEOUT: self.__retryConnectionPeriod += _RECONNECTION_TIMEOUT_INCREMENT return self.__retryConnectionPeriod def __processKick(self, peripheryID): if peripheryID > 0: self.__reconnect(peripheryID) self.onKickWhileLoginReceived(peripheryID) def __processQueue(self, queueNumber): self.onQueued(queueNumber) @property def serverUserName(self): return self.__hostItem.name @property def serverUserNameShort(self): return self.__hostItem.shortName @property def peripheryID(self): return self.__hostItem.peripheryID @property def areaID(self): if not self.isDisconnected(): return self.__hostItem.areaID else: return None @property def url(self): return self.__hostItem.url @property def loginName(self): if not self.isDisconnected(): return self.__lastLoginName else: return None @property def lastLoginName(self): return self.__lastLoginName @property def databaseID(self): if not self.isDisconnected(): return BigWorld.player().databaseID else: return None def disconnect(self): BigWorld.disconnect() def setKickedFromServer(self, reason, isBan, expiryTime): self.disconnect() self.onKickedFromServer(reason, isBan, expiryTime) def isDisconnected(self): return self.__connectionStatus != LOGIN_STATUS.LOGGED_ON def isStandalone(self): return self.peripheryID == 0 def isConnected(self): return self.__connectionStatus == LOGIN_STATUS.LOGGED_ON def checkClientServerVersions(self, clientVersion, serverVersion): if not isValidClientVersion(clientVersion, serverVersion) or ResMgr.activeContentType() in (constants.CONTENT_TYPE.INCOMPLETE, constants.CONTENT_TYPE.TUTORIAL): LOG_DEBUG('Version mismatch. Client is "%s", server needs "%s".' % (clientVersion, serverVersion)) self.onRejected(LOGIN_STATUS.LOGIN_BAD_PROTOCOL_VERSION, {}) BigWorld.disconnect()
class _CachedVehicle(object): itemsCache = dependency.descriptor(IItemsCache) hangarSpace = dependency.descriptor(IHangarSpace) def __init__(self): self._eManager = EventManager() self.onChanged = Event(self._eManager) self.onChangeStarted = Event(self._eManager) self.__changeCallbackID = None self.__onVehicleChangedCallback = None return def init(self): self._addListeners() def destroy(self): self._eManager.clear() self._clearChangeCallback() self._removeListeners() def selectVehicle(self, vehInvID=0, callback=None, waitingOverlapsUI=False): raise NotImplementedError def selectNoVehicle(self): raise NotImplementedError def isPresent(self): return self.item is not None def isCollectible(self): return self.isPresent() and self.item.isCollectible def refreshModel(self, outfit=None): raise NotImplementedError def updateVehicleDescriptorInModel(self): raise NotImplementedError @property def item(self): raise NotImplementedError @property def invID(self): raise NotImplementedError @property def intCD(self): raise NotImplementedError def _addListeners(self): g_clientUpdateManager.addCallbacks( {'inventory': self._onInventoryUpdate}) self.itemsCache.onSyncCompleted += self._onSyncCompleted def _removeListeners(self): self.itemsCache.onSyncCompleted -= self._onSyncCompleted g_clientUpdateManager.removeObjectCallbacks(self) def _changeDone(self): self._clearChangeCallback() if isPlayerAccount(): self._updateVehicle() Waiting.hide('updateCurrentVehicle') def _onInventoryUpdate(self, invDiff): raise NotImplementedError def _onPostProgressionUpdate(self): raise NotImplementedError def _onSyncCompleted(self, _, diff): if self.intCD in diff.get(GUI_ITEM_TYPE.VEH_POST_PROGRESSION, {}): self._onPostProgressionUpdate() def _updateVehicle(self): abilities = BigWorld.player().inventory.abilities.abilitiesManager scopedPerks = abilities.getPerksByVehicle(self.invID) if self.item: self.item.initPerksController(scopedPerks) self.onChanged() def _setChangeCallback(self, callback=None): self.__onVehicleChangedCallback = callback if not self.__changeCallbackID: self.__changeCallbackID = BigWorld.callback(0.2, self._changeDone) def _clearChangeCallback(self): if self.__onVehicleChangedCallback is not None: self.__onVehicleChangedCallback() self.__onVehicleChangedCallback = None if self.__changeCallbackID is not None: BigWorld.cancelCallback(self.__changeCallbackID) self.__changeCallbackID = None return def _selectVehicle(self, vehID, callback=None): raise NotImplementedError
class ScaleformGuiImpl(IGuiImpl): __slots__ = ('__proxy', '__eventMgr') __appLoader = dependency.descriptor(IAppLoader) def __init__(self): super(ScaleformGuiImpl, self).__init__() self.__proxy = None self.__eventMgr = EventManager() self.onComponentFound = Event(self.__eventMgr) self.onComponentDisposed = Event(self.__eventMgr) self.onTriggerActivated = Event(self.__eventMgr) self.onEffectCompleted = Event(self.__eventMgr) self.onInit = Event(self.__eventMgr) self.__appLoader.onGUISpaceBeforeEnter += self.__onBeforeEnterSpace return def fini(self): self.__appLoader.onGUISpaceBeforeEnter -= self.__onBeforeEnterSpace self.__appLoader.onGUIInitialized -= self.__setProxy self.clear() self.__eventMgr.clear() def clear(self): if self.__proxy is not None: self.__proxy.onCreated -= self.__onProxyCreated self.__proxy.onComponentFoundEvent -= self.__onComponentFound self.__proxy.onComponentDisposedEvent -= self.__onComponentDisposed self.__proxy.onEffectCompletedEvent -= self.__onEffectCompleted self.__proxy.onTriggerActivatedEvent -= self.__onTriggerActivated self.__proxy = None return def showEffect(self, componentID, viewID, effectType, effectData, effectBuilder=''): self.__proxy.as_showEffectS(viewID, componentID, effectType, { 'data': effectData, 'builder': effectBuilder }) def hideEffect(self, componentID, viewID, effectType, effectBuilder=''): self.__proxy.as_hideEffectS(viewID, componentID, effectType, effectBuilder) def setDescriptions(self, descriptions): descrs = defaultdict(list) for descr in descriptions: descrs[descr.viewId].append({ 'id': descr.ID, 'viewName': descr.viewId, 'path': descr.path }) self.__proxy.as_setDescriptionsS(descrs) def setSystemEnabled(self, enabled): self.__proxy.as_setSystemEnabledS(enabled) def setCriteria(self, name, value): self.__proxy.as_setCriteriaS(name, value) def setViewCriteria(self, componentID, viewUniqueName): self.__proxy.as_setComponentViewCriteriaS(componentID, viewUniqueName) def setTriggers(self, componentID, triggers): self.__proxy.as_setTriggersS(componentID, triggers) def supportedViewTypes(self): return (GuiType.SCALEFORM, GuiType.WULF) def isInited(self): return self.__proxy is not None and self.__proxy.isCreated() def __onBeforeEnterSpace(self, spaceID): if spaceID in (GuiGlobalSpaceID.LOBBY, GuiGlobalSpaceID.BATTLE): self.__setProxy() def __setProxy(self): self.clear() self.__proxy = self.__appLoader.getApp().tutorialManager if self.__proxy is None: self.__appLoader.onGUIInitialized += self.__setProxy return else: self.__proxy.onComponentFoundEvent += self.__onComponentFound self.__proxy.onComponentDisposedEvent += self.__onComponentDisposed self.__proxy.onEffectCompletedEvent += self.__onEffectCompleted self.__proxy.onTriggerActivatedEvent += self.__onTriggerActivated self.__appLoader.onGUIInitialized -= self.__setProxy if not self.__proxy.isCreated(): self.__proxy.onCreated += self.__onProxyCreated else: self.onInit() return def __onComponentFound(self, componentId, viewTutorialId): self.onComponentFound(componentId, viewTutorialId) def __onTriggerActivated(self, componentId, triggerId, state): self.onTriggerActivated(componentId, triggerId, state) def __onComponentDisposed(self, componentId): self.onComponentDisposed(componentId) def __onEffectCompleted(self, componentId, effectType): self.onEffectCompleted(componentId, effectType) def __onProxyCreated(self): self.onInit()
class CelebritySceneController(ICelebritySceneController): __slots__ = ('__eventsManager', '__celebrityEntity', '__questGroups', '__quests', '__isInChallengeView', '__tokens', '__marathonQuests', '__completedQuestsMask', '__questsCount', '__completedQuestsCount') __newYearController = dependency.descriptor(INewYearController) __eventsCache = dependency.descriptor(IEventsCache) __itemsCache = dependency.descriptor(IItemsCache) __hangarSpace = dependency.descriptor(IHangarSpace) __settingsCore = dependency.descriptor(ISettingsCore) def __init__(self): super(CelebritySceneController, self).__init__() self.__eventsManager = EventManager() self.onQuestsUpdated = Event(self.__eventsManager) self.__celebrityEntity = None self.__celebrityEntryEntity = None self.__questGroups = {} self.__quests = {} self.__tokens = {} self.__marathonQuests = {} self.__completedQuestsMask = 0 self.__questsCount = 0 self.__completedQuestsCount = 0 self.__isInChallengeView = False return @property def isChallengeVisited(self): return self.__settingsCore.serverSettings.getNewYearStorage().get(NewYearStorageKeys.CELEBRITY_CHALLENGE_VISITED, False) @property def isWelcomeAnimationViewed(self): return self.__settingsCore.serverSettings.getNewYearStorage().get(NewYearStorageKeys.CELEBRITY_WELCOME_VIEWED, False) @property def isInChallengeView(self): return self.__isInChallengeView @property def isChallengeCompleted(self): return self.completedQuestsCount == self.questsCount @property def hasNewCompletedQuests(self): completedQuestsMask = self.__getCompletedQuestsMask() return bool(completedQuestsMask ^ self.__completedQuestsMask) @property def questGroups(self): return self.__questGroups @property def quests(self): return self.__quests @property def tokens(self): return self.__tokens @property def marathonQuests(self): return self.__marathonQuests @property def completedQuestsMask(self): return self.__completedQuestsMask @property def questsCount(self): return self.__questsCount @property def completedQuestsCount(self): return self.__completedQuestsCount def fini(self): self.__destroy() super(CelebritySceneController, self).fini() def onLobbyInited(self, _): self.__subscribe() self.__updateQuests() def onDisconnected(self): self.__destroy() def onAvatarBecomePlayer(self): self.__destroy() def addCelebrityEntity(self, entity): self.__celebrityEntity = entity def removeCelebrityEntity(self): self.__celebrityEntity = None return def addCelebrityEntryEntity(self, entity): self.__celebrityEntryEntity = entity def removeCelebrityEntryEntity(self): self.__celebrityEntryEntity = None return def onEnterChallenge(self): self.__isInChallengeView = True if self.isChallengeCompleted: animationTrigger = _AnimationTriggers.CHALLENGE_COMPLETED elif not self.isChallengeVisited and not self.isWelcomeAnimationViewed: animationTrigger = _AnimationTriggers.CHALLENGE_WELCOME elif self.hasNewCompletedQuests: animationTrigger = _AnimationTriggers.QUEST_COMPLETED else: animationTrigger = _AnimationTriggers.CHALLENGE_IDLE self.__setAnimationTrigger(animationTrigger) self.__saveCompletedQuestsMask() def onExitChallenge(self): self.__setAnimationTrigger(_AnimationTriggers.HANGAR_IDLE) self.__isInChallengeView = False def onSimplifyQuest(self): self.__setAnimationTrigger(_AnimationTriggers.QUEST_SIMPLIFIED) def onAnimatorEvent(self, name): if name == _AnimationEvents.WELCOME_COMPLETED: self.__settingsCore.serverSettings.saveInNewYearStorage({NewYearStorageKeys.CELEBRITY_WELCOME_VIEWED: True}) def __destroy(self): self.__unsubscribe() self.__eventsManager.clear() self.__celebrityEntity = None self.__celebrityEntryEntity = None self.__questGroups.clear() self.__quests.clear() self.__tokens.clear() self.__marathonQuests.clear() self.__isInChallengeView = False return def __subscribe(self): self.__eventsCache.onSyncCompleted += self.__onSyncCompleted self.__eventsCache.onQuestConditionUpdated += self.__onSyncCompleted def __unsubscribe(self): self.__eventsCache.onSyncCompleted -= self.__onSyncCompleted self.__eventsCache.onQuestConditionUpdated -= self.__onSyncCompleted def __onSyncCompleted(self): self.__updateQuests() def __setAnimationTrigger(self, triggerName): if not self.__hangarSpace.spaceInited: return elif self.__celebrityEntity is None: _logger.error('Failed to set animation state machine trigger: %s. Missing Celebrity Entity', triggerName) return else: self.__celebrityEntity.setAnimatorTrigger(triggerName) return def __updateQuests(self): self.__questGroups = getCelebrityQuestsGroups() self.__quests = getCelebrityQuests() self.__marathonQuests = getCelebrityMarathonQuests() self.__tokens = getCelebrityTokens() self.__completedQuestsMask = 0 for groupId, group in self.__questGroups.iteritems(): group.update(self.quests) if not group.isGroupCompleted: continue dayNum = CelebrityQuestTokenParts.getDayNum(groupId) dayNumBit = 1 << dayNum - 1 self.__completedQuestsMask |= dayNumBit self.__questsCount = getCelebrityQuestCount() self.__completedQuestsCount = bin(self.completedQuestsMask).count('1') if self.__isInChallengeView: self.__saveCompletedQuestsMask() self.onQuestsUpdated() def __getCompletedQuestsMask(self): completedQuestsMask = AccountSettings.getUIFlag(NY_CELEBRITY_QUESTS_COMPLETED_MASK) return completedQuestsMask def __saveCompletedQuestsMask(self): AccountSettings.setUIFlag(NY_CELEBRITY_QUESTS_COMPLETED_MASK, self.__completedQuestsMask)
class PQController(object): def __init__(self, eventsCache): self.__clearCaches() self.__eventsCache = weakref.proxy(eventsCache) self.__em = EventManager() self.__hasQuestsForSelect = False self.__hasQuestsForReward = False self.onSelectedQuestsChanged = Event(self.__em) self.onSlotsCountChanged = Event(self.__em) self.onProgressUpdated = Event(self.__em) def init(self): for _, potapovQuestID in potapov_quests.g_cache: quest = self.__makeQuest(potapovQuestID) tile = self.__makeTile(quest.getTileID()) tile._addQuest(quest) season = self.__makeSeason(tile.getSeasonID()) season._addTile(tile) quest.setSeasonID(season.getID()) def fini(self): self.__em.clear() self.__clearCaches() def update(self, diff=None): if diff is not None: potapovQuestsDiff = diff.get("potapovQuests", {}) if "selected" in potapovQuestsDiff: self.onSelectedQuestsChanged(potapovQuestsDiff["selected"]) if "slots" in potapovQuestsDiff: self.onSlotsCountChanged(potapovQuestsDiff["slots"]) isNeedToUpdateProgress = len(potapovQuestsDiff) else: isNeedToUpdateProgress = True if isNeedToUpdateProgress: self.__hasQuestsForSelect = False self.__hasQuestsForReward = False freeSlotsCount = self.__eventsCache.questsProgress.getPotapovQuestsFreeSlots() for qID, quest in self.__quests.iteritems(): quest.updateProgress(self.__eventsCache) selectedQuests = self.__eventsCache.questsProgress.getSelectedPotapovQuestsIDs() selectedChains = set([self.__quests[questID].getChainID() for questID in selectedQuests]) for qID, quest in self.__quests.iteritems(): if ( not self.__hasQuestsForSelect and freeSlotsCount and quest.canBeSelected() and quest.getChainID() not in selectedChains ): self.__hasQuestsForSelect = True if not self.__hasQuestsForReward and quest.needToGetReward(): self.__hasQuestsForReward = True if self.__hasQuestsForSelect and self.__hasQuestsForReward: break for tile in self.__tiles.itervalues(): tile.updateProgress(self.__eventsCache) for season in self.__seasons.itervalues(): season.updateProgress(self.__eventsCache) self.onProgressUpdated() return def getNextTankwomanIDs(self, nationID, isPremium, fnGroup, lnGroup, iGroupID): lastFirstNameID, lastLastNameID, lastIconID = self.__eventsCache.questsProgress.getTankmanLastIDs(nationID) return map( operator.itemgetter(1), tankmen.getNextUniqueIDs( BigWorld.player().databaseID, lastFirstNameID, lastLastNameID, lastIconID, nationID, isPremium, fnGroup, lnGroup, iGroupID, ), ) def getQuests(self): return self.__quests def getTiles(self): return self.__tiles def getSeasons(self): return self.__seasons def getSelectedQuests(self): result = {} for qID in self.__eventsCache.questsProgress.getSelectedPotapovQuestsIDs(): result[qID] = self.__quests[qID] return result def getTokens(self): result = set() for tile in self.getTiles().itervalues(): result |= tile.getTokens().keys() return result def hasQuestsForSelect(self): return self.__hasQuestsForSelect def hasQuestsForReward(self): return self.__hasQuestsForReward def __clearCaches(self): self.__seasons = {} self.__tiles = {} self.__quests = {} def __makeSeason(self, seasonID): if seasonID not in self.__seasons: season = self.__seasons[seasonID] = event_items.PQSeason( seasonID, potapov_quests.g_seasonCache.getSeasonInfo(seasonID) ) else: season = self.__seasons[seasonID] return season def __makeTile(self, tileID): if tileID not in self.__tiles: tile = self.__tiles[tileID] = event_items.PQTile(tileID, potapov_quests.g_tileCache.getTileInfo(tileID)) else: tile = self.__tiles[tileID] return tile def __makeQuest(self, pqID, seasonID=None): if pqID not in self.__quests: pqType = potapov_quests.g_cache.questByPotapovQuestID(pqID) quest = self.__quests[pqID] = event_items.PotapovQuest(pqID, pqType, seasonID=seasonID) else: quest = self.__quests[pqID] return quest
class TabsContainer(object): eventsCache = dependency.descriptor(IEventsCache) goodiesCache = dependency.descriptor(IGoodiesCache) def __init__(self): self.__tabs = {TABS_IDS.INVENTORY: InventoryBoostersTab(), TABS_IDS.SHOP: ShopBoostersTab()} self.__currentTabIdx = None self.__activeBoostersCount = None self.__eManager = EventManager() self.onTabsUpdate = Event(self.__eManager) return def init(self): self.__activeBoostersCount = len(self.goodiesCache.getBoosters(criteria=REQ_CRITERIA.BOOSTER.ACTIVE).values()) g_clientUpdateManager.addCallbacks({'goodies': self.__onUpdateBoosters, 'shop': self.__onUpdateBoosters, 'stats': self.__onStatsChanged}) def setCurrentTabIdx(self, currentTabIdx): self.__currentTabIdx = currentTabIdx @property def currentTab(self): return self.__tabs[self.__currentTabIdx] @property def inventoryTab(self): return self.__tabs[TABS_IDS.INVENTORY] @property def shopTab(self): return self.__tabs[TABS_IDS.SHOP] def getTabs(self): return self.__tabs def setFilters(self, qualities, boosterTypes): for tab in self.__tabs.itervalues(): tab.setFilters(qualities, boosterTypes) def getActiveBoostersCount(self): return self.__activeBoostersCount def fini(self): self.__currentTabIdx = None self.__eManager.clear() g_clientUpdateManager.removeObjectCallbacks(self) for tab in self.__tabs.itervalues(): tab.fini() self.__tabs.clear() self.__activeBoostersCount = None return def __onUpdateBoosters(self, *args): for tab in self.__tabs.itervalues(): tab.update() self.__activeBoostersCount = len(self.goodiesCache.getBoosters(criteria=REQ_CRITERIA.BOOSTER.ACTIVE).values()) self.onTabsUpdate() def __onStatsChanged(self, stats): if Money.hasMoney(stats): self.shopTab.updateBalance() self.onTabsUpdate()
class _PreDefinedHostList(object): def __init__(self): super(_PreDefinedHostList, self).__init__() self._eManager = EventManager() self.onCsisQueryStart = Event(self._eManager) self.onCsisQueryComplete = Event(self._eManager) self._hosts = [] self._urlMap = {} self._nameMap = {} self._peripheryMap = {} self._isDataLoaded = False self._isCSISQueryInProgress = False self.__pingResult = {} self.__csisUrl = '' self.__csisResponse = {} self.__lastRoamingHosts = [] self.__csisCallbackID = None self.__lastCsisUpdateTime = 0 self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self.__recommended = [] self.__setPingCallback = False try: BigWorld.WGPinger.setOnPingCallback(self.__onPingPerformed) self.__setPingCallback = True except AttributeError: LOG_CURRENT_EXCEPTION() def fini(self): self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() self._isDataLoaded = False self.__pingResult.clear() self.__csisResponse.clear() self.__csisUrl = '' self.__lastCsisUpdateTime = None self.__queryCallback = None self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__csisAction = CSIS_ACTION.DEFAULT self._eManager.clear() self.__setPingCallback = False self.__cleanCsisTimerCallback() try: BigWorld.WGPinger.clearOnPingCallback() except AttributeError: LOG_CURRENT_EXCEPTION() @property def lastRoamingHosts(self): return self.__lastRoamingHosts def startCSISUpdate(self): if len(self.hosts()) > 1: self.__csisAction = CSIS_ACTION.addIfNot( self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__sendCsisQuery() def stopCSISUpdate(self): self.__csisAction = CSIS_ACTION.removeIfHas(self.__csisAction, CSIS_ACTION.UPDATE_ON_TIME) self.__cleanCsisTimerCallback() def autoLoginQuery(self, callback): if callback is None: LOG_WARNING('Callback is not defined.') return if self.__autoLoginQueryState != AUTO_LOGIN_QUERY_STATE.DEFAULT: LOG_WARNING('Auto login query in process.') return if len(self._hosts) < 2: callback(self.first()) return peripheryID, expired = self.readPeripheryTL() if peripheryID > 0 and expired > 0: if expired > time.time(): host = self.periphery(peripheryID) if host is not None: LOG_DEBUG('Recommended host taken from cache', host) callback(host) return if len(self.__recommended): LOG_DEBUG('Gets recommended from previous query', self.__recommended) host = self.__choiceFromRecommended() LOG_DEBUG('Recommended host', host) callback(host) return self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.START self.__queryCallback = callback self.__ping() self.__csisAction = CSIS_ACTION.addIfNot( self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__sendCsisQuery() def resetQueryResult(self): self.__recommended = [] self.__pingResult.clear() def savePeripheryTL(self, peripheryID, delta=STORED_AS_RECOMMEND_DELTA): if not AUTO_LOGIN_QUERY_ENABLED or not peripheryID: return try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: value = base64.b64encode( pickle.dumps((peripheryID, time.time() + delta))) loginSec.writeString('peripheryLifeTime', value) Settings.g_instance.save() except Exception: LOG_CURRENT_EXCEPTION() def readPeripheryTL(self): if not AUTO_LOGIN_QUERY_ENABLED: return (0, 0) result = (0, 0) try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: value = loginSec.readString('peripheryLifeTime') if len(value): value = pickle.loads(base64.b64decode(value)) if len(value) > 1: result = value except Exception: result = ('', 0) LOG_CURRENT_EXCEPTION() return result def clearPeripheryTL(self): if not AUTO_LOGIN_QUERY_ENABLED: return try: loginSec = Settings.g_instance.userPrefs[Settings.KEY_LOGIN_INFO] if loginSec is not None: loginSec.writeString('peripheryLifeTime', '') Settings.g_instance.save() except Exception: LOG_CURRENT_EXCEPTION() def readScriptConfig(self, dataSection): if self._isDataLoaded or dataSection is None: return self.__csisUrl = dataSection.readString('csisUrl') self._hosts = [] self._urlMap.clear() self._nameMap.clear() self._peripheryMap.clear() loginSection = dataSection['login'] if loginSection is None: return for name, subSec in loginSection.items(): name = subSec.readString('name') shortName = subSec.readString('short_name') urls = _LoginAppUrlIterator(subSec.readStrings('url')) host = urls.primary if host is not None: if not len(name): name = host keyPath = subSec.readString('public_key_path') if not len(keyPath): keyPath = None areaID = subSec.readString('game_area_id') if not len(areaID): areaID = None app = self._makeHostItem( name, shortName, host, urlToken=subSec.readString('url_token'), urlIterator=urls if len(urls) > 1 else None, keyPath=keyPath, areaID=areaID, peripheryID=subSec.readInt('periphery_id', 0)) idx = len(self._hosts) url = app.url if url in self._urlMap: LOG_ERROR( 'Host url is already added. This host is ignored', url) continue self._urlMap[url] = idx urlToken = app.urlToken if len(urlToken): if urlToken in self._urlMap: LOG_ERROR( 'Alternative host url is already added. This url is ignored', app.url) else: self._urlMap[urlToken] = idx self._nameMap[app.name] = idx if app.peripheryID: self._peripheryMap[app.peripheryID] = idx self._hosts.append(app) self._isDataLoaded = True def predefined(self, url): return url in self._urlMap def roaming(self, url): return url in [p.url for p in self.roamingHosts()] def first(self): if len(self._hosts): return self._hosts[0] return self._makeHostItem('', '', '') def byUrl(self, url): result = self._makeHostItem('', '', url) index = self._urlMap.get(url, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.url == url: result = host return result def byName(self, name): result = self._makeHostItem(name, '', '') index = self._nameMap.get(name, -1) if index > -1: result = self._hosts[index] else: for host in self.roamingHosts(): if host.name == name: result = host return result def hosts(self): return self._hosts[:] def shortList(self): result = self.getSimpleHostsList(self._hosts) if AUTO_LOGIN_QUERY_ENABLED and len(result) > 1 and len( self.peripheries()) > 1: result.insert( 0, (AUTO_LOGIN_QUERY_URL, i18n.makeString('#menu:login/auto'), HOST_AVAILABILITY.IGNORED, None)) return result def getSimpleHostsList(self, hosts): result = [] defAvail = HOST_AVAILABILITY.getDefault() predefined = tuple((host.url for host in self.peripheries())) isInProgress = self._isCSISQueryInProgress csisResGetter = self.__csisResponse.get for item in hosts: if item.url not in predefined: status = HOST_AVAILABILITY.IGNORED else: status = defAvail if isInProgress else csisResGetter( item.peripheryID, defAvail) result.append((item.url, item.name, status, item.peripheryID)) return result def urlIterator(self, primary): result = None index = self._urlMap.get(primary, -1) if index > -1: result = self._hosts[index].urlIterator return result def periphery(self, peripheryID): if peripheryID in self._peripheryMap: index = self._peripheryMap[peripheryID] return self._hosts[index] roamingHosts = dict( ((host.peripheryID, host) for host in self.roamingHosts())) if peripheryID in roamingHosts: return roamingHosts[peripheryID] def peripheries(self): return filter(lambda app: app.peripheryID, self._hosts) def roamingHosts(self): p = BigWorld.player() result = [] if hasattr(p, 'serverSettings'): for peripheryID, name, shortName, host, keyPath in p.serverSettings[ 'roaming'][3]: result.append( self._makeHostItem(name, shortName, host, keyPath=keyPath, peripheryID=peripheryID)) self.__lastRoamingHosts = sorted(result, key=operator.itemgetter(0)) return self.__lastRoamingHosts def hostsWithRoaming(self): predefined = tuple((host.url for host in self.peripheries())) hosts = self.peripheries() for h in self.roamingHosts(): if h.url not in predefined: hosts.append(h) return hosts def isRoamingPeriphery(self, peripheryID): return peripheryID not in [p.peripheryID for p in self.peripheries()] def _makeHostItem(self, name, shortName, url, urlToken='', urlIterator=None, keyPath=None, areaID=None, peripheryID=0): if not len(shortName): shortName = name return _HostItem(name, shortName, url, urlToken, urlIterator, keyPath, areaID, peripheryID) def _determineRecommendHost(self): defAvail = HOST_AVAILABILITY.NOT_AVAILABLE pResGetter = self.__pingResult.get csisResGetter = self.__csisResponse.get queryResult = map( lambda host: (host, pResGetter(host.url, -1), csisResGetter(host.peripheryID, defAvail)), self.peripheries()) self.__recommended = filter( lambda item: item[2] == HOST_AVAILABILITY.RECOMMENDED, queryResult) if not len(self.__recommended): self.__recommended = filter( lambda item: item[2] == HOST_AVAILABILITY.NOT_RECOMMENDED, queryResult) recommendLen = len(self.__recommended) if not recommendLen: if len(queryResult) > 1: LOG_DEBUG('List of recommended is empty. Gets host by ping') self.__recommended = self.__filterRecommendedByPing( queryResult) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() else: LOG_DEBUG('Gets first as recommended') result = self.first() else: LOG_DEBUG('Recommended by CSIS', self.__recommended) if recommendLen > 1: self.__recommended = self.__filterRecommendedByPing( self.__recommended) LOG_DEBUG('Recommended by ping', self.__recommended) result = self.__choiceFromRecommended() return result def __ping(self): if not self.__setPingCallback: self.__onPingPerformed([]) return try: peripheries = map(lambda host: host.url, self.peripheries()) LOG_DEBUG('Ping starting', peripheries) BigWorld.WGPinger.ping(peripheries) except (AttributeError, TypeError): LOG_CURRENT_EXCEPTION() self.__onPingPerformed([]) def __onPingPerformed(self, result): LOG_DEBUG('Ping performed', result) try: self.__pingResult = dict(result) self.__autoLoginQueryCompleted( AUTO_LOGIN_QUERY_STATE.PING_PERFORMED) except Exception: LOG_CURRENT_EXCEPTION() self.__pingResult = {} def __startCsisTimer(self): self.__cleanCsisTimerCallback() self.__csisCallbackID = BigWorld.callback(CSIS_REQUEST_TIMER, self.__onCsisTimer) def __cleanCsisTimerCallback(self): if self.__csisCallbackID: BigWorld.cancelCallback(self.__csisCallbackID) self.__csisCallbackID = None def __onCsisTimer(self): self.__csisCallbackID = None self.__sendCsisQuery() def __sendCsisQuery(self): if len(self.__csisUrl): if not self._isCSISQueryInProgress: timeFromLastUpdate = time.time() - self.__lastCsisUpdateTime if timeFromLastUpdate >= CSIS_REQUEST_TIMER: self._isCSISQueryInProgress = True self.onCsisQueryStart() allHosts = self.hosts() peripheries = map(lambda host: host.peripheryID, allHosts) LOG_DEBUG('CSIS query sending', peripheries) _CSISRequestWorker(self.__csisUrl, self.__receiveCsisResponse, peripheries).start() else: self.__finishCsisQuery() else: LOG_DEBUG('CSIS url is not defined - ignore') self._isCSISQueryInProgress = False self.stopCSISUpdate() self.__finishCsisQuery() self.__lastCsisUpdateTime = 0 def __receiveCsisResponse(self, response): LOG_DEBUG('CSIS query received', response) self._isCSISQueryInProgress = False self.__csisResponse = response self.__lastCsisUpdateTime = time.time() self.__finishCsisQuery() def __finishCsisQuery(self): if self.__csisAction & CSIS_ACTION.AUTO_LOGIN_REQUEST: self.__receiveAutoLoginCSISResponse(self.__csisResponse) if self.__csisAction & CSIS_ACTION.UPDATE_ON_TIME: self.__startCsisTimer() self.onCsisQueryComplete(self.__csisResponse) def __receiveAutoLoginCSISResponse(self, response): self.__csisAction = CSIS_ACTION.removeIfHas( self.__csisAction, CSIS_ACTION.AUTO_LOGIN_REQUEST) self.__autoLoginQueryCompleted( AUTO_LOGIN_QUERY_STATE.CSIS_RESPONSE_RECEIVED) def __autoLoginQueryCompleted(self, state): if not self.__autoLoginQueryState & state: self.__autoLoginQueryState |= state if self.__autoLoginQueryState == AUTO_LOGIN_QUERY_STATE.COMPLETED: host = self._determineRecommendHost() LOG_DEBUG('Recommended host', host) self.__autoLoginQueryState = AUTO_LOGIN_QUERY_STATE.DEFAULT self.__queryCallback(host) self.__queryCallback = None def __filterRecommendedByPing(self, recommended): result = recommended filtered = filter(lambda item: item[1] > -1, recommended) if len(filtered): minPingTime = min(filtered, key=lambda item: item[1])[1] maxPingTime = 1.2 * minPingTime result = filter(lambda item: item[1] < maxPingTime, filtered) return result def __choiceFromRecommended(self): recommended = random.choice(self.__recommended) self.__recommended = filter(lambda item: item != recommended, self.__recommended) return recommended[0]
class LobbyContext(ILobbyContext): connectionMgr = dependency.descriptor(IConnectionManager) def __init__(self): super(LobbyContext, self).__init__() self.__credentials = None self.__guiCtx = {} self.__arenaUniqueIDs = {} self.__serverSettings = ServerSettings({}) self.__battlesCount = None self.__epicBattlesCount = None self.__clientArenaIDGenerator = Int32IDGenerator() self.__headerNavigationConfirmators = set() self.__fightButtonConfirmators = set() self.__changeListener = LobbyContextChangeListener(self) self.__em = EventManager() self.onServerSettingsChanged = Event(self.__em) return def clear(self): self.__headerNavigationConfirmators.clear() self.__fightButtonConfirmators.clear() self.__credentials = None self.__battlesCount = None self.__guiCtx.clear() self.__arenaUniqueIDs.clear() if self.__serverSettings: self.__serverSettings.clear() self.__em.clear() return def onAccountBecomePlayer(self): self.setServerSettings(BigWorld.player().serverSettings) def onAccountShowGUI(self, ctx): self.__guiCtx = ctx or {} def getArenaUniqueIDByClientID(self, clientArenaID): for arenaUniqueID, cArenaID in self.__arenaUniqueIDs.iteritems(): if cArenaID == clientArenaID: return arenaUniqueID def getClientIDByArenaUniqueID(self, arenaUniqueID): if arenaUniqueID in self.__arenaUniqueIDs: return self.__arenaUniqueIDs[arenaUniqueID] clientID = self.__clientArenaIDGenerator.next() self.__arenaUniqueIDs[arenaUniqueID] = clientID return clientID def setCredentials(self, login, token): self.__credentials = (login, token) def getCredentials(self): return self.__credentials def getBattlesCount(self): return self.__battlesCount def getEpicBattlesCount(self): return self.__epicBattlesCount def updateBattlesCount(self, battlesCount, epicBattlesCount): self.__battlesCount = battlesCount self.__epicBattlesCount = epicBattlesCount def update(self, diff): if self.__serverSettings: if 'serverSettings' in diff: self.__notifyToUpdate(diff['serverSettings']) self.__changeListener.update(diff['serverSettings']) self.__serverSettings.update(diff['serverSettings']) elif ('serverSettings', '_r') in diff: self.__notifyToUpdate(diff[('serverSettings', '_r')]) self.__changeListener.update(diff[('serverSettings', '_r')]) self.__serverSettings.set(diff[('serverSettings', '_r')]) def updateGuiCtx(self, ctx): self.__guiCtx.update(ctx) def getGuiCtx(self): return self.__guiCtx @property def collectUiStats(self): return self.__guiCtx.get('collectUiStats', True) @property def needLogUXEvents(self): return self.__guiCtx.get('logUXEvents', False) def getServerSettings(self): return self.__serverSettings def setServerSettings(self, serverSettings): if self.__serverSettings: self.__serverSettings.clear() self.__serverSettings = ServerSettings(serverSettings) self.onServerSettingsChanged(self.__serverSettings) def getPlayerFullName(self, pName, clanInfo=None, clanAbbrev=None, regionCode=None, pDBID=None): fullName = pName if clanInfo and len(clanInfo) > 1: clanAbbrev = clanInfo[1] if clanAbbrev: fullName = '{0:>s} [{1:>s}]'.format(pName, clanAbbrev) if pDBID is not None: regionCode = self.getRegionCode(pDBID) if regionCode: fullName = '{0:>s} {1:>s}'.format(fullName, regionCode) return fullName def getClanAbbrev(self, clanInfo): clanAbbrev = None if clanInfo and len(clanInfo) > 1: clanAbbrev = clanInfo[1] return clanAbbrev def getRegionCode(self, dbID): regionCode = None serverSettings = self.getServerSettings() if serverSettings is not None: roaming = serverSettings.roaming if dbID and not roaming.isSameRealm(dbID): _, regionCode = roaming.getPlayerHome(dbID) return regionCode def isAnotherPeriphery(self, peripheryID): if not self._isSkipPeripheryChecking(): return self.connectionMgr.peripheryID != peripheryID LOG_NOTE('Skip periphery checking in standalone mode') return False @dependency.replace_none_kwargs(itemsCache=IItemsCache) def isPeripheryAvailable(self, peripheryID, itemsCache=None): result = True if self._isSkipPeripheryChecking(): LOG_NOTE('Skip periphery checking in standalone mode') return result else: if g_preDefinedHosts.periphery(peripheryID) is None: LOG_ERROR('Periphery not found', peripheryID) result = False elif self.__credentials is None: LOG_ERROR('Login info not found', peripheryID) result = False elif g_preDefinedHosts.isRoamingPeriphery( peripheryID ) and itemsCache is not None and not isRoamingEnabled( itemsCache.items.stats.attributes): LOG_ERROR('Roaming is not supported', peripheryID) result = False return result def getPeripheryName(self, peripheryID, checkAnother=True): name = None if not checkAnother or self.isAnotherPeriphery(peripheryID): host = g_preDefinedHosts.periphery(peripheryID) if host is not None: name = host.name return name def addHeaderNavigationConfirmator(self, confirmator): self.__headerNavigationConfirmators.add(confirmator) def deleteHeaderNavigationConfirmator(self, confirmator): if confirmator in self.__headerNavigationConfirmators: self.__headerNavigationConfirmators.remove(confirmator) @async @process def isHeaderNavigationPossible(self, callback=None): for confirmator in self.__headerNavigationConfirmators: confirmed = yield confirmator() if not confirmed: callback(False) callback(True) def addFightButtonConfirmator(self, confirmator): self.__fightButtonConfirmators.add(confirmator) def deleteFightButtonConfirmator(self, confirmator): if confirmator in self.__fightButtonConfirmators: self.__fightButtonConfirmators.remove(confirmator) @async @process def isFightButtonPressPossible(self, callback=None): for confirmator in self.__fightButtonConfirmators: confirmed = yield confirmator() if not confirmed: callback(False) callback(True) @classmethod def _isSkipPeripheryChecking(cls): return cls.connectionMgr.isStandalone() and CURRENT_REALM == 'CT' @dependency.replace_none_kwargs(itemsCache=IItemsCache) def __notifyToUpdate(self, diff, itemsCache=None): if 'lootBoxes_config' in diff: itemsCache.items.tokens.updateAllLootBoxes( diff['lootBoxes_config'])
class RefSystem(Controller): def __init__(self, proxy): super(RefSystem, self).__init__(proxy) self.__referrers = [] self.__referrals = [] self.__quests = [] self.__xpPoolOfDeletedRals = 0 self.__totalXP = 0 self.__isTotallyCompleted = False self.__posByXPinTeam = 0 self.__eventMgr = EventManager() self.onUpdated = Event(self.__eventMgr) self.onQuestsUpdated = Event(self.__eventMgr) self.onPlayerBecomeReferrer = Event(self.__eventMgr) self.onPlayerBecomeReferral = Event(self.__eventMgr) @storage_getter('users') def usersStorage(self): return None def fini(self): self.__referrers = None self.__referrals = None self.__eventMgr.clear() self.__clearQuestsData() super(RefSystem, self).fini() def onLobbyStarted(self, ctx): g_clientUpdateManager.addCallbacks({'stats.refSystem': self.__onRefStatsUpdated}) g_eventsCache.onSyncCompleted += self.__onEventsUpdated g_playerEvents.onShopResync += self.__onShopUpdated self.__update(g_itemsCache.items.stats.refSystem) self.__updateQuests() def onAvatarBecomePlayer(self): self.__stop() def onDisconnected(self): self.__stop() def getReferrers(self): return self.__referrers def getReferrals(self): return self.__referrals def getQuests(self): return self.__quests def isTotallyCompleted(self): return self.__isTotallyCompleted def getPosByXPinTeam(self): return self.__posByXPinTeam def getTotalXP(self): return self.__totalXP def getReferralsXPPool(self): result = self.__xpPoolOfDeletedRals for i in self.getReferrals(): result += i.getXPPool() return result def getAvailableReferralsCount(self): return _getMaxNumberOfReferrals() - len(self.__referrals) def showTankmanAwardWindow(self, tankman, completedQuestIDs): LOG_DEBUG('Referrer has been get tankman award', tankman, completedQuestIDs) curXp, nextXp, _ = self.__getAwardParams(completedQuestIDs) shared_events.showAwardWindow(TankmanAward(tankman, curXp, nextXp)) def showVehicleAwardWindow(self, vehicle, completedQuestIDs): LOG_DEBUG('Referrer has been get vehicle award', vehicle, completedQuestIDs) curXp, nextXp, isBoughtVehicle = self.__getAwardParams(completedQuestIDs) shared_events.showAwardWindow(VehicleAward(vehicle, isBoughtVehicle, curXp)) def showCreditsAwardWindow(self, creditsValue, completedQuestIDs): if creditsValue > 0: LOG_DEBUG('Referrer has been get credits award', creditsValue, completedQuestIDs) shared_events.showAwardWindow(CreditsAward(creditsValue)) @classmethod def getRefPeriods(cls): return _getRefSystemPeriods() @classmethod def getMaxReferralXPPool(cls): return _getMaxReferralXPPool() @classmethod def getMaxNumberOfReferrals(cls): return _getMaxNumberOfReferrals() @classmethod def isReferrer(cls): refSystemStats = g_itemsCache.items.stats.refSystem return refSystemStats.get('activeInvitations', 0) > 0 or len(refSystemStats.get('referrals', {})) > 0 def showReferrerIntroWindow(self, invitesCount): g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.REFERRAL_REFERRER_INTRO_WINDOW, ctx={'invitesCount': invitesCount})) self.onPlayerBecomeReferrer() def showReferralIntroWindow(self, nickname, isNewbie = False): g_eventBus.handleEvent(events.LoadViewEvent(VIEW_ALIAS.REFERRAL_REFERRALS_INTRO_WINDOW, ctx={'referrerName': nickname, 'newbie': isNewbie})) self.onPlayerBecomeReferral() def __stop(self): g_playerEvents.onShopResync -= self.__onShopUpdated g_eventsCache.onSyncCompleted -= self.__onEventsUpdated g_clientUpdateManager.removeObjectCallbacks(self) def __getAwardParams(self, completedQuestIDs): completedQuestID = completedQuestIDs.pop() if len(completedQuestIDs) else -1 currentXP = nextXP = None for xp, quests in reversed(self.getQuests()): if completedQuestID in map(methodcaller('getID'), quests): currentXP = xp break else: nextXP = xp return (currentXP, nextXP, self.getReferralsXPPool() < self.getTotalXP()) def __clearQuestsData(self): self.__quests = [] self.__isTotallyCompleted = False self.__totalXP = 0 def __update(self, data): self.__referrers = [] self.__referrals = [] self.__xpPoolOfDeletedRals = 0 self.__posByXPinTeam = g_itemsCache.items.shop.refSystem['posByXPinTeam'] storage = self.usersStorage userGetter = storage.getUser userSetter = storage.addUser storage.removeTags({USER_TAG.REFERRER, USER_TAG.REFERRAL}) def updateUser(item, tags): dbID = item.getAccountDBID() user = userGetter(dbID) if user: user.addTags(tags) if USER_TAG.INVALID_NAME in user.getTags(): user.update(name=item.getNickName()) else: userSetter(SharedUserEntity(dbID, name=item.getNickName(), tags=tags, clanInfo=ClanInfo(abbrev=item.getClanAbbrev()))) for referrer in self.__buildReferrers(data): self.__referrers.append(referrer) updateUser(referrer, {USER_TAG.REFERRER}) for referral in self.__buildReferrals(data): self.__referrals.append(referral) updateUser(referral, {USER_TAG.REFERRAL}) self.onUpdated() g_messengerEvents.users.onUsersListReceived({USER_TAG.REFERRER, USER_TAG.REFERRAL}) @classmethod def __makeRefItem(cls, dbID, **data): try: return _RefItem(dbID, **data) except: LOG_ERROR('There is error while building ref system item') LOG_CURRENT_EXCEPTION() def __buildReferrers(self, data): for key, item in (data.get('referrers') or {}).iteritems(): referrer = self.__makeRefItem(key, **item) if referrer is not None: yield referrer def __buildReferrals(self, data): for key, item in (data.get('referrals') or {}).iteritems(): if key == 'xpPoolOfDeletedRals': self.__xpPoolOfDeletedRals = item else: referral = self.__makeRefItem(key, **item) if referral is not None: yield referral def __updateQuests(self): self.__clearQuestsData() refSystemQuests = g_eventsCache.getHiddenQuests(lambda x: x.getType() == EVENT_TYPE.REF_SYSTEM_QUEST) if refSystemQuests: self.__quests = self.__mapQuests(refSystemQuests.values()) self.__totalXP, _ = self.__quests[-1] notCompleted = findFirst(lambda q: not q.isCompleted(), refSystemQuests.values()) self.__isTotallyCompleted = notCompleted is None self.onQuestsUpdated() @classmethod def __mapQuests(cls, events): result = defaultdict(list) for event in sorted(events, key=methodcaller('getID')): result[event.accountReqs.getConditions().find('refSystemRalXPPool').getValue()].append(event) return sorted(result.iteritems(), key=itemgetter(0)) def __onRefStatsUpdated(self, diff): self.__update(g_itemsCache.items.stats.refSystem) def __onEventsUpdated(self): self.__updateQuests() def __onShopUpdated(self): self.__update(g_itemsCache.items.stats.refSystem) self.__updateQuests()
class ConnectionManager(IConnectionManager): def __init__(self): self.__connectionData = ConnectionData() self.__connectionUrl = None self.__connectionMethod = CONNECTION_METHOD.BASIC self.__connectionStatus = LOGIN_STATUS.NOT_SET self.__lastLoginName = None self.__hostItem = g_preDefinedHosts._makeHostItem('', '', '') self.__retryConnectionPeriod = _MIN_RECONNECTION_TIMEOUT self.__retryConnectionCallbackID = None g_playerEvents.onKickWhileLoginReceived += self.__processKick g_playerEvents.onLoginQueueNumberReceived += self.__processQueue self.__eManager = EventManager() self.onLoggedOn = Event(self.__eManager) self.onConnected = Event(self.__eManager) self.onRejected = Event(self.__eManager) self.onDisconnected = Event(self.__eManager) self.onKickedFromServer = Event(self.__eManager) self.onKickWhileLoginReceived = Event(self.__eManager) self.onQueued = Event(self.__eManager) return def fini(self): g_playerEvents.onKickWhileLoginReceived -= self.__processKick g_playerEvents.onLoginQueueNumberReceived -= self.__processQueue self.__eManager.clear() self.stopRetryConnection() def initiateConnection(self, params, password, serverName): self.__setConnectionData(params, password) if serverName == AUTO_LOGIN_QUERY_URL: g_preDefinedHosts.autoLoginQuery(self.__setHostDataAndConnect) else: self.__setHostDataAndConnect(g_preDefinedHosts.byUrl(serverName)) def stopRetryConnection(self): if self.__retryConnectionCallbackID is not None: BigWorld.cancelCallback(self.__retryConnectionCallbackID) self.__retryConnectionPeriod = 0 self.__retryConnectionCallbackID = None return @uniprof.regionDecorator(label='offline.connect', scope='enter') def __connect(self): self.__retryConnectionCallbackID = None if constants.IS_DEVELOPMENT: LOG_DEBUG( 'Calling BigWorld.connect with params: {0}, serverName: {1}, inactivityTimeout: {2}, publicKeyPath: {3}' .format(self.__connectionData.username, self.__connectionUrl, constants.CLIENT_INACTIVITY_TIMEOUT, self.__connectionData.publicKeyPath)) nextTick(lambda: BigWorld. connect(self.__connectionUrl, self.__connectionData, self. __serverResponseHandler))() if g_preDefinedHosts.predefined( self.__connectionUrl) or g_preDefinedHosts.roaming( self.__connectionUrl): self.__hostItem = g_preDefinedHosts.byUrl(self.__connectionUrl) else: for server in BigWorld.serverDiscovery.servers: if server.serverString == self.__connectionUrl: self.__hostItem = self.__hostItem._replace( name=server.ownerName, shortName=server.ownerName) break else: self.__hostItem = self.__hostItem._replace( name=self.__connectionUrl, shortName=self.__connectionUrl) return @uniprof.regionDecorator(label='offline.connect', scope='exit') def __serverResponseHandler(self, stage, status, responseDataJSON): if constants.IS_DEVELOPMENT: LOG_DEBUG( 'Received server response with stage: {0}, status: {1}, responseData: {2}' .format(stage, status, responseDataJSON)) self.__connectionStatus = status try: responseData = json.loads(responseDataJSON) except ValueError: responseData = {'errorMessage': responseDataJSON} if status == LOGIN_STATUS.LOGGED_ON: if stage == 1: if self.__connectionMethod == CONNECTION_METHOD.TOKEN and 'token2' in responseData: self.__swtichToToken2(responseData['token2']) self.onLoggedOn(responseData) self.onConnected() else: if self.__retryConnectionCallbackID is None: status_ = self.__connectionStatus errorMsg = responseData.get('errorMessage', '') if errorMsg in INVALID_TOKEN2_EXPIRED: status_ = LOGIN_STATUS.SESSION_END self.onRejected(status_, responseData) if status == LOGIN_STATUS.LOGIN_REJECTED_RATE_LIMITED: self.__reconnect() if stage == 6: self.onDisconnected() g_playerEvents.onDisconnected() return def __setConnectionData(self, params, password): self.__connectionMethod = params['auth_method'] if 'auth_realm' not in params: params['auth_realm'] = constants.AUTH_REALM m = hashlib.md5() m.update(params['session']) params['session'] = m.hexdigest() if constants.IS_IGR_ENABLED: params['is_igr'] = '1' username_ = json.dumps(params, encoding='utf-8') LOG_NOTE('User authentication method: {0}'.format( params['auth_method'])) if 'token2' in params and params['token2']: password = '' else: password = pwd_token.generate(password) self.__connectionData.username = username_ self.__connectionData.password = password self.__connectionData.inactivityTimeout = constants.CLIENT_INACTIVITY_TIMEOUT self.__connectionData.clientContext = json.dumps( {'lang_id': getClientLanguage()}) if constants.IS_DEVELOPMENT and params[ 'auth_method'] == CONNECTION_METHOD.BASIC and params['login'][ 0] == '@': try: self.__connectionData.username = params['login'][1:] except IndexError: self.__connectionData.username = params['login'] def __swtichToToken2(self, token2): self.__connectionMethod = CONNECTION_METHOD.TOKEN2 params = json.loads(self.__connectionData.username, encoding='utf-8') params.pop('token', None) params['token2'] = token2 params['auth_method'] = CONNECTION_METHOD.TOKEN2 self.__connectionData.username = json.dumps(params, encoding='utf-8') return def __setHostData(self, predefinedHost): self.__connectionData.publicKeyPath = predefinedHost.keyPath self.__connectionUrl = predefinedHost.urlToken if ( self.__connectionMethod == CONNECTION_METHOD.TOKEN or self.__connectionMethod == CONNECTION_METHOD.TOKEN2 ) and predefinedHost.urlToken else predefinedHost.url def __setHostDataAndConnect(self, predefinedHost): self.__setHostData(predefinedHost) self.__connect() def __reconnect(self): self.stopRetryConnection() self.__retryConnectionCallbackID = BigWorld.callback( self.__getRetryConnectionPeriod(), self.__connect) def __getRetryConnectionPeriod(self): if self.__retryConnectionPeriod != _MAX_RECONNECTION_TIMEOUT: self.__retryConnectionPeriod += _RECONNECTION_TIMEOUT_INCREMENT return self.__retryConnectionPeriod def __processKick(self, peripheryID): if peripheryID > 0: host = g_preDefinedHosts.periphery(peripheryID, False) if host is not None: self.__setHostData(host) self.__reconnect() self.onKickWhileLoginReceived(peripheryID) return def __processQueue(self, queueNumber): self.onQueued(queueNumber) @property def serverUserName(self): return self.__hostItem.name @property def serverUserNameShort(self): return self.__hostItem.shortName @property def peripheryID(self): return self.__hostItem.peripheryID @property def areaID(self): return self.__hostItem.areaID if not self.isDisconnected() else None @property def url(self): return self.__hostItem.url @property def loginName(self): return self.__lastLoginName if not self.isDisconnected() else None @property def lastLoginName(self): return self.__lastLoginName @property def databaseID(self): return BigWorld.player( ).databaseID if not self.isDisconnected() else None @property def connectionMethod(self): return self.__connectionMethod def disconnect(self): BigWorld.disconnect() def setKickedFromServer(self, reason, isBan, expiryTime): self.disconnect() self.onKickedFromServer(reason, isBan, expiryTime) def isDisconnected(self): return self.__connectionStatus != LOGIN_STATUS.LOGGED_ON def isStandalone(self): return self.peripheryID == 0 def isConnected(self): return self.__connectionStatus == LOGIN_STATUS.LOGGED_ON def checkClientServerVersions(self, clientVersion, serverVersion): if not isValidClientVersion(clientVersion, serverVersion) or ResMgr.activeContentType( ) in (constants.CONTENT_TYPE.INCOMPLETE, constants.CONTENT_TYPE.TUTORIAL): LOG_DEBUG('Version mismatch. Client is "%s", server needs "%s".' % (clientVersion, serverVersion)) self.onRejected(LOGIN_STATUS.LOGIN_BAD_PROTOCOL_VERSION, {}) BigWorld.disconnect() def setLastLogin(self, email): self.__lastLoginName = email
class FunRandomController(IFunRandomController, Notifiable, SeasonProvider, IGlobalListener): _ALERT_DATA_CLASS = FunRandomAlertData __itemsCache = dependency.descriptor(IItemsCache) __lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(FunRandomController, self).__init__() self.__em = EventManager() self.onUpdated = Event(self.__em) self.onGameModeStatusTick = Event(self.__em) self.onGameModeStatusUpdated = Event(self.__em) self.__serverSettings = None self.__funRandomSettings = None self.__modifiersDataProvider = ModifiersDataProvider() return def init(self): super(FunRandomController, self).init() self.addNotificator( SimpleNotifier(self.getTimer, self.__gameModeStatusUpdate)) self.addNotificator( TimerNotifier(self.getTimer, self.__gameModeStatusTick)) def fini(self): self.__em.clear() self.clearNotification() super(FunRandomController, self).fini() def onAccountBecomePlayer(self): self.__onServerSettingsChanged(self.__lobbyContext.getServerSettings()) def onAccountBecomeNonPlayer(self): self.stopNotification() self.stopGlobalListening() def onDisconnected(self): self.stopNotification() self.stopGlobalListening() if self.__serverSettings is not None: self.__serverSettings.onServerSettingsChange -= self.__onServerSettingsUpdate self.__serverSettings = self.__funRandomSettings = self.__modifiersDataProvider = None return def onLobbyInited(self, event=None): self.startNotification() self.startGlobalListening() def isAvailable(self): return self.isBattlesPossible() and not self.isFrozen() def isBattlesPossible(self): return self.isEnabled() and self.getCurrentSeason() is not None def isEnabled(self): return self.__funRandomSettings.isEnabled def isFunRandomPrbActive(self): return False if self.prbEntity is None else bool( self.prbEntity.getModeFlags() & FUNCTIONAL_FLAG.FUN_RANDOM) def isSuitableVehicle(self, vehicle, isSquad=False): restriction = '' ctx = {} settings = self.__funRandomSettings state, _ = vehicle.getState() restrictions = UNIT_RESTRICTION if isSquad else PRE_QUEUE_RESTRICTION if state == Vehicle.VEHICLE_STATE.UNSUITABLE_TO_QUEUE or vehicle.compactDescr in settings.forbiddenVehTypes: restriction = restrictions.LIMIT_VEHICLE_TYPE ctx = {'forbiddenType': vehicle.shortUserName} if vehicle.type in settings.forbiddenClassTags: restriction = restrictions.LIMIT_VEHICLE_CLASS ctx = {'forbiddenClass': vehicle.type} if vehicle.level not in settings.levels: restriction = restrictions.LIMIT_LEVEL ctx = {'levels': settings.levels} return ValidationResult(False, restriction, ctx) if restriction else None def isSuitableVehicleAvailable(self): criteria = self.__getSuitableVehiclesCriteria(REQ_CRITERIA.UNLOCKED) criteria |= ~REQ_CRITERIA.VEHICLE.SECRET | ~REQ_CRITERIA.HIDDEN | ~REQ_CRITERIA.VEHICLE.PREMIUM unlockedVehicles = self.__itemsCache.items.getVehicles(criteria) return len(unlockedVehicles) > 0 def canGoToMode(self): return self.hasSuitableVehicles() or self.isSuitableVehicleAvailable() def hasSuitableVehicles(self): criteria = self.__getSuitableVehiclesCriteria(REQ_CRITERIA.INVENTORY) criteria |= ~REQ_CRITERIA.VEHICLE.EXPIRED_RENT return len(self.__itemsCache.items.getVehicles(criteria)) > 0 def getAlertBlock(self): if self.hasSuitableVehicles(): alertData = self._getAlertBlockData() buttonCallback = event_dispatcher.showFunRandomPrimeTimeWindow else: alertData = self._ALERT_DATA_CLASS.constructNoVehicles() buttonCallback = event_dispatcher.showFunRandomInfoPage return (buttonCallback, alertData or self._ALERT_DATA_CLASS(), alertData is not None) def getModeSettings(self): return self.__funRandomSettings def getModifiersDataProvider(self): return self.__modifiersDataProvider @adisp.process def selectFunRandomBattle(self): dispatcher = self.prbDispatcher if dispatcher is None: _logger.error('Prebattle dispatcher is not defined') return else: yield dispatcher.doSelectAction( PrbAction(PREBATTLE_ACTION_NAME.FUN_RANDOM)) return def _createSeason(self, cycleInfo, seasonData): return FunRandomSeason(cycleInfo, seasonData, self.__funRandomSettings.eventID) def __onServerSettingsChanged(self, serverSettings): if self.__serverSettings is not None: self.__serverSettings.onServerSettingsChange -= self.__onServerSettingsUpdate self.__serverSettings = serverSettings self.__serverSettings.onServerSettingsChange += self.__onServerSettingsUpdate self.__updateFunRandomSettings() return def __onServerSettingsUpdate(self, diff): if Configs.FUN_RANDOM_CONFIG.value in diff: self.__updateFunRandomSettings() def __getSuitableVehiclesCriteria(self, criteria): criteria = criteria | REQ_CRITERIA.VEHICLE.LEVELS( self.__funRandomSettings.levels) criteria |= ~REQ_CRITERIA.VEHICLE.CLASSES( self.__funRandomSettings.forbiddenClassTags) criteria |= ~REQ_CRITERIA.VEHICLE.SPECIFIC_BY_CD( self.__funRandomSettings.forbiddenVehTypes) criteria |= ~REQ_CRITERIA.VEHICLE.HAS_TAGS( BATTLE_MODE_VEH_TAGS_EXCEPT_FUN) return criteria def __gameModeStatusTick(self): self.onGameModeStatusTick() def __gameModeStatusUpdate(self): status, _, _ = self.getPrimeTimeStatus() self.onGameModeStatusUpdated(status) def __resetGameModeStatusTimers(self): self.startNotification() self.__gameModeStatusUpdate() self.__gameModeStatusTick() def __updateFunRandomSettings(self): self.__funRandomSettings = self.__serverSettings.funRandomConfig self.__modifiersDataProvider = ModifiersDataProvider( self.__funRandomSettings.battleModifiersDescr) self.__rememberGameMode() self.__resetGameModeStatusTimers() self.onUpdated() def __rememberGameMode(self): currentCycleID = self.getCurrentCycleID() rememberedCycleID = AccountSettings.getSettings( FUN_RANDOM_LAST_CYCLE_ID) if currentCycleID is not None and currentCycleID != rememberedCycleID: AccountSettings.setSettings(FUN_RANDOM_LAST_CYCLE_ID, currentCycleID) SelectorBattleTypesUtils.setBattleTypeAsUnknown( SELECTOR_BATTLE_TYPES.FUN_RANDOM) return
class AbstractContextMenuHandler(object): __metaclass__ = ABCMeta def __init__(self, cmProxy, ctx=None, handlers=None): self._eManager = EventManager() self.onContextMenuHide = Event(self._eManager) super(AbstractContextMenuHandler, self).__init__() self.__cmProxy = weakref.proxy(cmProxy) self.__handlers = handlers or {} self._initFlashValues(ctx) @property def app(self): return self.__cmProxy.app def fini(self): self._eManager.clear() self.__handlers = None self.__cmProxy = None self._clearFlashValues() return def getOptions(self, ctx=None): return self._generateOptions(ctx) def onOptionSelect(self, optionId): if optionId in self.__handlers: return getattr(self, self.__handlers[optionId])() LOG_WARNING('Unknown context menu option', self, self.__cmProxy, optionId) def getCMInfo(self): pass def _dispatchChanges(self, options): if self.__cmProxy is not None: self.__cmProxy._onOptionsChanged(options) return @classmethod def _makeItem(cls, optId, optLabel=None, optInitData=None, optSubMenu=None, linkage=None, iconType=''): return { 'id': optId, 'label': optLabel, 'iconType': iconType, 'initData': cls.__makeOptDataDefaults(optInitData), 'submenu': optSubMenu, 'linkage': linkage } def _makeSeparator(self): return self._makeItem(_SEPARATOR_ID) @abstractmethod def _generateOptions(self, ctx=None): raise NotImplementedError def _initFlashValues(self, ctx): pass def _clearFlashValues(self): pass @staticmethod def __makeOptDataDefaults(optInitData): if optInitData is None: return {'visible': True} else: if 'visible' not in optInitData or optInitData['visible'] is None: optInitData['visible'] = True return optInitData
class TabsContainer(object): def __init__(self): self.__tabs = { TABS_IDS.INVENTORY: InventoryBoostersTab(), TABS_IDS.QUESTS: QuestsBoostersTab(), TABS_IDS.SHOP: ShopBoostersTab(), } self.__currentTabIdx = None self.__activeBoostersCount = None self.__eManager = EventManager() self.onTabsUpdate = Event(self.__eManager) return def init(self): self.__activeBoostersCount = len(g_goodiesCache.getBoosters(criteria=REQ_CRITERIA.BOOSTER.ACTIVE).values()) g_clientUpdateManager.addCallbacks( {"goodies": self.__onUpdateBoosters, "shop": self.__onUpdateBoosters, "stats": self.__onStatsChanged} ) g_eventsCache.onSyncCompleted += self.__onQuestsUpdate def setCurrentTabIdx(self, currentTabIdx): self.__currentTabIdx = currentTabIdx @property def currentTab(self): return self.__tabs[self.__currentTabIdx] @property def inventoryTab(self): return self.__tabs[TABS_IDS.INVENTORY] @property def shopTab(self): return self.__tabs[TABS_IDS.SHOP] @property def questsTab(self): return self.__tabs[TABS_IDS.QUESTS] def getTabs(self): return self.__tabs def setFilters(self, qualities, boosterTypes): for tab in self.__tabs.itervalues(): tab.setFilters(qualities, boosterTypes) def getActiveBoostersCount(self): return self.__activeBoostersCount def fini(self): self.__currentTabIdx = None self.__eManager.clear() g_clientUpdateManager.removeObjectCallbacks(self) g_eventsCache.onSyncCompleted -= self.__onQuestsUpdate for tab in self.__tabs.itervalues(): tab.fini() self.__tabs.clear() self.__activeBoostersCount = None return def __onUpdateBoosters(self, *args): for tab in self.__tabs.itervalues(): tab.update() self.__activeBoostersCount = len(g_goodiesCache.getBoosters(criteria=REQ_CRITERIA.BOOSTER.ACTIVE).values()) self.onTabsUpdate() def __onQuestsUpdate(self, *args): self.questsTab.updateQuests() self.__onUpdateBoosters() def __onStatsChanged(self, stats): if "credits" in stats or "gold" in stats: self.shopTab.updateBalance() self.onTabsUpdate()