Example #1
0
def _reset_stress_test(args: Dict[str, Any]) -> None:
    from ba._general import Call
    from ba._enums import TimeType
    _ba.set_stress_testing(False, args['player_count'])
    _ba.screenmessage('Resetting stress test...')
    session = _ba.get_foreground_host_session()
    assert session is not None
    session.end()
    _ba.timer(1.0, Call(start_stress_test, args), timetype=TimeType.REAL)
Example #2
0
def save_ids(ids, pb_id, display_string):

    pdata.update_display_string(pb_id, ids)

    if display_string not in ids:
        msg = "Spoofed Id detected , Goodbye"
        _ba.pushcall(Call(kick_by_pb_id, pb_id, msg), from_other_thread=True)
        serverdata.clients[pb_id]["verified"] = False
        logger.log(pb_id + "|| kicked , for using spoofed id " +
                   display_string)
    else:
        serverdata.clients[pb_id]["verified"] = True
Example #3
0
def save_age(age, pb_id, display_string):

    pdata.add_profile(pb_id, display_string, display_string, age)
    time.sleep(2)
    thread2 = FetchThread(target=get_device_accounts,
                          callback=save_ids,
                          pb_id=pb_id,
                          display_string=display_string)
    thread2.start()
    if get_account_age(age) < settings["minAgeToJoinInHours"]:
        msg = "New Accounts not allowed to play here , come back tmrw."
        logger.log(pb_id + "|| kicked > new account")
        _ba.pushcall(Call(kick_by_pb_id, pb_id, msg), from_other_thread=True)
Example #4
0
    def delay_add(start_time: float) -> None:
        def doit(start_time_2: float) -> None:
            from ba import _lang
            _ba.screenmessage(
                _lang.get_resource('debugWindow.totalReloadTimeText').replace(
                    '${TIME}', str(_ba.time(TimeType.REAL) - start_time_2)))
            _ba.print_load_info()
            if _ba.app.config.resolve('Texture Quality') != 'High':
                _ba.screenmessage(_lang.get_resource(
                    'debugWindow.reloadBenchmarkBestResultsText'),
                                  color=(1, 1, 0))

        _ba.add_clean_frame_callback(Call(doit, start_time))
Example #5
0
def print_corrupt_file_error() -> None:
    """Print an error if a corrupt file is found."""
    from ba._general import Call
    from ba._generated.enums import TimeType
    _ba.timer(2.0,
              lambda: _ba.screenmessage(
                  _ba.app.lang.get_resource('internal.corruptFileText').
                  replace('${EMAIL}', '*****@*****.**'),
                  color=(1, 0, 0),
              ),
              timetype=TimeType.REAL)
    _ba.timer(2.0,
              Call(_ba.playsound, _ba.getsound('error')),
              timetype=TimeType.REAL)
Example #6
0
    def __del__(self) -> None:

        # If the activity has been run then we should have already cleaned
        # it up, but we still need to run expire calls for un-run activities.
        if not self._expired:
            with _ba.Context('empty'):
                self._expire()

        # Inform our owner that we officially kicked the bucket.
        if self._transitioning_out:
            session = self._session()
            if session is not None:
                _ba.pushcall(
                    Call(session.transitioning_out_activity_was_freed,
                         self.can_show_ad_on_death))
Example #7
0
    def send_message(
        self,
        msg: Message,
        on_response: Callable[[Any], None],
    ) -> None:
        """Asynchronously send a message to the cloud from the game thread.

        The provided on_response call will be run in the logic thread
        and passed either the response or the error that occurred.
        """
        from ba._general import Call
        del msg  # Unused.

        _ba.pushcall(
            Call(on_response,
                 RuntimeError('Cloud functionality is not available.')))
Example #8
0
 def _play_current_playlist(self) -> None:
     try:
         from ba._general import Call
         assert self._current_playlist is not None
         if _ba.mac_music_app_play_playlist(self._current_playlist):
             pass
         else:
             _ba.pushcall(Call(
                 _ba.screenmessage,
                 _ba.app.lang.get_resource('playlistNotFoundText') +
                 ': \'' + self._current_playlist + '\'', (1, 0, 0)),
                          from_other_thread=True)
     except Exception:
         from ba import _error
         _error.print_exception(
             f'error playing playlist {self._current_playlist}')
Example #9
0
 def _handle_get_playlists_command(
         self, target: Callable[[List[str]], None]) -> None:
     from ba._general import Call
     try:
         playlists = _ba.mac_music_app_get_playlists()
         playlists = [
             p for p in playlists if p not in [
                 'Music', 'Movies', 'TV Shows', 'Podcasts', 'iTunes\xa0U',
                 'Books', 'Genius', 'iTunes DJ', 'Music Videos',
                 'Home Videos', 'Voice Memos', 'Audiobooks'
             ]
         ]
         playlists.sort(key=lambda x: x.lower())
     except Exception as exc:
         print('Error getting iTunes playlists:', exc)
         playlists = []
     _ba.pushcall(Call(target, playlists), from_other_thread=True)
Example #10
0
    def announce_game_results(self,
                              activity: ba.GameActivity,
                              results: ba.GameResults,
                              delay: float,
                              announce_winning_team: bool = True) -> None:
        """Show basic game result at the end of a game.

        (before transitioning to a score screen).
        This will include a zoom-text of 'BLUE WINS'
        or whatnot, along with a possible audio
        announcement of the same.
        """
        # pylint: disable=cyclic-import
        # pylint: disable=too-many-locals
        from ba._math import normalized_color
        from ba._general import Call
        from ba._gameutils import cameraflash
        from ba._language import Lstr
        from ba._freeforallsession import FreeForAllSession
        from ba._messages import CelebrateMessage
        _ba.timer(delay, Call(_ba.playsound, _ba.getsound('boxingBell')))

        if announce_winning_team:
            winning_sessionteam = results.winning_sessionteam
            if winning_sessionteam is not None:
                # Have all players celebrate.
                celebrate_msg = CelebrateMessage(duration=10.0)
                assert winning_sessionteam.activityteam is not None
                for player in winning_sessionteam.activityteam.players:
                    if player.actor:
                        player.actor.handlemessage(celebrate_msg)
                cameraflash()

                # Some languages say "FOO WINS" different for teams vs players.
                if isinstance(self, FreeForAllSession):
                    wins_resource = 'winsPlayerText'
                else:
                    wins_resource = 'winsTeamText'
                wins_text = Lstr(resource=wins_resource,
                                 subs=[('${NAME}', winning_sessionteam.name)])
                activity.show_zoom_message(
                    wins_text,
                    scale=0.85,
                    color=normalized_color(winning_sessionteam.color),
                )
Example #11
0
    def run(self) -> None:
        from ba._general import Call
        try:
            scan = DirectoryScan(self._dirs)
            scan.scan()
            results = scan.results
        except Exception as exc:
            results = ScanResults(errors=f'Scan exception: {exc}')

        # Push a call to the game thread to print warnings/errors
        # or otherwise deal with scan results.
        _ba.pushcall(Call(_ba.app.meta.handle_scan_results, results),
                     from_other_thread=True)

        # We also, however, immediately make results available.
        # This is because the game thread may be blocked waiting
        # for them so we can't push a call or we'd get deadlock.
        _ba.app.meta.metascan = results
Example #12
0
    def _handle_server_restarts(self) -> bool:
        """Handle automatic restarts/shutdowns in server mode.

        Returns True if an action was taken; otherwise default action
        should occur (starting next round, etc).
        """
        # pylint: disable=cyclic-import

        # FIXME: Move server stuff to its own module.
        if self._allow_server_restart and _ba.app.server_config_dirty:
            from ba import _server
            from ba._lang import Lstr
            from ba._general import Call
            from ba._enums import TimeType
            if _ba.app.server_config.get('quit', False):
                if not self._kicked_off_server_shutdown:
                    if _ba.app.server_config.get(
                            'quit_reason') == 'restarting':
                        # FIXME: Should add a server-screen-message call
                        #  or something.
                        _ba.chat_message(
                            Lstr(resource='internal.serverRestartingText').
                            evaluate())
                        print(('Exiting for server-restart at ' +
                               time.strftime('%c')))
                    else:
                        print(('Exiting for server-shutdown at ' +
                               time.strftime('%c')))
                    with _ba.Context('ui'):
                        _ba.timer(2.0, _ba.quit, timetype=TimeType.REAL)
                    self._kicked_off_server_shutdown = True
                    return True
            else:
                if not self._kicked_off_server_restart:
                    print(('Running updated server config at ' +
                           time.strftime('%c')))
                    with _ba.Context('ui'):
                        _ba.timer(1.0,
                                  Call(_ba.pushcall,
                                       _server.launch_server_session),
                                  timetype=TimeType.REAL)
                    self._kicked_off_server_restart = True
                    return True
        return False
Example #13
0
    def end(  # type: ignore
            self,
            results: Any = None,
            announce_winning_team: bool = True,
            announce_delay: float = 0.1,
            force: bool = False) -> None:
        """
        End the game and announce the single winning team
        unless 'announce_winning_team' is False.
        (for results without a single most-important winner).
        """
        # pylint: disable=arguments-differ
        from ba._coopsession import CoopSession
        from ba._multiteamsession import MultiTeamSession
        from ba._general import Call

        # Announce win (but only for the first finish() call)
        # (also don't announce in co-op sessions; we leave that up to them).
        session = self.session
        if not isinstance(session, CoopSession):
            do_announce = not self.has_ended()
            super().end(results, delay=2.0 + announce_delay, force=force)

            # Need to do this *after* end end call so that results is valid.
            assert isinstance(results, TeamGameResults)
            if do_announce and isinstance(session, MultiTeamSession):
                session.announce_game_results(
                    self,
                    results,
                    delay=announce_delay,
                    announce_winning_team=announce_winning_team)

        # For co-op we just pass this up the chain with a delay added
        # (in most cases). Team games expect a delay for the announce
        # portion in teams/ffa mode so this keeps it consistent.
        else:
            # don't want delay on restarts..
            if (isinstance(results, dict) and 'outcome' in results
                    and results['outcome'] == 'restart'):
                delay = 0.0
            else:
                delay = 2.0
                _ba.timer(0.1, Call(_ba.playsound, _ba.getsound('boxingBell')))
            super().end(results, delay=delay, force=force)
Example #14
0
    def return_to_main_menu_session_gracefully(self,
                                               reset_ui: bool = True) -> None:
        """Attempt to cleanly get back to the main menu."""
        # pylint: disable=cyclic-import
        from ba import _benchmark
        from ba._general import Call
        from bastd.mainmenu import MainMenuSession
        if reset_ui:
            _ba.app.ui.clear_main_menu_window()

        if isinstance(_ba.get_foreground_host_session(), MainMenuSession):
            # It may be possible we're on the main menu but the screen is faded
            # so fade back in.
            _ba.fade_screen(True)
            return

        _benchmark.stop_stress_test()  # Stop stress-test if in progress.

        # If we're in a host-session, tell them to end.
        # This lets them tear themselves down gracefully.
        host_session: Optional[ba.Session] = _ba.get_foreground_host_session()
        if host_session is not None:

            # Kick off a little transaction so we'll hopefully have all the
            # latest account state when we get back to the menu.
            _ba.add_transaction({
                'type': 'END_SESSION',
                'sType': str(type(host_session))
            })
            _ba.run_transactions()

            host_session.end()

        # Otherwise just force the issue.
        else:
            _ba.pushcall(Call(_ba.new_host_session, MainMenuSession))
Example #15
0
 def run(self):
     player_data = pdata.get_info(self.pbid)
     _ba.pushcall(Call(on_player_join_server, self.pbid, player_data),
                  from_other_thread=True)
    def _show_info(self) -> None:
        """Show the game description."""
        from ba._gameutils import animate
        from bastd.actor.zoomtext import ZoomText
        name = self.get_instance_display_string()
        ZoomText(name,
                 maxwidth=800,
                 lifespan=2.5,
                 jitter=2.0,
                 position=(0, 180),
                 flash=False,
                 color=(0.93 * 1.25, 0.9 * 1.25, 1.0 * 1.25),
                 trailcolor=(0.15, 0.05, 1.0, 0.0)).autoretain()
        _ba.timer(0.2, Call(_ba.playsound, _ba.getsound('gong')))

        # The description can be either a string or a sequence with args
        # to swap in post-translation.
        desc_in = self.get_instance_description()
        desc_l: Sequence
        if isinstance(desc_in, str):
            desc_l = [desc_in]  # handle simple string case
        else:
            desc_l = desc_in
        if not isinstance(desc_l[0], str):
            raise TypeError('Invalid format for instance description')
        subs = []
        for i in range(len(desc_l) - 1):
            subs.append(('${ARG' + str(i + 1) + '}', str(desc_l[i + 1])))
        translation = Lstr(translate=('gameDescriptions', desc_l[0]),
                           subs=subs)

        # Do some standard filters (epic mode, etc).
        if self.settings_raw.get('Epic Mode', False):
            translation = Lstr(resource='epicDescriptionFilterText',
                               subs=[('${DESCRIPTION}', translation)])
        vrmode = _ba.app.vr_mode
        dnode = _ba.newnode('text',
                            attrs={
                                'v_attach': 'center',
                                'h_attach': 'center',
                                'h_align': 'center',
                                'color': (1, 1, 1, 1),
                                'shadow': 1.0 if vrmode else 0.5,
                                'flatness': 1.0 if vrmode else 0.5,
                                'vr_depth': -30,
                                'position': (0, 80),
                                'scale': 1.2,
                                'maxwidth': 700,
                                'text': translation
                            })
        cnode = _ba.newnode('combine',
                            owner=dnode,
                            attrs={
                                'input0': 1.0,
                                'input1': 1.0,
                                'input2': 1.0,
                                'size': 4
                            })
        cnode.connectattr('output', dnode, 'color')
        keys = {0.5: 0, 1.0: 1.0, 2.5: 1.0, 4.0: 0.0}
        animate(cnode, 'input3', keys)
        _ba.timer(4.0, dnode.delete)
Example #17
0
    def submit_kill(self, showpoints: bool = True) -> None:
        """Submit a kill for this player entry."""
        # FIXME Clean this up.
        # pylint: disable=too-many-statements
        from ba._lang import Lstr
        from ba._general import Call
        self._multi_kill_count += 1
        stats = self._stats()
        assert stats
        if self._multi_kill_count == 1:
            score = 0
            name = None
            delay = 0.0
            color = (0.0, 0.0, 0.0, 1.0)
            scale = 1.0
            sound = None
        elif self._multi_kill_count == 2:
            score = 20
            name = Lstr(resource='twoKillText')
            color = (0.1, 1.0, 0.0, 1)
            scale = 1.0
            delay = 0.0
            sound = stats.orchestrahitsound1
        elif self._multi_kill_count == 3:
            score = 40
            name = Lstr(resource='threeKillText')
            color = (1.0, 0.7, 0.0, 1)
            scale = 1.1
            delay = 0.3
            sound = stats.orchestrahitsound2
        elif self._multi_kill_count == 4:
            score = 60
            name = Lstr(resource='fourKillText')
            color = (1.0, 1.0, 0.0, 1)
            scale = 1.2
            delay = 0.6
            sound = stats.orchestrahitsound3
        elif self._multi_kill_count == 5:
            score = 80
            name = Lstr(resource='fiveKillText')
            color = (1.0, 0.5, 0.0, 1)
            scale = 1.3
            delay = 0.9
            sound = stats.orchestrahitsound4
        else:
            score = 100
            name = Lstr(resource='multiKillText',
                        subs=[('${COUNT}', str(self._multi_kill_count))])
            color = (1.0, 0.5, 0.0, 1)
            scale = 1.3
            delay = 1.0
            sound = stats.orchestrahitsound4

        def _apply(name2: Lstr, score2: int, showpoints2: bool,
                   color2: Tuple[float, float, float, float], scale2: float,
                   sound2: Optional[ba.Sound]) -> None:
            from bastd.actor.popuptext import PopupText

            # Only award this if they're still alive and we can get
            # a current position for them.
            our_pos: Optional[Sequence[float]] = None
            if self._player is not None:
                if self._player.gameplayer is not None:
                    if self._player.gameplayer.node:
                        our_pos = self._player.gameplayer.node.position
            if our_pos is None:
                return

            # Jitter position a bit since these often come in clusters.
            our_pos = (our_pos[0] + (random.random() - 0.5) * 2.0,
                       our_pos[1] + (random.random() - 0.5) * 2.0,
                       our_pos[2] + (random.random() - 0.5) * 2.0)
            activity = self.getactivity()
            if activity is not None:
                PopupText(Lstr(
                    value=(('+' + str(score2) + ' ') if showpoints2 else '') +
                    '${N}',
                    subs=[('${N}', name2)]),
                          color=color2,
                          scale=scale2,
                          position=our_pos).autoretain()
            if sound2:
                _ba.playsound(sound2)

            self.score += score2
            self.accumscore += score2

            # Inform a running game of the score.
            if score2 != 0 and activity is not None:
                activity.handlemessage(PlayerScoredMessage(score=score2))

        if name is not None:
            _ba.timer(
                0.3 + delay,
                Call(_apply, name, score, showpoints, color, scale, sound))

        # Keep the tally rollin'...
        # set a timer for a bit in the future.
        self._multi_kill_timer = _ba.Timer(1.0, self._end_multi_kill)
Example #18
0
def withDelay(session, playlist):

    time.sleep(1)

    _ba.pushcall(Call(updateSession, session, playlist),
                 from_other_thread=True)
Example #19
0
 def do_print() -> None:
     _ba.timer(1.0,
               Call(_ba.screenmessage, Lstr(resource='usingItunesText'),
                    (0, 1, 0)),
               timetype=TimeType.REAL)
Example #20
0
    def _set_ready(self, ready: bool) -> None:
        # pylint: disable=cyclic-import
        from bastd.ui.profile import browser as pbrowser
        from ba._general import Call
        profilename = self._profilenames[self._profileindex]

        # Handle '_edit' as a special case.
        if profilename == '_edit' and ready:
            with _ba.Context('ui'):
                pbrowser.ProfileBrowserWindow(in_main_menu=False)

                # Give their input-device UI ownership too
                # (prevent someone else from snatching it in crowded games)
                _ba.set_ui_input_device(self._sessionplayer.inputdevice)
            return

        if not ready:
            self._sessionplayer.assigninput(
                InputType.LEFT_PRESS,
                Call(self.handlemessage, ChangeMessage('team', -1)))
            self._sessionplayer.assigninput(
                InputType.RIGHT_PRESS,
                Call(self.handlemessage, ChangeMessage('team', 1)))
            self._sessionplayer.assigninput(
                InputType.BOMB_PRESS,
                Call(self.handlemessage, ChangeMessage('character', 1)))
            self._sessionplayer.assigninput(
                InputType.UP_PRESS,
                Call(self.handlemessage, ChangeMessage('profileindex', -1)))
            self._sessionplayer.assigninput(
                InputType.DOWN_PRESS,
                Call(self.handlemessage, ChangeMessage('profileindex', 1)))
            self._sessionplayer.assigninput(
                (InputType.JUMP_PRESS, InputType.PICK_UP_PRESS,
                 InputType.PUNCH_PRESS),
                Call(self.handlemessage, ChangeMessage('ready', 1)))
            self._ready = False
            self._update_text()
            self._sessionplayer.setname('untitled', real=False)
        else:
            self._sessionplayer.assigninput(
                (InputType.LEFT_PRESS, InputType.RIGHT_PRESS,
                 InputType.UP_PRESS, InputType.DOWN_PRESS,
                 InputType.JUMP_PRESS, InputType.BOMB_PRESS,
                 InputType.PICK_UP_PRESS), self._do_nothing)
            self._sessionplayer.assigninput(
                (InputType.JUMP_PRESS, InputType.BOMB_PRESS,
                 InputType.PICK_UP_PRESS, InputType.PUNCH_PRESS),
                Call(self.handlemessage, ChangeMessage('ready', 0)))

            # Store the last profile picked by this input for reuse.
            input_device = self._sessionplayer.inputdevice
            name = input_device.name
            unique_id = input_device.unique_identifier
            device_profiles = _ba.app.config.setdefault(
                'Default Player Profiles', {})

            # Make an exception if we have no custom profiles and are set
            # to random; in that case we'll want to start picking up custom
            # profiles if/when one is made so keep our setting cleared.
            special = ('_random', '_edit', '__account__')
            have_custom_profiles = any(p not in special
                                       for p in self._profiles)

            profilekey = name + ' ' + unique_id
            if profilename == '_random' and not have_custom_profiles:
                if profilekey in device_profiles:
                    del device_profiles[profilekey]
            else:
                device_profiles[profilekey] = profilename
            _ba.app.config.commit()

            # Set this player's short and full name.
            self._sessionplayer.setname(self._getname(),
                                        self._getname(full=True),
                                        real=True)
            self._ready = True
            self._update_text()

            # Inform the session that this player is ready.
            _ba.getsession().handlemessage(PlayerReadyMessage(self))