Ejemplo n.º 1
0
 def init_emulator_and_game(self):
     """Initializes emulator and game objects."""
     if not self.emulator_name:
         self.setup_gui_first_time()
     if self.emulator_type == NoxPlayer.__name__:
         self.emulator = NoxPlayer(self.emulator_name)
         if self.emulator.get_version(
         ) and self.emulator.get_version() < LooseVersion('7.0.0.0'):
             menu = self.menuBar.addMenu("Emulator")
             action = menu.addAction(
                 f"Make {self.emulator.name} restartable")
             action.triggered.connect(self.emulator.set_config_for_bot)
     if self.emulator_type == BlueStacks.__name__:
         self.emulator = BlueStacks(self.emulator_name)
     if not self.emulator.restartable:
         self.restart_game_button.setEnabled(False)
         self.restart_game_button.setText(
             f"{self.restart_game_button.text()}\n"
             "[Unavailable (check logs)]")
         self.restart_game_button = None
     self.game = Game(self.emulator)
     self.manager = SyncManager()
     self.manager.start()
     self.game._modes = self.manager.dict()
     if self.game_app_rect:
         self.game._game_app_ui.button_rect = Rect(*self.game_app_rect)
Ejemplo n.º 2
0
def Manager():
    '''
    Returns a manager associated with a running server process

    The managers methods such as `Lock()`, `Condition()` and `Queue()`
    can be used to create shared objects.
    '''
    from multiprocess.managers import SyncManager
    m = SyncManager()
    m.start()
    return m
Ejemplo n.º 3
0
def Manager():
    '''
    Returns a manager associated with a running server process

    The managers methods such as `Lock()`, `Condition()` and `Queue()`
    can be used to create shared objects.
    '''
    from multiprocess.managers import SyncManager
    m = SyncManager()
    m.start()
    return m
Ejemplo n.º 4
0
    def __init__(self, emulator):
        """Class initialization.

        :param lib.emulators.android_emulator.AndroidEmulator emulator: instance of Android emulator.
        """
        self.emulator = emulator
        self.emulator.manager = SyncManager()
        self.emulator.manager.start()
        self.emulator.screen_elements = self.emulator.manager.list()
        self.font = ImageFont.load_default()
        self._decorate()
Ejemplo n.º 5
0
class MainWindow(QMainWindow, design.Ui_MainWindow):
    """Class for working with main GUI window."""

    recorder = None

    @classmethod
    def pause_recorder(cls):
        if isinstance(cls.recorder, EmulatorCapture):
            cls.recorder.pause()

    @classmethod
    def resume_recorder(cls):
        if isinstance(cls.recorder, EmulatorCapture):
            cls.recorder.resume()

    def __init__(self, file_logger, settings):
        """Class initialization.

        :param logging.FileHandler file_logger: file handler of log-file.
        :param PyQt5.QtCore.QSettings.QSettings settings: GUI settings.
        """
        super().__init__()
        self.setupUi(self)
        set_default_icon(window=self)
        self.settings = settings
        self._init_window_settings()
        self.emulator_name, self.emulator_type, self.game_app_rect, self.emulator, self.game = None, None, None, None, None
        self.load_settings_from_file()
        self.game.file_logger_name = None
        if file_logger:
            self.game.file_logger_name = file_logger.baseFilename
            self.logger = QTextEditFileLogger(
                all_logger_widget=self.logger_text,
                info_logger_widget=self.logger_text_info,
                error_logger_widget=self.logger_text_error,
                log_file=file_logger.baseFilename)
        else:
            self.logger_text.setPlainText(
                "Cannot create log file because `logs` folder doesn't exists.")
        run_and_stop_button = self.create_blockable_button(
            button=self.run_queue_button)
        self.queue_list = QueueList(list_widget=self.queue_list_widget,
                                    run_and_stop_button=run_and_stop_button,
                                    add_button=self.add_queue_button,
                                    edit_button=self.edit_queue_button,
                                    remove_button=self.remove_queue_button,
                                    game=self.game,
                                    queue_selector_buttons=[
                                        self.queue_button_1,
                                        self.queue_button_2,
                                        self.queue_button_3,
                                        self.queue_button_4
                                    ])
        self.screen_image = ScreenImageLabel(emulator=self.emulator,
                                             widget=self.screen_label)
        self.acquire_heroic_quest_rewards_checkbox.stateChanged.connect(
            self.acquire_heroic_quest_rewards_state_changed)
        self.mission_team_spin_box.valueChanged.connect(
            self.mission_team_changed)
        self.timeline_team_spin_box.valueChanged.connect(
            self.timeline_team_changed)
        self.threads = ThreadPool()
        self._user_name_acquired = False
        self.background_functions_to_run()
        self.background_timer = Timer()
        self.background_timer.set_timer(self.background_functions_to_run,
                                        timer_ms=5000)
        self.blockable_buttons = [
            self.run_queue_button, self.add_queue_button,
            self.edit_queue_button, self.remove_queue_button
        ]
        self.tasks = []
        self.create_tasks()

        if self.emulator.initialized and self.emulator.restartable:
            if not self.game.is_main_menu() and not BattleBot(
                    self.game, None).is_battle():
                if not self.game.go_to_main_menu():
                    logger.warning(
                        "Can't get to the main menu. Restarting the game just in case."
                    )
                    self.restart_game_button.click()
        self._create_menu_for_recorder()

    def _init_window_settings(self):
        """Restores the State of a GUI from settings."""
        self.resize(
            self.settings.value("MainWindow/size", defaultValue=self.size()))
        self.move(
            self.settings.value("MainWindow/pos", defaultValue=self.pos()))
        if self.settings.value("MainWindow/isMaximized") == 'true':
            self.showMaximized()

    def background_functions_to_run(self):
        """Runs functions in thread to prevent GUI freezing."""
        self.threads.run_thread(func=self._update_labels)
        self.threads.run_thread(func=self._handle_errors)

    def _update_labels(self):
        """Updates game's labels such as: username, energy, gold and boost points."""
        if not self.emulator.initialized:
            return
        if not self._user_name_acquired and self.game.is_main_menu():
            self.label_username.setText(self.game.user_name)
            self._user_name_acquired = True
        self.label_energy.setText(
            f"Energy: {self.game.energy} / {self.game.energy_max}")
        self.label_gold.setText(f"Gold: {self.game.gold}")
        self.label_boosts.setText(f"Boosts: {self.game.boost} / {100}")

    def _handle_errors(self):
        """Handles network errors by restarting the queue."""
        if not (self.emulator.initialized
                and self.handle_network_errors_checkbox.isChecked()):
            return
        if self.game.close_network_error_notification(
        ) and self.queue_list.process:
            logger.info("Rerunning the queue due network error.")
            self.queue_list.run_and_stop_button.button.click()
            sleep(1)
            self.queue_list.run_and_stop_button.button.click()

    def mission_team_changed(self):
        """'Mission team' spinbox event when value is changed."""
        team = self.mission_team_spin_box.value()
        self.game.set_mission_team(team)
        logger.info(f"Team number for missions : {self.game.mission_team}")
        self.save_settings_to_file()

    def timeline_team_changed(self):
        """'Timeline team' spinbox event when value is changed."""
        team = self.timeline_team_spin_box.value()
        self.game.set_timeline_team(team)
        logger.info(
            f"Team number for TimeLine battles : {self.game.timeline_team}")
        self.save_settings_to_file()

    def acquire_heroic_quest_rewards_state_changed(self):
        """'Acquire heroic quest rewards' checkbox even when value is changed."""
        if self.acquire_heroic_quest_rewards_checkbox.isChecked():
            self.game.ACQUIRE_HEROIC_QUEST_REWARDS = True
        else:
            self.game.ACQUIRE_HEROIC_QUEST_REWARDS = False
        logger.info(
            f"Acquire Heroic Quest rewards: {self.game.ACQUIRE_HEROIC_QUEST_REWARDS}"
        )
        self.save_settings_to_file()

    def load_settings_from_file(self):
        """Loads settings and applies them to game."""
        game_settings = load_game_settings()
        if not game_settings:
            self.setup_gui_first_time()
            return self.load_settings_from_file()
        self.game_app_rect = game_settings.get("game_app_rect")
        self.emulator_name = game_settings.get("emulator_name")
        self.emulator_type = game_settings.get("emulator_type")
        self.timeline_team_spin_box.setValue(
            game_settings.get("timeline_team"))
        self.mission_team_spin_box.setValue(game_settings.get("mission_team"))
        self.acquire_heroic_quest_rewards_checkbox.setChecked(
            game_settings.get("acquire_heroic_quest_rewards", True))
        self.handle_network_errors_checkbox.setChecked(
            game_settings.get("handle_network_errors", False))
        self.init_emulator_and_game()
        self.game.set_mission_team(self.mission_team_spin_box.value())
        self.game.set_timeline_team(self.timeline_team_spin_box.value())
        self.game.ACQUIRE_HEROIC_QUEST_REWARDS = self.acquire_heroic_quest_rewards_checkbox.isChecked(
        )

    def save_settings_to_file(self):
        """Stores GUI settings to file."""
        game_settings = {
            "timeline_team":
            self.game.timeline_team,
            "mission_team":
            self.game.mission_team,
            "acquire_heroic_quest_rewards":
            self.game.ACQUIRE_HEROIC_QUEST_REWARDS,
            "handle_network_errors":
            self.handle_network_errors_checkbox.isChecked(),
            "emulator_name":
            self.emulator_name,
            "emulator_type":
            self.emulator_type,
            "game_app_rect":
            self.game_app_rect
        }
        save_game_settings(game_settings)
        logger.debug("Game settings saved.")

    def setup_gui_first_time(self):
        """Setups GUI settings for first time.
        Runs `SetupEmulator` and retrieves information about emulator and game app."""
        setup = SetupEmulator()
        setup.run_emulator_setup()
        self.emulator_name, self.emulator_type, self.game_app_rect = setup.get_emulator_and_game_app(
        )
        game_settings = {
            "timeline_team":
            self.timeline_team_spin_box.value(),
            "mission_team":
            self.mission_team_spin_box.value(),
            "acquire_heroic_quest_rewards":
            self.acquire_heroic_quest_rewards_checkbox.isChecked(),
            "handle_network_errors":
            self.handle_network_errors_checkbox.isChecked(),
            "emulator_name":
            self.emulator_name,
            "emulator_type":
            self.emulator_type,
            "game_app_rect":
            self.game_app_rect
        }
        save_game_settings(game_settings)
        logger.debug("Saving setting from first setup.")

    def init_emulator_and_game(self):
        """Initializes emulator and game objects."""
        if not self.emulator_name:
            self.setup_gui_first_time()
        if self.emulator_type == NoxPlayer.__name__:
            self.emulator = NoxPlayer(self.emulator_name)
            if self.emulator.get_version(
            ) and self.emulator.get_version() < LooseVersion('7.0.0.0'):
                menu = self.menuBar.addMenu("Emulator")
                action = menu.addAction(
                    f"Make {self.emulator.name} restartable")
                action.triggered.connect(self.emulator.set_config_for_bot)
        if self.emulator_type == BlueStacks.__name__:
            self.emulator = BlueStacks(self.emulator_name)
        if not self.emulator.restartable:
            self.restart_game_button.setEnabled(False)
            self.restart_game_button.setText(
                f"{self.restart_game_button.text()}\n"
                "[Unavailable (check logs)]")
            self.restart_game_button = None
        self.game = Game(self.emulator)
        self.manager = SyncManager()
        self.manager.start()
        self.game._modes = self.manager.dict()
        if self.game_app_rect:
            self.game._game_app_ui.button_rect = Rect(*self.game_app_rect)

    def _create_menu_for_recorder(self):
        """Creates menu bar for emulator recording."""
        menu = self.menuBar.addMenu("Video Recorder")
        self.recorder_action = menu.addAction("Start recording")
        self.recorder_action.triggered.connect(self._start_recording)

    def _start_recording(self):
        """Starts recording video from emulator."""
        MainWindow.recorder = EmulatorCapture(self.emulator)
        MainWindow.recorder.start()
        MainWindow.recorder.pause()

        self.recorder_action.setText("Stop recording")
        try_to_disconnect(self.recorder_action.triggered,
                          self._start_recording)
        self.recorder_action.triggered.connect(self._stop_recording)

        self.screen_image.get_image_func = lambda: bgr_to_rgb(
            MainWindow.recorder.video_capture.source.frame())

    def _stop_recording(self):
        """Stops recording video from emulator."""
        MainWindow.recorder.stop()
        MainWindow.recorder = None

        self.recorder_action.setText("Start recording")
        try_to_disconnect(self.recorder_action.triggered, self._stop_recording)
        self.recorder_action.triggered.connect(self._start_recording)

        self.screen_image.get_image_func = self.emulator.get_screen_image

    def closeEvent(self, event):
        """Main window close event."""
        self.queue_list.stop_queue()
        for task in self.tasks:
            task.abort()
        self.save_settings_to_file()
        self.queue_list.save_queue_to_file()
        self.settings.setValue("MainWindow/size", self.size())
        self.settings.setValue("MainWindow/isMaximized", self.isMaximized())
        self.settings.setValue("MainWindow/pos", self.pos())

    def create_blockable_button(self, button):
        """Creates button that blocks others."""
        if not button:
            return
        two_state_button = TwoStateButton(button=button)
        two_state_button.connect_first_state(self.block_buttons,
                                             caller_button=button)
        two_state_button.connect_second_state(self.unblock_buttons)
        two_state_button.signals.first_state.connect(self.unblock_buttons)
        return two_state_button

    def block_buttons(self, caller_button):
        """Blocks buttons except caller one.

        :param PyQt5.QtWidgets.QPushButton.QPushButton caller_button: button that called the event.
        """
        buttons_to_block = [
            button for button in self.blockable_buttons
            if button and button.isEnabled() and button != caller_button
        ]
        for button in buttons_to_block:
            button.setEnabled(False)

    def unblock_buttons(self):
        """Unblocks all buttons."""
        for button in self.blockable_buttons:
            if button:
                button.setEnabled(True)

    def _create_task(self, button, task_class):
        """Creates blockable button for task and initialized it.

        :param PyQt5.QtWidgets.QPushButton.QPushButton button: button to run the task.
        :param type[lib.gui.single_task_manager.SingleTask] task_class: class object of the task.
        """
        blockable_button = self.create_blockable_button(button=button)
        task = task_class(game=self.game, button=blockable_button)
        self.blockable_buttons.append(button)
        self.tasks.append(task)

    def create_tasks(self):
        """Creates all available tasks."""
        self._create_task(button=self.autoplay_button, task_class=AutoPlayTask)
        self._create_task(button=self.daily_trivia_button,
                          task_class=DailyTriviaTask)
        self._create_task(button=self.world_boss_invasion_button,
                          task_class=WorldBossInvasionTask)
        self._create_task(button=self.squad_battle_button,
                          task_class=SquadBattleAllTask)
        self._create_task(button=self.danger_room_button,
                          task_class=DangerRoomOneBattleTask)
        self._create_task(button=self.restart_game_button,
                          task_class=RestartGameTask)
        self._create_task(button=self.comic_cards_button,
                          task_class=ComicCardsTask)
        self._create_task(button=self.custom_gear_button,
                          task_class=CustomGearTask)
        self._create_task(button=self.dispatch_mission_rewards,
                          task_class=DispatchMissionAcquireTask)
        self._create_task(button=self.enhance_potential_button,
                          task_class=EnhancePotentialTask)
        self._create_task(button=self.shadowland_button,
                          task_class=ShadowlandAllFloorsTask)