Example #1
0
 def _refresh_account_name_text(self) -> None:
     if self._account_name_text is None:
         return
     try:
         name_str = _ba.get_account_display_string()
     except Exception:
         ba.print_exception()
         name_str = '??'
     ba.textwidget(edit=self._account_name_text, text=name_str)
Example #2
0
def gamepad_configure_callback(event: Dict[str, Any]) -> None:
    """Respond to a gamepad button press during config selection."""
    from ba.internal import get_remote_app_name
    from bastd.ui.settings import gamepad

    # Ignore all but button-presses.
    if event['type'] not in ['BUTTONDOWN', 'HATMOTION']:
        return
    _ba.release_gamepad_input()
    try:
        ba.containerwidget(edit=ba.app.main_menu_window, transition='out_left')
    except Exception:
        ba.print_exception('Error transitioning out main_menu_window.')
    ba.playsound(ba.getsound('activateBeep'))
    ba.playsound(ba.getsound('swish'))
    inputdevice = event['input_device']
    assert isinstance(inputdevice, ba.InputDevice)
    if inputdevice.allows_configuring:
        ba.app.main_menu_window = (
            gamepad.GamepadSettingsWindow(inputdevice).get_root_widget())
    else:
        width = 700
        height = 200
        button_width = 100
        uiscale = ba.app.uiscale
        ba.app.main_menu_window = dlg = (ba.containerwidget(
            scale=(1.7 if uiscale is ba.UIScale.SMALL else
                   1.4 if uiscale is ba.UIScale.MEDIUM else 1.0),
            size=(width, height),
            transition='in_right'))
        device_name = inputdevice.name
        if device_name == 'iDevice':
            msg = ba.Lstr(resource='bsRemoteConfigureInAppText',
                          subs=[('${REMOTE_APP_NAME}', get_remote_app_name())])
        else:
            msg = ba.Lstr(resource='cantConfigureDeviceText',
                          subs=[('${DEVICE}', device_name)])
        ba.textwidget(parent=dlg,
                      position=(0, height - 80),
                      size=(width, 25),
                      text=msg,
                      scale=0.8,
                      h_align='center',
                      v_align='top')

        def _ok() -> None:
            from bastd.ui.settings import controls
            ba.containerwidget(edit=dlg, transition='out_right')
            ba.app.main_menu_window = (controls.ControlsSettingsWindow(
                transition='in_left').get_root_widget())

        ba.buttonwidget(parent=dlg,
                        position=((width - button_width) / 2, 20),
                        size=(button_width, 60),
                        label=ba.Lstr(resource='okText'),
                        on_activate_call=_ok)
Example #3
0
 def __del__(self) -> None:
     try:
         ba.app.ui.have_party_queue_window = False
         _ba.add_transaction({
             'type': 'PARTY_QUEUE_REMOVE',
             'q': self._queue_id
         })
         _ba.run_transactions()
     except Exception:
         ba.print_exception('Error removing self from party queue.')
Example #4
0
    def _run_selected_playlist(self) -> None:
        _ba.unlock_all_input()
        try:
            _ba.new_host_session(self._sessiontype)
        except Exception:
            from bastd import mainmenu
            ba.print_exception('exception running session', self._sessiontype)

            # Drop back into a main menu session.
            _ba.new_host_session(mainmenu.MainMenuSession)
    def _update_bots(self) -> None:
        assert self._bot_update_interval is not None
        self._bot_update_interval = max(0.5, self._bot_update_interval * 0.98)
        self._bot_update_timer = ba.Timer(self._bot_update_interval,
                                          ba.WeakCall(self._update_bots))
        botspawnpts: list[Sequence[float]] = [[-5.0, 5.5, -4.14],
                                              [0.0, 5.5, -4.14],
                                              [5.0, 5.5, -4.14]]
        dists = [0.0, 0.0, 0.0]
        playerpts: list[Sequence[float]] = []
        for player in self.players:
            try:
                if player.is_alive():
                    assert isinstance(player.actor, PlayerSpaz)
                    assert player.actor.node
                    playerpts.append(player.actor.node.position)
            except Exception:
                ba.print_exception('Error updating bots.')
        for i in range(3):
            for playerpt in playerpts:
                dists[i] += abs(playerpt[0] - botspawnpts[i][0])
            dists[i] += random.random() * 5.0  # Minor random variation.
        if dists[0] > dists[1] and dists[0] > dists[2]:
            spawnpt = botspawnpts[0]
        elif dists[1] > dists[2]:
            spawnpt = botspawnpts[1]
        else:
            spawnpt = botspawnpts[2]

        spawnpt = (spawnpt[0] + 3.0 * (random.random() - 0.5), spawnpt[1],
                   2.0 * (random.random() - 0.5) + spawnpt[2])

        # Normalize our bot type total and find a random number within that.
        total = 0.0
        for spawninfo in self._bot_spawn_types.values():
            total += spawninfo.spawnrate
        randval = random.random() * total

        # Now go back through and see where this value falls.
        total = 0
        bottype: Optional[type[SpazBot]] = None
        for spawntype, spawninfo in self._bot_spawn_types.items():
            total += spawninfo.spawnrate
            if randval <= total:
                bottype = spawntype
                break
        spawn_time = 1.0
        assert bottype is not None
        self._bots.spawn_bot(bottype, pos=spawnpt, spawn_time=spawn_time)

        # After every spawn we adjust our ratios slightly to get more
        # difficult.
        for spawninfo in self._bot_spawn_types.values():
            spawninfo.spawnrate += spawninfo.increase
            spawninfo.increase += spawninfo.dincrease
Example #6
0
    def handlemessage(self, msg: Any) -> Any:
        if isinstance(msg, ba.PlayerScoredMessage):
            self._score += msg.score
            self._update_scores()

        elif isinstance(msg, ba.PlayerDiedMessage):
            # Augment standard behavior.
            super().handlemessage(msg)

            self._a_player_has_been_killed = True

            # Respawn them shortly.
            player = msg.getplayer(Player)
            assert self.initialplayerinfos is not None
            respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0
            player.respawn_timer = ba.Timer(
                respawn_time, ba.Call(self.spawn_player_if_exists, player))
            player.respawn_icon = RespawnIcon(player, respawn_time)

        elif isinstance(msg, SpazBotDiedMessage):
            if msg.how is ba.DeathType.REACHED_GOAL:
                return None
            pts, importance = msg.spazbot.get_death_points(msg.how)
            if msg.killerplayer is not None:
                target: Optional[Sequence[float]]
                try:
                    assert msg.spazbot is not None
                    assert msg.spazbot.node
                    target = msg.spazbot.node.position
                except Exception:
                    ba.print_exception()
                    target = None
                try:
                    if msg.killerplayer:
                        self.stats.player_scored(msg.killerplayer,
                                                 pts,
                                                 target=target,
                                                 kill=True,
                                                 screenmessage=False,
                                                 importance=importance)
                        ba.playsound(self._dingsound if importance == 1 else
                                     self._dingsoundhigh,
                                     volume=0.6)
                except Exception:
                    ba.print_exception('Error on SpazBotDiedMessage')

            # Normally we pull scores from the score-set, but if there's no
            # player lets be explicit.
            else:
                self._score += pts
            self._update_scores()

        else:
            return super().handlemessage(msg)
        return None
Example #7
0
    def _run_selected_playlist(self) -> None:
        # pylint: disable=cyclic-import
        _ba.unlock_all_input()
        try:
            _ba.new_host_session(self._sessiontype)
        except Exception:
            from bastd import mainmenu
            ba.print_exception(f'Error running session {self._sessiontype}.')

            # Drop back into a main menu session.
            _ba.new_host_session(mainmenu.MainMenuSession)
Example #8
0
 def _refresh_tickets_text(self) -> None:
     if self._tickets_text is None:
         return
     try:
         tc_str = str(_ba.get_v1_account_ticket_count())
     except Exception:
         ba.print_exception()
         tc_str = '-'
     ba.textwidget(edit=self._tickets_text,
                   text=ba.Lstr(resource=self._r + '.ticketsText',
                                subs=[('${COUNT}', tc_str)]))
Example #9
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._back_button:
             sel_name = 'Back'
         elif sel == self._scrollwidget:
             sel_name = 'Scroll'
         else:
             raise Exception('unrecognized selection')
         ba.app.window_states[self.__class__.__name__] = sel_name
     except Exception:
         ba.print_exception('exception saving state for', self.__class__)
Example #10
0
 def _restore_state(self) -> None:
     try:
         sel_name = ba.app.ui.window_states.get(type(self))
         if sel_name == 'Back':
             sel = self._back_button
         elif sel_name == 'Scroll':
             sel = self._scrollwidget
         else:
             sel = self._back_button
         ba.containerwidget(edit=self._root_widget, selected_child=sel)
     except Exception:
         ba.print_exception(f'Error restoring state for {self}.')
Example #11
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._back_button:
             sel_name = 'Back'
         elif sel == self._scrollwidget:
             sel_name = 'Scroll'
         else:
             raise ValueError('unrecognized selection')
         ba.app.ui.window_states[type(self)] = sel_name
     except Exception:
         ba.print_exception(f'Error saving state for {self}.')
Example #12
0
 def do_it() -> None:
     try:
         # reset to normal speed
         _ba.set_replay_speed_exponent(0)
         _ba.fade_screen(True)
         assert self._my_replay_selected is not None
         _ba.new_replay_session(_ba.get_replays_dir() + '/' +
                                self._my_replay_selected)
     except Exception:
         ba.print_exception('exception running replay session')
         # drop back into a fresh main menu session
         # in case we half-launched or something..
         from bastd import mainmenu
         _ba.new_host_session(mainmenu.MainMenuSession)
Example #13
0
 def _restore_state(self) -> None:
     # pylint: disable=too-many-branches
     try:
         sel_name = ba.app.ui.window_states.get(type(self),
                                                {}).get('sel_name')
         if sel_name == 'Back':
             sel = self._back_button
         else:
             ba.containerwidget(edit=self._root_widget,
                                selected_child=self._scrollwidget)
             if sel_name == 'VRTest':
                 sel = self._vr_test_button
             elif sel_name == 'NetTest':
                 sel = self._net_test_button
             elif sel_name == 'PromoCode':
                 sel = self._promo_code_button
             elif sel_name == 'Benchmarks':
                 sel = self._benchmarks_button
             elif sel_name == 'KickIdlePlayers':
                 sel = self._kick_idle_players_check_box.widget
             elif sel_name == 'DisableCameraShake':
                 sel = self._disable_camera_shake_check_box.widget
             elif (sel_name == 'AlwaysUseInternalKeyboard'
                   and self._always_use_internal_keyboard_check_box
                   is not None):
                 sel = self._always_use_internal_keyboard_check_box.widget
             elif (sel_name == 'DisableGyro'
                   and self._disable_gyro_check_box is not None):
                 sel = self._disable_gyro_check_box.widget
             elif (sel_name == 'Languages'
                   and self._language_popup is not None):
                 sel = self._language_popup.get_button()
             elif sel_name == 'TranslationEditor':
                 sel = self._translation_editor_button
             elif sel_name == 'ShowUserMods':
                 sel = self._show_user_mods_button
             elif sel_name == 'Plugins':
                 sel = self._plugins_button
             elif sel_name == 'ModdingGuide':
                 sel = self._modding_guide_button
             elif sel_name == 'LangInform':
                 sel = self._language_inform_checkbox
             else:
                 sel = None
             if sel is not None:
                 ba.containerwidget(edit=self._subcontainer,
                                    selected_child=sel,
                                    visible_child=sel)
     except Exception:
         ba.print_exception(f'Error restoring state for {self.__class__}')
Example #14
0
 def _delete_replay(self, replay: str) -> None:
     try:
         _ba.increment_analytics_count('Replay delete')
         os.remove((_ba.get_replays_dir() + '/' + replay).encode('utf-8'))
         self._refresh_my_replays()
         ba.playsound(ba.getsound('shieldDown'))
         if replay == self._my_replay_selected:
             self._my_replay_selected = None
     except Exception:
         ba.print_exception("exception deleting replay '" + replay + "'")
         ba.playsound(ba.getsound('error'))
         ba.screenmessage(ba.Lstr(resource=self._r +
                                  '.replayDeleteErrorText'),
                          color=(1, 0, 0))
Example #15
0
 def _uninstall_target():
     try:
         bap.uninstall(self.pkginfo.name)
     except Exception as e:
         ba.print_exception()
         ba.pushcall(ba.Call(ba.screenmessage,
                             f'Error: {e}',
                             color=(1, 0, 0)),
                     from_other_thread=True)
     else:
         ba.pushcall(ba.Call(ba.screenmessage, 'Done', color=(0, 1, 0)),
                     from_other_thread=True)
         if self._parent:
             self._parent._push_refresh()
    def _launch(self) -> None:
        if self._launched:
            return
        self._launched = True
        launched = False

        # If they gave us an existing activity, just restart it.
        if self._tournament_activity is not None:
            try:
                ba.timer(0.1,
                         lambda: ba.playsound(ba.getsound('cashRegister')),
                         timetype=ba.TimeType.REAL)
                with ba.Context(self._tournament_activity):
                    self._tournament_activity.end({'outcome': 'restart'},
                                                  force=True)
                ba.timer(0.3, self._transition_out, timetype=ba.TimeType.REAL)
                launched = True
                ba.screenmessage(ba.Lstr(translate=('serverResponses',
                                                    'Entering tournament...')),
                                 color=(0, 1, 0))

            # We can hit exceptions here if _tournament_activity ends before
            # our restart attempt happens.
            # In this case we'll fall back to launching a new session.
            # This is not ideal since players will have to rejoin, etc.,
            # but it works for now.
            except Exception:
                ba.print_exception('Error restarting tournament activity.')

        # If we had no existing activity (or were unable to restart it)
        # launch a new session.
        if not launched:
            ba.timer(0.1,
                     lambda: ba.playsound(ba.getsound('cashRegister')),
                     timetype=ba.TimeType.REAL)
            ba.timer(
                1.0,
                lambda: ba.app.launch_coop_game(
                    self._tournament_info['game'],
                    args={
                        'min_players': self._tournament_info['minPlayers'],
                        'max_players': self._tournament_info['maxPlayers'],
                        'tournament_id': self._tournament_id
                    }),
                timetype=ba.TimeType.REAL)
            ba.timer(0.7, self._transition_out, timetype=ba.TimeType.REAL)
            ba.screenmessage(ba.Lstr(translate=('serverResponses',
                                                'Entering tournament...')),
                             color=(0, 1, 0))
Example #17
0
 def _save_state(self) -> None:
     # pylint: disable=too-many-branches
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._scrollwidget:
             sel = self._subcontainer.get_selected_child()
             if sel == self._vr_test_button:
                 sel_name = 'VRTest'
             elif sel == self._net_test_button:
                 sel_name = 'NetTest'
             elif sel == self._promo_code_button:
                 sel_name = 'PromoCode'
             elif sel == self._benchmarks_button:
                 sel_name = 'Benchmarks'
             elif sel == self._kick_idle_players_check_box.widget:
                 sel_name = 'KickIdlePlayers'
             elif sel == self._disable_camera_shake_check_box.widget:
                 sel_name = 'DisableCameraShake'
             elif (self._always_use_internal_keyboard_check_box is not None
                   and sel
                   == self._always_use_internal_keyboard_check_box.widget):
                 sel_name = 'AlwaysUseInternalKeyboard'
             elif (self._disable_gyro_check_box is not None
                   and sel == self._disable_gyro_check_box.widget):
                 sel_name = 'DisableGyro'
             elif (self._language_popup is not None
                   and sel == self._language_popup.get_button()):
                 sel_name = 'Languages'
             elif sel == self._translation_editor_button:
                 sel_name = 'TranslationEditor'
             elif sel == self._show_user_mods_button:
                 sel_name = 'ShowUserMods'
             elif sel == self._plugins_button:
                 sel_name = 'Plugins'
             elif sel == self._modding_guide_button:
                 sel_name = 'ModdingGuide'
             elif sel == self._language_inform_checkbox:
                 sel_name = 'LangInform'
             else:
                 raise ValueError(f'unrecognized selection \'{sel}\'')
         elif sel == self._back_button:
             sel_name = 'Back'
         else:
             raise ValueError(f'unrecognized selection \'{sel}\'')
         ba.app.ui.window_states[self.__class__.__name__] = {
             'sel_name': sel_name
         }
     except Exception:
         ba.print_exception(f'Error saving state for {self.__class__}')
Example #18
0
 def _restore_state(self) -> None:
     try:
         try:
             sel_name = ba.app.window_states[self.__class__.__name__]
         except Exception:
             sel_name = None
         if sel_name == 'Back':
             sel = self._back_button
         elif sel_name == 'Scroll':
             sel = self._scrollwidget
         else:
             sel = self._back_button
         ba.containerwidget(edit=self._root_widget, selected_child=sel)
     except Exception:
         ba.print_exception('error restoring state for', self.__class__)
Example #19
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._new_button:
             sel_name = 'New'
         elif sel == self._edit_button:
             sel_name = 'Edit'
         elif sel == self._delete_button:
             sel_name = 'Delete'
         elif sel == self._scrollwidget:
             sel_name = 'Scroll'
         else:
             sel_name = 'Back'
         ba.app.window_states[self.__class__.__name__] = sel_name
     except Exception:
         ba.print_exception('error saving state for', self.__class__)
Example #20
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._teams_button:
             sel_name = 'Team Games'
         elif self._coop_button is not None and sel == self._coop_button:
             sel_name = 'Co-op Games'
         elif sel == self._free_for_all_button:
             sel_name = 'Free-for-All Games'
         elif sel == self._back_button:
             sel_name = 'Back'
         else:
             raise ValueError(f'unrecognized selection {sel}')
         ba.app.ui.window_states[type(self)] = sel_name
     except Exception:
         ba.print_exception(f'Error saving state for {self}.')
Example #21
0
 def run(self) -> None:
     try:
         # FIXME: Update this to work with IPv6 at some point.
         import socket
         sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
         sock.connect(('8.8.8.8', 80))
         val = sock.getsockname()[0]
         sock.close()
         ba.pushcall(ba.Call(self._call, val), from_other_thread=True)
     except Exception as exc:
         # Ignore expected network errors; log others.
         import errno
         if isinstance(exc, OSError) and exc.errno == errno.ENETUNREACH:
             pass
         else:
             ba.print_exception()
Example #22
0
    def _reset_progress(self) -> None:
        try:
            from ba.internal import getcampaign
            # FIXME: This would need to happen server-side these days.
            if self._can_reset_achievements:
                ba.app.config['Achievements'] = {}
                _ba.reset_achievements()
            campaign = getcampaign('Default')
            campaign.reset()  # also writes the config..
            campaign = getcampaign('Challenges')
            campaign.reset()  # also writes the config..
        except Exception:
            ba.print_exception('Error resetting co-op campaign progress.')

        ba.playsound(ba.getsound('shieldDown'))
        self._refresh()
Example #23
0
 def _restore_state(self) -> None:
     try:
         sel_name = ba.app.window_states.get(self.__class__.__name__)
         if sel_name == 'Team Games':
             sel = self._teams_button
         elif sel_name == 'Co-op Games':
             sel = self._coop_button
         elif sel_name == 'Free-for-All Games':
             sel = self._free_for_all_button
         elif sel_name == 'Back':
             sel = self._back_button
         else:
             sel = self._coop_button
         ba.containerwidget(edit=self._root_widget, selected_child=sel)
     except Exception:
         ba.print_exception(f'Error restoring state for {self}.')
Example #24
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._teams_button:
             sel_name = 'Team Games'
         elif sel == self._coop_button:
             sel_name = 'Co-op Games'
         elif sel == self._free_for_all_button:
             sel_name = 'Free-for-All Games'
         elif sel == self._back_button:
             sel_name = 'Back'
         else:
             raise Exception("unrecognized selected widget")
         ba.app.window_states[self.__class__.__name__] = sel_name
     except Exception:
         ba.print_exception('error saving state for', self.__class__)
Example #25
0
 def _save_state(self) -> None:
     try:
         sel = self._root_widget.get_selected_child()
         if sel == self._new_button:
             sel_name = 'New'
         elif sel == self._edit_button:
             sel_name = 'Edit'
         elif sel == self._delete_button:
             sel_name = 'Delete'
         elif sel == self._scrollwidget:
             sel_name = 'Scroll'
         else:
             sel_name = 'Back'
         ba.app.ui.window_states[type(self)] = sel_name
     except Exception:
         ba.print_exception(f'Error saving state for {self}.')
Example #26
0
 def run(self) -> None:
     try:
         # FIXME: Update this to work with IPv6 at some point.
         import socket
         sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
         sock.connect(('8.8.8.8', 80))
         val = sock.getsockname()[0]
         sock.close()
         ba.pushcall(ba.Call(self._call, val), from_other_thread=True)
     except Exception as exc:
         from efro.error import is_udp_network_error
         # Ignore expected network errors; log others.
         if is_udp_network_error(exc):
             pass
         else:
             ba.print_exception()
Example #27
0
    def handlemessage(self, msg: Any) -> Any:
        if isinstance(msg, stdflag.FlagPickedUpMessage):
            assert isinstance(msg.flag, FootballFlag)
            try:
                player = msg.node.getdelegate().getplayer()
                if player:
                    msg.flag.last_holding_player = player
                msg.flag.held_count += 1
            except Exception:
                ba.print_exception('exception in Football FlagPickedUpMessage;'
                                   " this shouldn't happen")

        elif isinstance(msg, stdflag.FlagDroppedMessage):
            assert isinstance(msg.flag, FootballFlag)
            msg.flag.held_count -= 1

        # Respawn dead players if they're still in the game.
        elif isinstance(msg, playerspaz.PlayerSpazDeathMessage):
            # Augment standard behavior.
            super().handlemessage(msg)
            self.respawn_player(msg.spaz.player)

        # Respawn dead flags.
        elif isinstance(msg, stdflag.FlagDeathMessage):
            if not self.has_ended():
                self._flag_respawn_timer = ba.Timer(3.0, self._spawn_flag)
                self._flag_respawn_light = ba.NodeActor(
                    ba.newnode('light',
                               attrs={
                                   'position': self._flag_spawn_pos,
                                   'height_attenuated': False,
                                   'radius': 0.15,
                                   'color': (1.0, 1.0, 0.3)
                               }))
                assert self._flag_respawn_light.node
                ba.animate(self._flag_respawn_light.node,
                           'intensity', {
                               0.0: 0,
                               0.25: 0.15,
                               0.5: 0
                           },
                           loop=True)
                ba.timer(3.0, self._flag_respawn_light.node.delete)

        else:
            # Augment standard behavior.
            super().handlemessage(msg)
Example #28
0
    def run(self) -> None:
        ba.app.ping_thread_count += 1
        sock: Optional[socket.socket] = None
        try:
            import socket
            from ba.internal import get_ip_address_type
            socket_type = get_ip_address_type(self._address)
            sock = socket.socket(socket_type, socket.SOCK_DGRAM)
            sock.connect((self._address, self._port))

            accessible = False
            starttime = time.time()

            # Send a few pings and wait a second for
            # a response.
            sock.settimeout(1)
            for _i in range(3):
                sock.send(b'\x0b')
                result: Optional[bytes]
                try:
                    # 11: BA_PACKET_SIMPLE_PING
                    result = sock.recv(10)
                except Exception:
                    result = None
                if result == b'\x0c':
                    # 12: BA_PACKET_SIMPLE_PONG
                    accessible = True
                    break
                time.sleep(1)
            ping = (time.time() - starttime) * 1000.0
            ba.pushcall(ba.Call(self._call, self._address, self._port,
                                ping if accessible else None),
                        from_other_thread=True)
        except Exception as exc:
            from efro.error import is_udp_network_error
            if is_udp_network_error(exc):
                pass
            else:
                ba.print_exception('Error on gather ping', once=True)
        finally:
            try:
                if sock is not None:
                    sock.close()
            except Exception:
                ba.print_exception('Error on gather ping cleanup', once=True)

        ba.app.ping_thread_count -= 1
Example #29
0
 def _restore_state(self) -> None:
     try:
         sel_name = ba.app.window_states.get(self.__class__.__name__)
         if sel_name == 'Back':
             sel = self._back_button
         elif sel_name == 'Scroll':
             sel = self._scrollwidget
         elif sel_name == 'Customize':
             sel = self._scrollwidget
             ba.containerwidget(edit=self._subcontainer,
                                selected_child=self._customize_button,
                                visible_child=self._customize_button)
         else:
             sel = self._scrollwidget
         ba.containerwidget(edit=self._root_widget, selected_child=sel)
     except Exception:
         ba.print_exception(f'Error restoring state for {self}.')
Example #30
0
    def _rename_my_replay(self, replay: str) -> None:
        new_name = None
        try:
            if not self._my_replay_rename_text:
                return
            new_name_raw = cast(
                str, ba.textwidget(query=self._my_replay_rename_text))
            new_name = new_name_raw + '.brp'

            # Ignore attempts to change it to what it already is
            # (or what it looks like to the user).
            if (replay != new_name
                    and self._get_replay_display_name(replay) != new_name_raw):
                old_name_full = (_ba.get_replays_dir() + '/' +
                                 replay).encode('utf-8')
                new_name_full = (_ba.get_replays_dir() + '/' +
                                 new_name).encode('utf-8')
                # False alarm; ba.textwidget can return non-None val.
                # pylint: disable=unsupported-membership-test
                if os.path.exists(new_name_full):
                    ba.playsound(ba.getsound('error'))
                    ba.screenmessage(
                        ba.Lstr(resource=self._r +
                                '.replayRenameErrorAlreadyExistsText'),
                        color=(1, 0, 0))
                elif any(char in new_name_raw for char in ['/', '\\', ':']):
                    ba.playsound(ba.getsound('error'))
                    ba.screenmessage(ba.Lstr(resource=self._r +
                                             '.replayRenameErrorInvalidName'),
                                     color=(1, 0, 0))
                else:
                    _ba.increment_analytics_count('Replay rename')
                    os.rename(old_name_full, new_name_full)
                    self._refresh_my_replays()
                    ba.playsound(ba.getsound('gunCocking'))
        except Exception:
            ba.print_exception(
                f"Error renaming replay '{replay}' to '{new_name}'.")
            ba.playsound(ba.getsound('error'))
            ba.screenmessage(
                ba.Lstr(resource=self._r + '.replayRenameErrorText'),
                color=(1, 0, 0),
            )

        ba.containerwidget(edit=self._my_replays_rename_window,
                           transition='out_scale')