class BattleSessionProvider(IBattleSessionProvider): __slots__ = ('__ctx', '__sharedRepo', '__dynamicRepo', '__requestsCtrl', '__arenaDP', '__arenaListeners', '__viewComponentsBridge', '__weakref__', '__arenaVisitor', '__invitations', '__isReplayPlaying', '__battleCache') def __init__(self): super(BattleSessionProvider, self).__init__() self.__ctx = BattleContext() self.__sharedRepo = controllers.SharedControllersLocator() self.__dynamicRepo = controllers.DynamicControllersLocator() self.__requestsCtrl = None self.__arenaDP = None self.__arenaVisitor = arena_visitor.createSkeleton() self.__arenaListeners = None self.__viewComponentsBridge = None self.__invitations = None self.__isReplayPlaying = False self.__battleCache = BattleClientCache() return @property def shared(self): return self.__sharedRepo @property def dynamic(self): return self.__dynamicRepo @property def arenaVisitor(self): return self.__arenaVisitor @property def invitations(self): return self.__invitations @property def battleCache(self): return self.__battleCache @property def isReplayPlaying(self): return self.__isReplayPlaying def getCtx(self): return self.__ctx @async def sendRequest(self, ctx, callback, allowDelay=None): self.__requestsCtrl.request(ctx, callback=callback, allowDelay=allowDelay) def setPlayerVehicle(self, vID, vDesc): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.setGunSettings(vDesc.gun) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.notifyPlayerVehicleSet() ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.setPlayerVehicle(vID) ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.spawnVehicle(vID) mapKind = self.__arenaVisitor.type.getVehicleCamouflageKind() g_tankActiveCamouflage[ vDesc.type.compactDescr] = SeasonType.fromArenaKind(mapKind) return def switchVehicle(self, vehicleID): repo = self.shared for ctrl in (repo.ammo, repo.equipments, repo.optionalDevices): if ctrl is not None: ctrl.clear(False) repo.vehicleState.switchToOther(vehicleID) return def updateObservedVehicleData(self, vID, extraData): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl.setGunSettings(extraData.gunSettings) for intCD, quantity, quantityInClip in extraData.orderedAmmo: ctrl.setShells(intCD, quantity, quantityInClip) ctrl.setCurrentShellCD(extraData.currentShellCD) ctrl.setNextShellCD(extraData.nextShellCD) ctrl.setGunReloadTime(extraData.reloadTimeLeft, extraData.reloadBaseTime) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) for intCD, quantity, stage, timeRemaining, totalTime in extraData.orderedEquipment: ctrl.setEquipment(intCD, quantity, stage, timeRemaining, totalTime) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) for deviceID, isOn in extraData.orderedOptionalDevices: ctrl.setOptionalDevice(deviceID, isOn) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.refreshVehicleStateValue(VEHICLE_VIEW_STATE.HEALTH) ctrl.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_CHANGED, vID) return def getArenaDP(self): return self.__arenaDP def addArenaCtrl(self, controller): return self.__arenaListeners.addController( controller) if self.__arenaListeners is not None else False def removeArenaCtrl(self, controller): if self.__arenaListeners is not None: self.__arenaListeners.removeController(controller) return def registerViewComponentsCtrl(self, controller): if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerController(controller) return True else: return False def registerViewComponents(self, *data): if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerViewComponents(*data) return def addViewComponent(self, componentID, component, rule=VIEW_COMPONENT_RULE.PROXY): if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.addViewComponent(componentID, component, rule=rule) return def removeViewComponent(self, componentID): if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.removeViewComponent(componentID) return def getExitResult(self): if not self.__isReplayPlaying and not self.__arenaVisitor.gui.isTrainingBattle( ) and not self.__arenaVisitor.gui.isEventBattle(): vInfo = self.__arenaDP.getVehicleInfo() vStats = self.__arenaDP.getVehicleStats() if self.__arenaVisitor.hasRespawns(): isDeserter = not vStats.stopRespawn else: isDeserter = avatar_getter.isVehicleAlive( ) and not avatar_getter.isVehicleOverturned() return BattleExitResult(isDeserter, vInfo.player) else: return BattleExitResult(False, None) return None @staticmethod def exit(): avatar_getter.leaveArena() def start(self, setup): self.__isReplayPlaying = setup.isReplayPlaying self.__arenaVisitor = arena_visitor.createByAvatar(avatar=setup.avatar) setup.sessionProvider = weakref.proxy(self) self.__arenaDP = ArenaDataProvider(setup) self.__ctx.start(self.__arenaDP) self.__battleCache.load() self.__arenaListeners = ListenersCollection() self.__arenaListeners.start(setup) self.__viewComponentsBridge = createComponentsBridge() setup.sessionProvider = weakref.proxy(self) self.__sharedRepo = controllers.createShared(setup) self.__dynamicRepo = controllers.createDynamic(setup) self.__requestsCtrl = AvatarRequestsController() self.__invitations = invitations.createInvitationsHandler(setup) setup.clear() g_playerEvents.onBattleResultsReceived += self.__pe_onBattleResultsReceived def stop(self): g_playerEvents.onBattleResultsReceived -= self.__pe_onBattleResultsReceived if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.clear() self.__viewComponentsBridge = None if self.__invitations is not None: self.__invitations.clear() self.__invitations = None if self.__requestsCtrl is not None: self.__requestsCtrl.fini() self.__requestsCtrl = None if self.__arenaListeners is not None: self.__arenaListeners.stop() self.__arenaListeners = None if self.__arenaDP is not None: self.__arenaDP.clear() self.__arenaDP = None self.__sharedRepo.destroy() self.__dynamicRepo.destroy() self.__arenaVisitor.clear() self.__arenaVisitor = arena_visitor.createSkeleton() self.__battleCache.clear() self.__ctx.stop() return def switchToPostmortem(self, noRespawnPossible=True, respawnAvailable=False): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.switchToPostmortem(noRespawnPossible, respawnAvailable) return def useLoaderIntuition(self): ctrl = self.__sharedRepo.messages if ctrl is not None: ctrl.showVehicleMessage('LOADER_INTUITION_WAS_USED') ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.useLoaderIntuition() return def movingToRespawnBase(self): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.movingToRespawn() ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.movingToRespawn() return def invalidateVehicleState(self, state, value, vehicleID=0): ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.invalidate(state, value, vehicleID) if state == VEHICLE_VIEW_STATE.DESTROYED: ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(leave=False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(leave=False) return def setVehicleHealth(self, isPlayerVehicle, vehicleID, newHealth, attackerID, attackReasonID): if not isPlayerVehicle: ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.setVehicleNewHealth(vehicleID, newHealth, attackerID, attackReasonID) ctrl = self.__dynamicRepo.battleField if ctrl is not None: ctrl.setVehicleHealth(vehicleID, newHealth) return def repairPointAction(self, repairPointIndex, action, nextActionTime): ctrl = self.__dynamicRepo.repair if ctrl is not None: ctrl.action(repairPointIndex, action, nextActionTime) return def updateAvatarPrivateStats(self, stats): ctrl = self.__sharedRepo.privateStats if ctrl is not None: ctrl.update(stats) return def addHitDirection(self, hitDirYaw, attackerID, damage, isBlocked, critFlags, isHighExplosive, damagedID, attackReasonID): hitDirectionCtrl = self.__sharedRepo.hitDirection if hitDirectionCtrl is not None: atackerVehInfo = self.__arenaDP.getVehicleInfo(attackerID) atackerVehType = atackerVehInfo.vehicleType isAlly = self.__arenaDP.isAllyTeam(atackerVehInfo.team) playerVehType = self.__arenaDP.getVehicleInfo( damagedID).vehicleType hitData = HitData( yaw=hitDirYaw, attackerID=attackerID, isAlly=isAlly, damage=damage, attackerVehName=atackerVehType.shortNameWithPrefix, isBlocked=isBlocked, attackerVehClassTag=atackerVehType.classTag, critFlags=critFlags, playerVehMaxHP=playerVehType.maxHealth, isHighExplosive=isHighExplosive, attackReasonID=attackReasonID) if not hitData.isNonPlayerAttackReason( ) and not hitData.isBattleAbilityConsumable(): hitDirectionCtrl.addHit(hitData) return def startVehicleVisual(self, vProxy, isImmediate=False): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.startVehicleVisual(vProxy, isImmediate) ctrl = self.__dynamicRepo.battleField if ctrl is not None: ctrl.setVehicleVisible(vProxy.id, vProxy.health) return def stopVehicleVisual(self, vehicleID, isPlayerVehicle): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.stopVehicleVisual(vehicleID, isPlayerVehicle) return def handleShortcutChatCommand(self, key): ctrl = self.__sharedRepo.chatCommands if ctrl is None: return else: if self.__arenaVisitor.gui.isInEpicRange(): mapCtrl = self.dynamic.maps if not mapCtrl or mapCtrl.overviewMapScreenVisible: return ctrl.handleShortcutChatCommand(key) return def __pe_onBattleResultsReceived(self, isActiveVehicle, _): if isActiveVehicle and not BattleReplay.g_replayCtrl.isPlaying: arenaUniqueID = self.__arenaVisitor.getArenaUniqueID() LOG_DEBUG('Try to exit from arena', arenaUniqueID) if arenaUniqueID: self.__ctx.lastArenaUniqueID = arenaUniqueID BattleSessionProvider.exit()
class BattleSessionProvider(IBattleSessionProvider): """This class is backend of GUI for one battle session.""" __slots__ = ('__ctx', '__sharedRepo', '__dynamicRepo', '__requestsCtrl', '__arenaDP', '__arenaListeners', '__viewComponentsBridge', '__weakref__', '__arenaVisitor', '__invitations', '__isReplayPlaying', '__battleCache') def __init__(self): super(BattleSessionProvider, self).__init__() self.__ctx = BattleContext() self.__sharedRepo = controllers.SharedControllersLocator() self.__dynamicRepo = controllers.DynamicControllersLocator() self.__requestsCtrl = None self.__arenaDP = None self.__arenaVisitor = arena_visitor.createSkeleton() self.__arenaListeners = None self.__viewComponentsBridge = None self.__invitations = None self.__isReplayPlaying = False self.__battleCache = BattleClientCache() return @property def shared(self): """ Returns reference to repository of shared controllers that are created for all game sessions. :return: instance of SharedControllersLocator. """ return self.__sharedRepo @property def dynamic(self): """ Returns reference to repository of controllers that are created for some game sessions. :return: instance of DynamicControllersLocator. """ return self.__dynamicRepo @property def arenaVisitor(self): """ Returns reference to visitor that has safe access to properties of arena. :return: instance of _ClientArenaVisitor. """ return self.__arenaVisitor @property def invitations(self): """ Returns reference to invitations handler. :return: instance of _SquadInvitationsHandler. """ return self.__invitations @property def battleCache(self): """ Returns reference to the battle cache that is stored on the server. Note that the cache is created once per each battle and can be used to restore data after re-login. :return: instance of derived class BattleClientCache """ return self.__battleCache @property def isReplayPlaying(self): """ Returns flag is this battle actually replay. :return: boolean flag """ return self.__isReplayPlaying def getCtx(self): """ Gets instance of ammo controller. :return: instance of AmmoController. """ return self.__ctx @async def sendRequest(self, ctx, callback, allowDelay = None): """ Sends request to the server. :param ctx: avatar request context object, @see gui.battle_control.request.context. :param callback: function that is invoked when response is received. :param allowDelay: bool. """ self.__requestsCtrl.request(ctx, callback=callback, allowDelay=allowDelay) def setPlayerVehicle(self, vID, vDesc): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.setGunSettings(vDesc.gun) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.setPlayerVehicle(vID) ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.spawnVehicle(vID) mapKind = self.__arenaVisitor.type.getVehicleCamouflageKind() g_tankActiveCamouflage[vDesc.type.compactDescr] = SeasonType.fromArenaKind(mapKind) return def switchVehicle(self, vehicleID): repo = self.shared for ctrl in (repo.ammo, repo.equipments, repo.optionalDevices): if ctrl is not None: ctrl.clear(False) repo.vehicleState.switchToOther(vehicleID) return def updateObservedVehicleData(self, vID, extraData): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl.setGunSettings(extraData.gunSettings) for intCD, quantity, quantityInClip in extraData.orderedAmmo: ctrl.setShells(intCD, quantity, quantityInClip) ctrl.setCurrentShellCD(extraData.currentShellCD) ctrl.setNextShellCD(extraData.nextShellCD) ctrl.setGunReloadTime(extraData.reloadTimeLeft, extraData.reloadBaseTime) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) for intCD, quantity, stage, timeRemaining in extraData.orderedEquipment: ctrl.setEquipment(intCD, quantity, stage, timeRemaining) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) for deviceID, isOn in extraData.orderedOptionalDevices: ctrl.setOptionalDevice(deviceID, isOn) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.refreshVehicleStateValue(VEHICLE_VIEW_STATE.HEALTH) ctrl.notifyStateChanged(VEHICLE_VIEW_STATE.VEHICLE_CHANGED, vID) return def getArenaDP(self): """Gets instance of arena data provider. :return: instance of ArenaDataProvider. """ return self.__arenaDP def addArenaCtrl(self, controller): """Adds arena controller. For additional information see gui.arena_info.IArenaController. :param controller: object that implements IArenaController. :return: True if controller is added to arena listeners, otherwise - False. """ if self.__arenaListeners is not None: return self.__arenaListeners.addController(controller) else: return False def removeArenaCtrl(self, controller): """Removes arena controller. :param controller: object extends IArenaController. """ if self.__arenaListeners is not None: self.__arenaListeners.removeController(controller) return def registerViewComponentsCtrl(self, controller): """Registers controller in the bridge of view components. :param controller: object that implements IViewComponentsController. :return: True if controller is added to arena listeners, otherwise - False. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerController(controller) return True else: return False def registerViewComponents(self, *data): """Sets view component data to find that components in routines addViewComponent, removeViewComponent. :param data: tuple((BATTLE_CTRL.*, (componentID, ...)), ...) """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerViewComponents(*data) return def addViewComponent(self, componentID, component, rule = VIEW_COMPONENT_RULE.PROXY): """View component has been created. :param componentID: string containing unique component ID. :param component: instance of component. :param rule: one of VIEW_COMPONENT_RULE.*. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.addViewComponent(componentID, component, rule=rule) return def removeViewComponent(self, componentID): """View component has been removed. :param componentID: string containing unique component ID. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.removeViewComponent(componentID) return def getExitResult(self): """ Gets result if player exits battle that are helped to notify player about penalty (if they have). :return: instance of BattleExitResult(isDeserter, player). """ if not self.__isReplayPlaying and not self.__arenaVisitor.gui.isTrainingBattle() and not self.__arenaVisitor.gui.isEventBattle(): vInfo = self.__arenaDP.getVehicleInfo() vStats = self.__arenaDP.getVehicleStats() if self.__arenaVisitor.hasRespawns(): isDeserter = not vStats.stopRespawn else: isDeserter = avatar_getter.isVehicleAlive() and not avatar_getter.isVehicleOverturned() return BattleExitResult(isDeserter, vInfo.player) else: return BattleExitResult(False, None) return None @staticmethod def exit(): """Exits from current battle session.""" avatar_getter.leaveArena() def start(self, setup): """ Battle session is started. :param setup: instance of BattleSessionSetup. :return: """ raise isinstance(setup, controllers.BattleSessionSetup) or AssertionError self.__isReplayPlaying = setup.isReplayPlaying self.__arenaVisitor = arena_visitor.createByAvatar(avatar=setup.avatar) setup.sessionProvider = weakref.proxy(self) self.__arenaDP = ArenaDataProvider(setup) self.__ctx.start(self.__arenaDP) self.__battleCache.load() self.__arenaListeners = ListenersCollection() self.__arenaListeners.start(setup) self.__viewComponentsBridge = createComponentsBridge() setup.sessionProvider = weakref.proxy(self) self.__sharedRepo = controllers.createShared(setup) self.__dynamicRepo = controllers.createDynamic(setup) self.__requestsCtrl = AvatarRequestsController() self.__invitations = invitations.createInvitationsHandler(setup) setup.clear() g_playerEvents.onBattleResultsReceived += self.__pe_onBattleResultsReceived def stop(self): g_playerEvents.onBattleResultsReceived -= self.__pe_onBattleResultsReceived if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.clear() self.__viewComponentsBridge = None if self.__invitations is not None: self.__invitations.clear() self.__invitations = None if self.__requestsCtrl is not None: self.__requestsCtrl.fini() self.__requestsCtrl = None if self.__arenaListeners is not None: self.__arenaListeners.stop() self.__arenaListeners = None if self.__arenaDP is not None: self.__arenaDP.clear() self.__arenaDP = None self.__sharedRepo.destroy() self.__dynamicRepo.destroy() self.__arenaVisitor.clear() self.__arenaVisitor = arena_visitor.createSkeleton() self.__battleCache.clear() self.__ctx.stop() return def switchToPostmortem(self, noRespawnPossible = True, respawnAvailable = False): """Player's vehicle is destroyed, switchers GUI to postmortem mode. :param noRespawnPossible: whether the player can respawn or not during the game. :param respawnAvailable: if the player can respawn directly after being dead (move to respawn ctrl mode) """ ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(noRespawnPossible) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.switchToPostmortem(noRespawnPossible, respawnAvailable) return def useLoaderIntuition(self): """Loader intuition was used.""" ctrl = self.__sharedRepo.messages if ctrl is not None: ctrl.showVehicleMessage('LOADER_INTUITION_WAS_USED') ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.useLoaderIntuition() return def movingToRespawnBase(self): """Player's avatar is moving to the respawn.""" ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.movingToRespawn() ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.movingToRespawn() return def invalidateVehicleState(self, state, value, vehicleID = 0): """State of player's vehicle (health, fire, state of device, etc.) is changed, notifies GUI about it. :param state: one of VEHICLE_VIEW_STATE.*. :param value: value of state. :param vehicleID: vehicle ID or zero. """ ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.invalidate(state, value, vehicleID) if state == VEHICLE_VIEW_STATE.DESTROYED: ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(leave=False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(leave=False) return def setVehicleHealth(self, isPlayerVehicle, vehicleID, newHealth, attackerID, attackReasonID): """New vehicle health value is changed, notifies GUI about it. :param isPlayerVehicle: (bool) determine is player vehicle :param vehicleID: (int) vehicle id :param newHealth: (int) vehicle health :param attackerID: (int) vehicle which dealt damage :param attackReasonID: (str) ATTACK_REASON.* """ if not isPlayerVehicle: ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.setVehicleNewHealth(vehicleID, newHealth, attackerID, attackReasonID) ctrl = self.__dynamicRepo.battleField if ctrl is not None: ctrl.setVehicleHealth(vehicleID, newHealth) return def repairPointAction(self, repairPointIndex, action, nextActionTime): ctrl = self.__dynamicRepo.repair if ctrl is not None: ctrl.action(repairPointIndex, action, nextActionTime) return def updateAvatarPrivateStats(self, stats): ctrl = self.__sharedRepo.privateStats if ctrl is not None: ctrl.update(stats) return def addHitDirection(self, hitDirYaw, attackerID, damage, isBlocked, critFlags, isHighExplosive, damagedID): hitDirectionCtrl = self.__sharedRepo.hitDirection if hitDirectionCtrl is not None: atackerVehInfo = self.__arenaDP.getVehicleInfo(attackerID) atackerVehType = atackerVehInfo.vehicleType isAlly = self.__arenaDP.isAllyTeam(atackerVehInfo.team) playerVehType = self.__arenaDP.getVehicleInfo(damagedID).vehicleType hitDirectionCtrl.addHit(HitData(yaw=hitDirYaw, attackerID=attackerID, isAlly=isAlly, damage=damage, attackerVehName=atackerVehType.shortNameWithPrefix, isBlocked=isBlocked, attackerVehClassTag=atackerVehType.classTag, critFlags=critFlags, playerVehMaxHP=playerVehType.maxHealth, isHighExplosive=isHighExplosive)) return def startVehicleVisual(self, vProxy, isImmediate = False): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.startVehicleVisual(vProxy, isImmediate) ctrl = self.__dynamicRepo.battleField if ctrl is not None: ctrl.setVehicleVisible(vProxy.id, vProxy.health) return def stopVehicleVisual(self, vehicleID, isPlayerVehicle): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.stopVehicleVisual(vehicleID, isPlayerVehicle) return def handleShortcutChatCommand(self, key): ctrl = self.__sharedRepo.chatCommands if ctrl is not None: ctrl.handleShortcutChatCommand(key) return def __pe_onBattleResultsReceived(self, isActiveVehicle, _): """It's listener of event _PlayerEvents.onBattleResultsReceived. :param isActiveVehicle: bool. """ if isActiveVehicle and not BattleReplay.g_replayCtrl.isPlaying: arenaUniqueID = self.__arenaVisitor.getArenaUniqueID() LOG_DEBUG('Try to exit from arena', arenaUniqueID) if arenaUniqueID: self.__ctx.lastArenaUniqueID = arenaUniqueID BattleSessionProvider.exit()
class BattleSessionProvider(object): """This class is backend of GUI for one battle session.""" __slots__ = ('__ctx', '__sharedRepo', '__dynamicRepo', '__requestsCtrl', '__arenaDP', '__arenaListeners', '__viewComponentsBridge', '__weakref__', '__arenaVisitor', '__invitations', '__isReplayPlaying', '__battleCache') def __init__(self): super(BattleSessionProvider, self).__init__() self.__ctx = BattleContext() self.__sharedRepo = controllers.SharedControllersLocator() self.__dynamicRepo = controllers.DynamicControllersLocator() self.__requestsCtrl = None self.__arenaDP = None self.__arenaVisitor = arena_visitor.createSkeleton() self.__arenaListeners = None self.__viewComponentsBridge = None self.__invitations = None self.__isReplayPlaying = False self.__battleCache = BattleClientCache() return @property def shared(self): """ Returns reference to repository of shared controllers that are created for all game sessions. :return: instance of SharedControllersLocator. """ return self.__sharedRepo @property def dynamic(self): """ Returns reference to repository of controllers that are created for some game sessions. :return: instance of DynamicControllersLocator. """ return self.__dynamicRepo @property def arenaVisitor(self): """ Returns reference to visitor that has safe access to properties of arena. :return: instance of _ClientArenaVisitor. """ return self.__arenaVisitor @property def invitations(self): """ Returns reference to invitations handler. :return: instance of _SquadInvitationsHandler. """ return self.__invitations @property def battleCache(self): """ Returns reference to the battle cache that is stored on the server. Note that the cache is created once per each battle and can be used to restore data after re-login. :return: instance of derived class BattleClientCache """ return self.__battleCache def getCtx(self): """ Gets instance of ammo controller. :return: instance of AmmoController. """ return self.__ctx @async def sendRequest(self, ctx, callback, allowDelay = None): """ Sends request to the server. :param ctx: avatar request context object, @see gui.battle_control.request.context. :param callback: function that is invoked when response is received. :param allowDelay: bool. """ self.__requestsCtrl.request(ctx, callback=callback, allowDelay=allowDelay) def setPlayerVehicle(self, vID, vDesc): ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.setGunSettings(vDesc.gun) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.setPlayerVehicle(vID) ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.setPlayerVehicle(vID) ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.spawnVehicle(vID) g_tankActiveCamouflage[vDesc.type.compactDescr] = self.__arenaVisitor.type.getVehicleCamouflageKind() return def getArenaDP(self): """Gets instance of arena data provider. :return: instance of ArenaDataProvider. """ return self.__arenaDP def addArenaCtrl(self, controller): """Adds arena controller. For additional information see gui.arena_info.IArenaController. :param controller: object that implements IArenaController. :return: True if controller is added to arena listeners, otherwise - False. """ if self.__arenaListeners is not None: return self.__arenaListeners.addController(controller) else: return False return def removeArenaCtrl(self, controller): """Removes arena controller. :param controller: object extends IArenaController. """ if self.__arenaListeners is not None: self.__arenaListeners.removeController(controller) return def registerViewComponentsCtrl(self, controller): """Registers controller in the bridge of view components. :param controller: object that implements IViewComponentsController. :return: True if controller is added to arena listeners, otherwise - False. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerController(controller) return True else: return False return def registerViewComponents(self, *data): """Sets view component data to find that components in routines addViewComponent, removeViewComponent. :param data: tuple((BATTLE_CTRL.*, (componentID, ...)), ...) """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.registerViewComponents(*data) return def addViewComponent(self, componentID, component, rule = VIEW_COMPONENT_RULE.PROXY): """View component has been created. :param componentID: string containing unique component ID. :param component: instance of component. :param rule: one of VIEW_COMPONENT_RULE.*. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.addViewComponent(componentID, component, rule=rule) return def removeViewComponent(self, componentID): """View component has been removed. :param componentID: string containing unique component ID. """ if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.removeViewComponent(componentID) return def getExitResult(self): """ Gets result if player exits battle that are helped to notify player about penalty (if they have). :return: instance of BattleExitResult(isDeserter, player). """ if not self.__isReplayPlaying and not self.__arenaVisitor.gui.isTrainingBattle(): vInfo = self.__arenaDP.getVehicleInfo() vStats = self.__arenaDP.getVehicleStats() if self.__arenaVisitor.gui.isEventBattle(): isDeserter = False elif self.__arenaVisitor.hasRespawns(): isDeserter = not vStats.stopRespawn else: isDeserter = avatar_getter.isVehicleAlive() and not avatar_getter.isVehicleOverturned() return BattleExitResult(isDeserter, vInfo.player) else: return BattleExitResult(False, None) return None @staticmethod def exit(): """Exits from current battle session.""" avatar_getter.leaveArena() def start(self, setup): """ Battle session is started. :param setup: instance of BattleSessionSetup. :return: """ raise isinstance(setup, controllers.BattleSessionSetup) or AssertionError self.__isReplayPlaying = setup.isReplayPlaying self.__arenaVisitor = arena_visitor.createByAvatar(avatar=setup.avatar) setup.sessionProvider = weakref.proxy(self) self.__arenaDP = ArenaDataProvider(setup) self.__ctx.start(self.__arenaDP) self.__battleCache.load() self.__arenaListeners = ListenersCollection() self.__arenaListeners.start(setup) self.__viewComponentsBridge = createComponentsBridge() setup.sessionProvider = weakref.proxy(self) self.__sharedRepo = controllers.createShared(setup) self.__dynamicRepo = controllers.createDynamic(setup) self.__requestsCtrl = AvatarRequestsController() self.__invitations = invitations.createInvitationsHandler(setup) setup.clear() g_playerEvents.onBattleResultsReceived += self.__pe_onBattleResultsReceived def stop(self): g_playerEvents.onBattleResultsReceived -= self.__pe_onBattleResultsReceived if self.__viewComponentsBridge is not None: self.__viewComponentsBridge.clear() self.__viewComponentsBridge = None if self.__invitations is not None: self.__invitations.clear() self.__invitations = None if self.__requestsCtrl is not None: self.__requestsCtrl.fini() self.__requestsCtrl = None if self.__arenaListeners is not None: self.__arenaListeners.stop() self.__arenaListeners = None if self.__arenaDP is not None: self.__arenaDP.clear() self.__arenaDP = None self.__sharedRepo.destroy() self.__dynamicRepo.destroy() self.__arenaVisitor.clear() self.__arenaVisitor = arena_visitor.createSkeleton() self.__battleCache.clear() self.__ctx.stop() return def switchToPostmortem(self): """Player's vehicle is destroyed, switchers GUI to postmortem mode.""" ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear() ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear() ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear() ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.setPlayerVehicle(0L) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.switchToPostmortem() return def useLoaderIntuition(self): """Loader intuition was used.""" ctrl = self.__sharedRepo.messages if ctrl is not None: ctrl.showVehicleMessage('LOADER_INTUITION_WAS_USED') ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.useLoaderIntuition() return def movingToRespawnBase(self): """Player's avatar is moving to the respawn.""" ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.optionalDevices if ctrl is not None: ctrl.clear(False) ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.movingToRespawn() ctrl = self.__dynamicRepo.respawn if ctrl is not None: ctrl.movingToRespawn() return def invalidateVehicleState(self, state, value, vehicleID = 0): """State of player's vehicle (health, fire, state of device, etc.) is changed, notifies GUI about it. :param state: one of VEHICLE_VIEW_STATE.*. :param value: value of state. :param vehicleID: vehicle ID or zero. """ ctrl = self.__sharedRepo.vehicleState if ctrl is not None: ctrl.invalidate(state, value, vehicleID) if state == VEHICLE_VIEW_STATE.DESTROYED: ctrl = self.__sharedRepo.ammo if ctrl is not None: ctrl.clear(leave=False) ctrl = self.__sharedRepo.equipments if ctrl is not None: ctrl.clear(leave=False) return def repairPointAction(self, repairPointIndex, action, nextActionTime): ctrl = self.__dynamicRepo.repair if ctrl is not None: ctrl.action(repairPointIndex, action, nextActionTime) return def updateAvatarPrivateStats(self, stats): ctrl = self.__sharedRepo.privateStats if ctrl is not None: ctrl.update(stats) return def addHitDirection(self, hitDirYaw, attackerID, damage, isBlocked, critFlags, isHighExplosive): hitDirectionCtrl = self.__sharedRepo.hitDirection if hitDirectionCtrl is not None: atackerVehInfo = self.__arenaDP.getVehicleInfo(attackerID) atackerVehType = atackerVehInfo.vehicleType isAlly = self.__arenaDP.isAllyTeam(atackerVehInfo.team) playerVehType = self.__arenaDP.getVehicleInfo().vehicleType hitDirectionCtrl.addHit(HitData(yaw=hitDirYaw, attackerID=attackerID, isAlly=isAlly, damage=damage, attackerVehName=atackerVehType.shortNameWithPrefix, isBlocked=isBlocked, attackerVehClassTag=atackerVehType.classTag, critFlags=critFlags, playerVehMaxHP=playerVehType.maxHealth, isHighExplosive=isHighExplosive)) return def startVehicleVisual(self, vProxy, isImmediate = False): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.startVehicleVisual(vProxy, isImmediate) return def stopVehicleVisual(self, vehicleID, isPlayerVehicle): ctrl = self.__sharedRepo.feedback if ctrl is not None: ctrl.stopVehicleVisual(vehicleID, isPlayerVehicle) return def handleShortcutChatCommand(self, key): ctrl = self.__sharedRepo.chatCommands if ctrl is not None: ctrl.handleShortcutChatCommand(key) return def __pe_onBattleResultsReceived(self, isActiveVehicle, _): """It's listener of event _PlayerEvents.onBattleResultsReceived. :param isActiveVehicle: bool. """ if isActiveVehicle: arenaUniqueID = self.__arenaVisitor.getArenaUniqueID() LOG_DEBUG('Try to exit from arena', arenaUniqueID) if arenaUniqueID: self.__ctx.lastArenaUniqueID = arenaUniqueID avatar_getter.leaveArena()