class TutorialLoader(object): lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(TutorialLoader, self).__init__() self.__loggedDBIDs = set() self.__afterBattle = False self.__tutorial = None self.__dispatcher = None self.__restoreID = None self.__settings = _settings.createSettingsCollection() self.__hintsManager = None self.__listener = None return def init(self): """ Initialization of tutorial loader. """ self.__listener = AppLoaderListener() self.__listener.start(weakref.proxy(self)) def fini(self): """ Tutorial loader finalizes work: stops training process, saving state, # if tutorial is running. """ if self.__listener is not None: self.__listener.stop() if self.__hintsManager is not None: self.__hintsManager.stop() if self.__dispatcher is not None: self.__dispatcher.stop() if self.__tutorial is not None: self.__tutorial.onStopped -= self.__onTutorialStopped self.__tutorial.stop() self.__loggedDBIDs.clear() self.__settings.clear() return @property def tutorial(self): return self.__tutorial @property def tutorialID(self): result = '' if self.__tutorial is not None: result = self.__tutorial.getID() return result @property def isRunning(self): result = False if self.__tutorial is not None: result = not self.__tutorial.isStopped() return result def isTutorialStopped(self): result = True if self.__tutorial is not None: result = self.__tutorial.isStopped() return result def run(self, settingsID, state=None): """ Try to run tutorial. :param settingsID: string containing settings ID of required tutorial. :param state: dict( reloadIfRun : bool - just reload tutorial if it's running, afterBattle : bool - tutorial should load scenario that is played when player left battle, initialChapter : str - name of initial chapter, restoreIfRun: bool - current tutorial will be started again if required tutorial stop. globalFlags : dict(GLOBAL_FLAG.* : bool,) ) :return: True if tutorial has started, otherwise - False. """ settings = self.__settings.getSettings(settingsID) if settings is None: LOG_ERROR('Can not find settings', settingsID) return False else: if state is None: state = {} reloadIfRun = state.pop('reloadIfRun', False) restoreIfRun = state.pop('restoreIfRun', False) isStopForced = state.pop('isStopForced', False) if self.__tutorial is not None and not self.__tutorial.isStopped(): isCurrent = self.__tutorial.getID() == settings.id if reloadIfRun and isCurrent: if isStopForced: self.__doStop() else: GlobalStorage.setFlags(state.get('globalFlags', {})) self.__tutorial.invalidateFlags() return True elif restoreIfRun and not isCurrent: self.__restoreID = self.__tutorial.getID() self.__doStop() else: LOG_ERROR('Tutorial already is running', self.__tutorial.getID()) return False state.setdefault('isAfterBattle', self.__afterBattle) state.setdefault('restart', True) state['byRequest'] = True result = self.__doRun(settings, state) if not result: self.__restoreID = None return result def stop(self, restore=True): self.__doStop() self.__doStopHints() if restore: self.__doRestore() else: self.__restoreID = None return def refuse(self): if self.__tutorial is not None: self.__tutorial.refuse() return def goToLobby(self): databaseID = account_helpers.getAccountDatabaseID() raise databaseID or AssertionError( 'Acoount database ID is not defined') isFirstStart = databaseID not in self.__loggedDBIDs self.__loggedDBIDs.add(databaseID) state = { 'isFirstStart': isFirstStart, 'isAfterBattle': self.__afterBattle } self.__setDispatcher(_LOBBY_DISPATCHER) self.__restoreID = _SETTINGS.QUESTS.id self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), state) self.__hintsManager = HintsManager() self.__hintsManager.start() def stopOnceOnlyHint(self, itemID): if self.__hintsManager is not None: self.__hintsManager.stopOnceOnlyHint(itemID) return def leaveLobby(self): self.stop(restore=False) def goToBattleLoading(self): self.__afterBattle = True self.__doClear() self.__doAutoRun((_SETTINGS.BATTLE_V2, _SETTINGS.BATTLE_QUESTS), {'canResolveChapterOnStart': False}) def goToBattle(self): if self.__tutorial is not None: self.__tutorial.startBattle() return def leaveBattle(self): self.stop(restore=False) def goToLogin(self): self.__afterBattle = False self.__doClear() def __doAutoRun(self, seq, state): for settings in seq: if self.__doRun(settings, state): return def __doRun(self, settings, state): if not settings.enabled: return False else: reqs = _settings.createTutorialElement(settings.reqs) if not reqs.isEnabled(): return False descriptor = loadDescriptorData(settings, settings.exParsers) if descriptor is None: LOG_ERROR('Descriptor is not valid. Tutorial is not available', settings) return False cache = _cache.TutorialCache(BigWorld.player().name) cache.read() cache.setSpace(settings.space) if state.get('byRequest', False): cache.setRefused(False) runCtx = RunCtx(cache, **state) reqs.prepare(runCtx) if not reqs.process(descriptor, runCtx): return False self.__doStop() if self.__dispatcher is None: self.__setDispatcher(settings.dispatcher) tutorial = core.Tutorial(settings, descriptor) result = tutorial.run(weakref.proxy(self.__dispatcher), runCtx) if result: self.__tutorial = tutorial self.__tutorial.onStopped += self.__onTutorialStopped return result def __doStop(self): if self.__tutorial is not None: self.__tutorial.onStopped -= self.__onTutorialStopped self.__tutorial.stop() self.__tutorial = None return def __doStopHints(self): if self.__hintsManager is not None: self.__hintsManager.stop() return def __doClear(self): self.__restoreID = None self.__doStop() self.__doStopHints() if self.__dispatcher is not None: self.__dispatcher.stop() self.__dispatcher = None return def __doRestore(self): if self.__restoreID is not None: settingsID, self.__restoreID = self.__restoreID, None LOG_DEBUG('Restore tutorial', settingsID) self.run(settingsID) return def __setDispatcher(self, settings): if self.__dispatcher is not None: self.__dispatcher.stop() self.__dispatcher = None self.__dispatcher = _settings.createTutorialElement(settings) self.__dispatcher.start(weakref.proxy(self)) return def __onTutorialStopped(self): """ Listener for event Tutorial.onStopped. """ self.__doRestore()
class TutorialLoader(object): lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(TutorialLoader, self).__init__() self.__loggedDBIDs = set() self.__afterBattle = False self.__tutorial = None self.__dispatcher = None self.__restoreID = None self.__settings = _settings.createSettingsCollection() self.__hintsManager = None self.__listener = None return def init(self): self.__listener = AppLoaderListener() self.__listener.start(weakref.proxy(self)) def fini(self): if self.__listener is not None: self.__listener.stop() if self.__hintsManager is not None: self.__hintsManager.stop() if self.__dispatcher is not None: self.__dispatcher.stop() if self.__tutorial is not None: self.__tutorial.onStopped -= self.__onTutorialStopped self.__tutorial.stop() self.__loggedDBIDs.clear() self.__settings.clear() return @property def tutorial(self): return self.__tutorial @property def tutorialID(self): result = '' if self.__tutorial is not None: result = self.__tutorial.getID() return result @property def isRunning(self): result = False if self.__tutorial is not None: result = not self.__tutorial.isStopped() return result def isTutorialStopped(self): result = True if self.__tutorial is not None: result = self.__tutorial.isStopped() return result def run(self, settingsID, state=None): settings = self.__settings.getSettings(settingsID) if settings is None: LOG_ERROR('Can not find settings', settingsID) return False else: if state is None: state = {} reloadIfRun = state.pop('reloadIfRun', False) restoreIfRun = state.pop('restoreIfRun', False) isStopForced = state.pop('isStopForced', False) if self.__tutorial is not None and not self.__tutorial.isStopped(): isCurrent = self.__tutorial.getID() == settings.id if reloadIfRun and isCurrent: if isStopForced: self.__doStop() else: GlobalStorage.setFlags(state.get('globalFlags', {})) LOG_DEBUG('invalidateFlags from TutorialLoader.run') self.__tutorial.invalidateFlags() return True elif restoreIfRun and not isCurrent: self.__restoreID = self.__tutorial.getID() self.__doStop() else: LOG_ERROR('Tutorial already is running', self.__tutorial.getID()) return False state.setdefault('isAfterBattle', self.__afterBattle) state.setdefault('restart', True) state['byRequest'] = True result = self.__doRun(settings, state) if not result: self.__restoreID = None return result def stop(self, restore=True): self.__doStop() self.__doStopHints() if restore: self.__doRestore() else: self.__restoreID = None return def refuse(self): if self.__tutorial is not None: self.__tutorial.refuse() return def goToLobby(self): databaseID = account_helpers.getAccountDatabaseID() if not databaseID: raise SoftException('Acoount database ID is not defined') isFirstStart = databaseID not in self.__loggedDBIDs self.__loggedDBIDs.add(databaseID) state = { 'isFirstStart': isFirstStart, 'isAfterBattle': self.__afterBattle } self.__setDispatcher(_LOBBY_DISPATCHER) self.__restoreID = _SETTINGS.QUESTS.id bootcampController = dependency.instance(IBootcampController) isInBootcampAccount = bootcampController.isInBootcampAccount() if isInBootcampAccount: selectedSettings = self.__doAutoRun( (_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS, _SETTINGS.BOOTCAMP_LOBBY), state) else: selectedSettings = None if selectedSettings is None or selectedSettings.hintsEnabled: self.__hintsManager = HintsManager() self.__hintsManager.start() return def stopOnceOnlyHint(self, itemID): if self.__hintsManager is not None: self.__hintsManager.stopOnceOnlyHint(itemID) return def leaveLobby(self): self.stop(restore=False) def goToBattleLoading(self): self.__afterBattle = True self.__doClear() self.__doAutoRun((_SETTINGS.BATTLE_V2, _SETTINGS.BATTLE_QUESTS), {'canResolveChapterOnStart': False}) def goToBattle(self): if self.__tutorial is not None: self.__tutorial.startBattle() return def leaveBattle(self): self.stop(restore=False) def goToLogin(self): self.__afterBattle = False self.__doClear() def __doAutoRun(self, seq, state): for settings in seq: if self.__doRun(settings, state): return settings return None def __doRun(self, settings, state): if not settings.enabled: return False else: reqs = _settings.createTutorialElement(settings.reqs) if not reqs.isEnabled(): return False descriptor = loadDescriptorData(settings, settings.exParsers) if descriptor is None: LOG_ERROR('Descriptor is not valid. Tutorial is not available', settings) return False cache = _cache.TutorialCache(BigWorld.player().name) cache.read() cache.setSpace(settings.space, ioEnabled=settings.cacheEnabled) if state.get('byRequest', False): cache.setRefused(False) runCtx = RunCtx(cache, **state) reqs.prepare(runCtx) if not reqs.process(descriptor, runCtx): return False self.__doStop() if self.__dispatcher is None: self.__setDispatcher(settings.dispatcher) self.__tutorial = core.Tutorial(settings, descriptor) self.__tutorial.onStopped += self.__onTutorialStopped result = self.__tutorial.run(weakref.proxy(self.__dispatcher), runCtx) if not result: self.__tutorial.onStopped -= self.__onTutorialStopped self.__tutorial = None return result def __doStop(self): if self.__tutorial is not None: self.__tutorial.onStopped -= self.__onTutorialStopped self.__tutorial.stop() self.__tutorial = None return def __doStopHints(self): if self.__hintsManager is not None: self.__hintsManager.stop() self.__hintsManager = None return def __doClear(self): self.__restoreID = None self.__doStop() self.__doStopHints() if self.__dispatcher is not None: self.__dispatcher.stop() self.__dispatcher = None return def __doRestore(self): if self.__restoreID is not None: settingsID, self.__restoreID = self.__restoreID, None LOG_DEBUG('Restore tutorial', settingsID) self.run(settingsID) return def __setDispatcher(self, settings): if self.__dispatcher is not None: self.__dispatcher.stop() self.__dispatcher = None self.__dispatcher = _settings.createTutorialElement(settings) self.__dispatcher.start(weakref.proxy(self)) return def __onTutorialStopped(self): self.__doRestore()