def __init__(self) -> None: env = _ba.env() self.controller: Optional[ba.UIController] = None self._main_menu_window: Optional[ba.Widget] = None self._main_menu_location: Optional[str] = None self._uiscale: ba.UIScale interfacetype = env['ui_scale'] if interfacetype == 'large': self._uiscale = UIScale.LARGE elif interfacetype == 'medium': self._uiscale = UIScale.MEDIUM elif interfacetype == 'small': self._uiscale = UIScale.SMALL else: raise RuntimeError(f'Invalid UIScale value: {interfacetype}') self.window_states: Dict = {} # FIXME: Kill this. self.main_menu_selection: Optional[str] = None # FIXME: Kill this. self.have_party_queue_window = False self.quit_window: Any = None self.dismiss_wii_remotes_window_call: (Optional[Callable[[], Any]]) = None self.cleanupchecks: List[UICleanupCheck] = [] self.upkeeptimer: Optional[ba.Timer] = None self.use_toolbars = env.get('toolbar_test', True) self.party_window: Any = None # FIXME: Don't use Any. self.title_color = (0.72, 0.7, 0.75) self.heading_color = (0.72, 0.7, 0.75) self.infotextcolor = (0.7, 0.9, 0.7)
def __init__(self): ba.screenmessage('Pro Unlock by Mr.Smoothy', color=( 0, 1, 0)) #will not work on android client ..still ... aadat se majboor if _ba.env().get("build_number", 0) >= 20124: _ba.get_purchased = hehe #now you are rich F else: print("pro unlocker only work on 1.5 ")
def locale(self) -> str: """Raw country/language code detected by the game (such as 'en_US'). Generally for language-specific code you should look at ba.App.language, which is the language the game is using (which may differ from locale if the user sets a language, etc.) """ env = _ba.env() assert isinstance(env['locale'], str) return env['locale']
def __init__(self): path = os.path.join(_ba.env()["python_directory_user"], "CustomCharacters" + os.sep) if not os.path.isdir(path): os.makedirs(path) files = os.listdir(path) for file in files: with open(path + file, 'r') as f: character = json.load(f) registercharacter(file, character)
def supports_soundtrack_entry_type(self, entry_type: str) -> bool: """Return whether provided soundtrack entry type is supported here.""" uas = _ba.env()['user_agent_string'] assert isinstance(uas, str) # FIXME: Generalize this. if entry_type == 'iTunesPlaylist': return 'Mac' in uas if entry_type in ('musicFile', 'musicFolder'): return ('android' in uas and _ba.android_get_external_storage_path() is not None) if entry_type == 'default': return True return False
def __init__(self) -> None: env = _ba.env() self.controller: Optional[ba.UIController] = None self._main_menu_window: Optional[ba.Widget] = None self._main_menu_location: Optional[str] = None self.window_states: Dict = {} # FIXME: Kill this. # self.windows: Dict = {} # FIXME: Kill this. self.main_menu_selection: Optional[str] = None # FIXME: Kill this. self.have_party_queue_window = False self.quit_window: Any = None self.dismiss_wii_remotes_window_call: (Optional[Callable[[], Any]]) = None self.cleanupchecks: List[UICleanupCheck] = [] self.upkeeptimer: Optional[ba.Timer] = None self.use_toolbars = env.get('toolbar_test', True) self.party_window: Any = None # FIXME: Don't use Any. self.title_color = (0.72, 0.7, 0.75) self.heading_color = (0.72, 0.7, 0.75) self.infotextcolor = (0.7, 0.9, 0.7)
def __init__(self) -> None: env = _ba.env() self.controller: Optional[ba.UIController] = None self._main_menu_window: Optional[ba.Widget] = None self._main_menu_location: Optional[str] = None self._uiscale: ba.UIScale interfacetype = env['ui_scale'] if interfacetype == 'large': self._uiscale = UIScale.LARGE elif interfacetype == 'medium': self._uiscale = UIScale.MEDIUM elif interfacetype == 'small': self._uiscale = UIScale.SMALL else: raise RuntimeError(f'Invalid UIScale value: {interfacetype}') self.window_states: Dict[Type, Any] = {} # FIXME: Kill this. self.main_menu_selection: Optional[str] = None # FIXME: Kill this. self.have_party_queue_window = False self.quit_window: Any = None self.dismiss_wii_remotes_window_call: (Optional[Callable[[], Any]]) = None self.cleanupchecks: List[UICleanupCheck] = [] self.upkeeptimer: Optional[ba.Timer] = None self.use_toolbars = env.get('toolbar_test', True) self.party_window: Any = None # FIXME: Don't use Any. self.title_color = (0.72, 0.7, 0.75) self.heading_color = (0.72, 0.7, 0.75) self.infotextcolor = (0.7, 0.9, 0.7) # Switch our overall game selection UI flow between Play and # Private-party playlist selection modes; should do this in # a more elegant way once we revamp high level UI stuff a bit. self.selecting_private_party_playlist: bool = False
def __init__(self) -> None: """(internal) Do not instantiate this class; use ba.app to access the single shared instance. """ # pylint: disable=too-many-statements from ba._music import MusicController # Config. self.config_file_healthy = False # This is incremented any time the app is backgrounded/foregrounded; # can be a simple way to determine if network data should be # refreshed/etc. self.fg_state = 0 # Environment stuff. # (pulling these into attrs so we can type-check them and provide docs) env = _ba.env() self._build_number: int = env['build_number'] assert isinstance(self._build_number, int) self._config_file_path: str = env['config_file_path'] assert isinstance(self._config_file_path, str) self._locale: str = env['locale'] assert isinstance(self._locale, str) self._user_agent_string: str = env['user_agent_string'] assert isinstance(self._user_agent_string, str) self._version: str = env['version'] assert isinstance(self._version, str) self._debug_build: bool = env['debug_build'] assert isinstance(self._debug_build, bool) self._test_build: bool = env['test_build'] assert isinstance(self._test_build, bool) self._python_directory_user: str = env['python_directory_user'] assert isinstance(self._python_directory_user, str) self._python_directory_ba: str = env['python_directory_ba'] assert isinstance(self._python_directory_ba, str) self._python_directory_site: str = env['python_directory_site'] assert isinstance(self._python_directory_site, str) self._platform: str = env['platform'] assert isinstance(self._platform, str) self._subplatform: str = env['subplatform'] assert isinstance(self._subplatform, str) self._interface_type: str = env['interface_type'] assert isinstance(self._interface_type, str) self._on_tv: bool = env['on_tv'] assert isinstance(self._on_tv, bool) self._vr_mode: bool = env['vr_mode'] assert isinstance(self._vr_mode, bool) self.protocol_version: int = env['protocol_version'] assert isinstance(self.protocol_version, int) self.toolbar_test: bool = env['toolbar_test'] assert isinstance(self.toolbar_test, bool) self.kiosk_mode: bool = env['kiosk_mode'] assert isinstance(self.kiosk_mode, bool) self.headless_build: bool = env['headless_build'] assert isinstance(self.headless_build, bool) # Misc. self.default_language = self._get_default_language() self.metascan: Optional[_meta.ScanResults] = None self.tips: List[str] = [] self.stress_test_reset_timer: Optional[ba.Timer] = None self.suppress_debug_reports = False self.last_ad_completion_time: Optional[float] = None self.last_ad_was_short = False self.did_weak_call_warning = False self.ran_on_app_launch = False # If we try to run promo-codes due to launch-args/etc we might # not be signed in yet; go ahead and queue them up in that case. self.pending_promo_codes: List[str] = [] self.last_in_game_ad_remove_message_show_time: Optional[float] = None self.log_have_new = False self.log_upload_timer_started = False self._config: Optional[ba.AppConfig] = None self.printed_live_object_warning = False self.last_post_purchase_message_time: Optional[float] = None # We include this extra hash with shared input-mapping names so # that we don't share mappings between differently-configured # systems. For instance, different android devices may give different # key values for the same controller type so we keep their mappings # distinct. self.input_map_hash: Optional[str] = None # Co-op Campaigns. self.campaigns: Dict[str, ba.Campaign] = {} # Server Mode. self.server: Optional[ba.ServerController] = None # Ads. self.last_ad_network = 'unknown' self.last_ad_network_set_time = time.time() self.ad_amt: Optional[float] = None self.last_ad_purpose = 'invalid' self.attempted_first_ad = False # Music. self.music = MusicController() # Language. self.language_target: Optional[_lang.AttrDict] = None self.language_merged: Optional[_lang.AttrDict] = None # Achievements. self.achievements: List[ba.Achievement] = [] self.achievements_to_display: (List[Tuple[ba.Achievement, bool]]) = [] self.achievement_display_timer: Optional[_ba.Timer] = None self.last_achievement_display_time: float = 0.0 self.achievement_completion_banner_slots: Set[int] = set() # Lobby. self.lobby_random_profile_index: int = 1 self.lobby_random_char_index_offset = random.randrange(1000) self.lobby_account_profile_device_id: Optional[int] = None # Main Menu. self.main_menu_did_initial_transition = False self.main_menu_last_news_fetch_time: Optional[float] = None # Spaz. self.spaz_appearances: Dict[str, spazappearance.Appearance] = {} self.last_spaz_turbo_warn_time: float = -99999.0 # Maps. self.maps: Dict[str, Type[ba.Map]] = {} # Gameplay. self.teams_series_length = 7 self.ffa_series_length = 24 self.coop_session_args: Dict = {} # UI. self.uicontroller: Optional[ba.UIController] = None self.main_menu_window: Optional[_ba.Widget] = None # FIXME: Kill this. self.window_states: Dict = {} # FIXME: Kill this. self.windows: Dict = {} # FIXME: Kill this. self.main_window: Optional[str] = None # FIXME: Kill this. self.main_menu_selection: Optional[str] = None # FIXME: Kill this. self.have_party_queue_window = False self.quit_window: Any = None self.dismiss_wii_remotes_window_call: (Optional[Callable[[], Any]]) = None self.value_test_defaults: dict = {} self.main_menu_window_refresh_check_count = 0 self.first_main_menu = True # FIXME: Move to mainmenu class. self.did_menu_intro = False # FIXME: Move to mainmenu class. self.main_menu_resume_callbacks: list = [] # Can probably go away. self.special_offer: Optional[Dict] = None self.league_rank_cache: Dict = {} self.tournament_info: Dict = {} self.account_tournament_list: Optional[Tuple[int, List[str]]] = None self.ping_thread_count = 0 self.invite_confirm_windows: List[Any] = [] # FIXME: Don't use Any. self.store_layout: Optional[Dict[str, List[Dict[str, Any]]]] = None self.store_items: Optional[Dict[str, Dict]] = None self.pro_sale_start_time: Optional[int] = None self.pro_sale_start_val: Optional[int] = None self.party_window: Any = None # FIXME: Don't use Any. self.title_color = (0.72, 0.7, 0.75) self.heading_color = (0.72, 0.7, 0.75) self.infotextcolor = (0.7, 0.9, 0.7) self.uicleanupchecks: List[UICleanupCheck] = [] self.uiupkeeptimer: Optional[ba.Timer] = None self.delegate: Optional[ba.AppDelegate] = None # A few shortcuts. self.small_ui = env['interface_type'] == 'small' self.med_ui = env['interface_type'] == 'medium' self.large_ui = env['interface_type'] == 'large' self.toolbars = env.get('toolbar_test', True)
import time import os import _thread from serverData import serverdata from file_handle import OpenJson import _ba # pylint: disable=import-error if TYPE_CHECKING: pass PLAYERS_DATA_PATH = os.path.join( _ba.env()["python_directory_user"], "playersData" + os.sep ) class CacheData: # pylint: disable=too-few-public-methods """Stores the cache data.""" roles: dict = {} data: dict = {} custom: dict = {} whitelist: list[str] = [] def get_info(account_id: str) -> dict | None: """Returns the information about player.
from __future__ import annotations from typing import TYPE_CHECKING from dataclasses import dataclass, field import os import datetime import threading import setting import _ba if TYPE_CHECKING: pass SETTINGS = setting.get_settings_data() SERVER_DATA_PATH = os.path.join(_ba.env()["python_directory_user"], "serverData" + os.sep) if SETTINGS["discordbot"]["enable"]: from features import discord_bot @dataclass class RecentLogs: """Saves the recent logs.""" chats: list[str] = field(default_factory=list) joinlog: list[str] = field(default_factory=list) cmndlog: list[str] = field(default_factory=list) misclogs: list[str] = field(default_factory=list)
def on_launch(self) -> None: """Runs after the app finishes bootstrapping. (internal)""" # FIXME: Break this up. # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-locals # pylint: disable=cyclic-import from ba import _apputils from ba import _appconfig from ba.ui import UIController, ui_upkeep from ba import _achievement from ba import _map from ba import _meta from ba import _music from ba import _campaign from bastd import appdelegate from bastd import maps as stdmaps from bastd.actor import spazappearance from ba._enums import TimeType cfg = self.config self.delegate = appdelegate.AppDelegate() self.uicontroller = UIController() _achievement.init_achievements() spazappearance.register_appearances() _campaign.init_campaigns() if _ba.env()['platform'] == 'android': self.music_player_type = _music.InternalMusicPlayer elif _ba.env()['platform'] == 'mac' and hasattr( _ba, 'mac_music_app_init'): self.music_player_type = _music.MacMusicAppMusicPlayer # FIXME: This should not be hard-coded. for maptype in [ stdmaps.HockeyStadium, stdmaps.FootballStadium, stdmaps.Bridgit, stdmaps.BigG, stdmaps.Roundabout, stdmaps.MonkeyFace, stdmaps.ZigZag, stdmaps.ThePad, stdmaps.DoomShroom, stdmaps.LakeFrigid, stdmaps.TipTop, stdmaps.CragCastle, stdmaps.TowerD, stdmaps.HappyThoughts, stdmaps.StepRightUp, stdmaps.Courtyard, stdmaps.Rampage ]: _map.register_map(maptype) if self.debug_build: _apputils.suppress_debug_reports() # IMPORTANT - if tweaking UI stuff, you need to make sure it behaves # for small, medium, and large UI modes. (doesn't run off screen, etc). # Set these to 1 to test with different sizes. Generally small is used # on phones, medium is used on tablets, and large is on desktops or # large tablets. # Kick off our periodic UI upkeep. # FIXME: Can probably kill this if we do immediate UI death checks. self.uiupkeeptimer = _ba.Timer(2.6543, ui_upkeep, timetype=TimeType.REAL, repeat=True) if bool(False): # force-test small UI self.small_ui = True self.med_ui = False with _ba.Context('ui'): _ba.pushcall(lambda: _ba.screenmessage( 'FORCING SMALL UI FOR TESTING', color=(1, 0, 1), log=True)) if bool(False): # force-test medium UI self.small_ui = False self.med_ui = True with _ba.Context('ui'): _ba.pushcall(lambda: _ba.screenmessage( 'FORCING MEDIUM UI FOR TESTING', color= (1, 0, 1), log=True)) if bool(False): # force-test large UI self.small_ui = False self.med_ui = False with _ba.Context('ui'): _ba.pushcall(lambda: _ba.screenmessage( 'FORCING LARGE UI FOR TESTING', color=(1, 0, 1), log=True)) # If there's a leftover log file, attempt to upload # it to the server and/or get rid of it. _apputils.handle_leftover_log_file() try: _apputils.handle_leftover_log_file() except Exception: from ba import _error _error.print_exception('Error handling leftover log file') # Notify the user if we're using custom system scripts. # FIXME: This no longer works since sys-scripts is an absolute path; # need to just add a proper call to query this. # if env['system_scripts_directory'] != 'data/scripts': # ba.screenmessage("Using custom system scripts...", # color=(0, 1, 0)) # Only do this stuff if our config file is healthy so we don't # overwrite a broken one or whatnot and wipe out data. if not self.config_file_healthy: if self.platform in ('mac', 'linux', 'windows'): from bastd.ui import configerror configerror.ConfigErrorWindow() return # For now on other systems we just overwrite the bum config. # At this point settings are already set; lets just commit them # to disk. _appconfig.commit_app_config(force=True) # If we're using a non-default playlist, lets go ahead and get our # music-player going since it may hitch (better while we're faded # out than later). try: if ('Soundtrack' in cfg and cfg['Soundtrack'] not in ['__default__', 'Default Soundtrack']): _music.get_music_player() except Exception: from ba import _error _error.print_exception('error prepping music-player') launch_count = cfg.get('launchCount', 0) launch_count += 1 # So we know how many times we've run the game at various # version milestones. for key in ('lc14173', 'lc14292'): cfg.setdefault(key, launch_count) # Debugging - make note if we're using the local test server so we # don't accidentally leave it on in a release. # FIXME - move this to native layer. server_addr = _ba.get_master_server_address() if 'localhost' in server_addr: _ba.timer(2.0, lambda: _ba.screenmessage("Note: using local server", (1, 1, 0), log=True), timetype=TimeType.REAL) elif 'test' in server_addr: _ba.timer( 2.0, lambda: _ba.screenmessage("Note: using test server-module", (1, 1, 0), log=True), timetype=TimeType.REAL) cfg['launchCount'] = launch_count cfg.commit() # Run a test in a few seconds to see if we should pop up an existing # pending special offer. def check_special_offer() -> None: from bastd.ui import specialoffer config = self.config if ('pendingSpecialOffer' in config and _ba.get_public_login_id() == config['pendingSpecialOffer']['a']): self.special_offer = config['pendingSpecialOffer']['o'] specialoffer.show_offer() if self.subplatform != 'headless': _ba.timer(3.0, check_special_offer, timetype=TimeType.REAL) # Start scanning for things exposed via ba_meta. _meta.start_scan() # Auto-sign-in to a local account in a moment if we're set to. def do_auto_sign_in() -> None: if self.subplatform == 'headless': _ba.sign_in('Local') elif cfg.get('Auto Account State') == 'Local': _ba.sign_in('Local') _ba.pushcall(do_auto_sign_in) self.ran_on_launch = True
def __init__(self) -> None: """(internal) Do not instantiate this class; use ba.app to access the single shared instance. """ # pylint: disable=too-many-statements from ba._music import MusicSubsystem from ba._ui import UI # Config. self.config_file_healthy = False # This is incremented any time the app is backgrounded/foregrounded; # can be a simple way to determine if network data should be # refreshed/etc. self.fg_state = 0 self._env = _ba.env() self.protocol_version: int = self._env['protocol_version'] assert isinstance(self.protocol_version, int) self.toolbar_test: bool = self._env['toolbar_test'] assert isinstance(self.toolbar_test, bool) self.demo_mode: bool = self._env['demo_mode'] assert isinstance(self.demo_mode, bool) self.arcade_mode: bool = self._env['arcade_mode'] assert isinstance(self.arcade_mode, bool) self.headless_build: bool = self._env['headless_build'] assert isinstance(self.headless_build, bool) # Plugins. self.potential_plugins: List[ba.PotentialPlugin] = [] self.active_plugins: Dict[str, ba.Plugin] = {} # Misc. self.default_language = self._get_default_language() self.metascan: Optional[_meta.ScanResults] = None self.tips: List[str] = [] self.stress_test_reset_timer: Optional[ba.Timer] = None self.last_ad_completion_time: Optional[float] = None self.last_ad_was_short = False self.did_weak_call_warning = False self.ran_on_app_launch = False # If we try to run promo-codes due to launch-args/etc we might # not be signed in yet; go ahead and queue them up in that case. self.pending_promo_codes: List[str] = [] self.last_in_game_ad_remove_message_show_time: Optional[float] = None self.log_have_new = False self.log_upload_timer_started = False self._config: Optional[ba.AppConfig] = None self.printed_live_object_warning = False self.last_post_purchase_message_time: Optional[float] = None # We include this extra hash with shared input-mapping names so # that we don't share mappings between differently-configured # systems. For instance, different android devices may give different # key values for the same controller type so we keep their mappings # distinct. self.input_map_hash: Optional[str] = None # Co-op Campaigns. self.campaigns: Dict[str, ba.Campaign] = {} # Server Mode. self.server: Optional[ba.ServerController] = None # Ads. self.last_ad_network = 'unknown' self.last_ad_network_set_time = time.time() self.ad_amt: Optional[float] = None self.last_ad_purpose = 'invalid' self.attempted_first_ad = False # Music. self.music = MusicSubsystem() # Language. self.language_target: Optional[_lang.AttrDict] = None self.language_merged: Optional[_lang.AttrDict] = None # Achievements. self.achievements: List[ba.Achievement] = [] self.achievements_to_display: (List[Tuple[ba.Achievement, bool]]) = [] self.achievement_display_timer: Optional[_ba.Timer] = None self.last_achievement_display_time: float = 0.0 self.achievement_completion_banner_slots: Set[int] = set() # Lobby. self.lobby_random_profile_index: int = 1 self.lobby_random_char_index_offset = random.randrange(1000) self.lobby_account_profile_device_id: Optional[int] = None # Main Menu. self.main_menu_did_initial_transition = False self.main_menu_last_news_fetch_time: Optional[float] = None # Spaz. self.spaz_appearances: Dict[str, spazappearance.Appearance] = {} self.last_spaz_turbo_warn_time: float = -99999.0 # Maps. self.maps: Dict[str, Type[ba.Map]] = {} # Gameplay. self.teams_series_length = 7 self.ffa_series_length = 24 self.coop_session_args: Dict = {} # UI. self.ui = UI() self.value_test_defaults: dict = {} self.first_main_menu = True # FIXME: Move to mainmenu class. self.did_menu_intro = False # FIXME: Move to mainmenu class. self.main_menu_window_refresh_check_count = 0 # FIXME: Mv to mainmenu. self.main_menu_resume_callbacks: list = [] # Can probably go away. self.special_offer: Optional[Dict] = None self.league_rank_cache: Dict = {} self.tournament_info: Dict = {} self.account_tournament_list: Optional[Tuple[int, List[str]]] = None self.ping_thread_count = 0 self.invite_confirm_windows: List[Any] = [] # FIXME: Don't use Any. self.store_layout: Optional[Dict[str, List[Dict[str, Any]]]] = None self.store_items: Optional[Dict[str, Dict]] = None self.pro_sale_start_time: Optional[int] = None self.pro_sale_start_val: Optional[int] = None self.delegate: Optional[ba.AppDelegate] = None
def flush(self) -> None: """Flush the file.""" self._original.flush() def isatty(self) -> bool: """Are we a terminal?""" return self._original.isatty() sys.stdout = _BAConsoleRedirect(sys.stdout, _ba.print_stdout) # type: ignore sys.stderr = _BAConsoleRedirect(sys.stderr, _ba.print_stderr) # type: ignore # Let's lookup mods first (so users can do whatever they want). # and then our bundled scripts last (don't want to encourage dists # overriding proper python functionality) sys.path.insert(0, _ba.env()['python_directory_user']) sys.path.append(_ba.env()['python_directory_app']) sys.path.append(_ba.env()['python_directory_app_site']) # Tell Python to not handle SIGINT itself (it normally generates # KeyboardInterrupts which make a mess; we want to do a simple # clean exit). We capture interrupts per-platform in the C++ layer. # I tried creating a handler in Python but it seemed to often have # a delay of up to a second before getting called. (not a huge deal # but I'm picky). signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling. # ..though it turns out we need to set up our C signal handling AFTER # we've told Python to disable its own; otherwise (on Mac at least) it # wipes out our existing C handler. _ba.setup_sigint()
def _ballistica_bootstrap() -> object: import sys import signal import _ba import threading class _BAConsoleRedirect: def __init__(self, original: TextIO, call: Callable[[str], None]) -> None: self._lock = threading.Lock() self._linebits: List[str] = [] self._original = original self._call = call self._pending_ship = False def write(self, sval: Any) -> None: """Override standard stdout write.""" self._call(sval) # Now do logging: # Add it to our accumulated line. # If the message ends in a newline, we can ship it # immediately as a log entry. Otherwise, schedule a ship # next cycle (if it hasn't yet at that point) so that we # can accumulate subsequent prints. # (so stuff like print('foo', 123, 'bar') will ship as one entry) with self._lock: self._linebits.append(sval) if sval.endswith('\n'): self._shiplog() else: _ba.pushcall(self._shiplog, from_other_thread=True, suppress_other_thread_warning=True) def _shiplog(self) -> None: with self._lock: line = ''.join(self._linebits) if not line: return self._linebits = [] # Log messages aren't expected to have trailing newlines. if line.endswith('\n'): line = line[:-1] _ba.log(line, to_stdout=False) def flush(self) -> None: """Flush the file.""" self._original.flush() def isatty(self) -> bool: """Are we a terminal?""" return self._original.isatty() sys.stdout = _BAConsoleRedirect( # type: ignore sys.stdout, _ba.print_stdout) sys.stderr = _BAConsoleRedirect( # type: ignore sys.stderr, _ba.print_stderr) # Let's lookup mods first (so users can do whatever they want). # and then our bundled scripts last (don't want to encourage dists # overriding proper python functionality) sys.path.insert(0, _ba.env()['python_directory_user']) sys.path.append(_ba.env()['python_directory_app']) sys.path.append(_ba.env()['python_directory_app_site']) # Tell Python to not handle SIGINT itself (it normally generates # KeyboardInterrupts which make a mess; we want to do a simple # clean exit). We capture interrupts per-platform in the C++ layer. # I tried creating a handler in Python but it seemed to often have # a delay of up to a second before getting called. (not a huge deal # but I'm picky). signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling. # ..though it turns out we need to set up our C signal handling AFTER # we've told Python to disable its own; otherwise (on Mac at least) it # wipes out our existing C handler. _ba.setup_sigint() # Sanity check: we should always be run in UTF-8 mode. if sys.flags.utf8_mode != 1: print('ERROR: Python\'s UTF-8 mode is not set.' ' This will likely result in errors.') # FIXME: I think we should init Python in the main thread, which should # also avoid these issues. (and also might help us play better with # Python debuggers?) # Gloriously hacky workaround here: # Our 'main' Python thread is the game thread (not the app's main # thread) which means it has a small stack compared to the main # thread (at least on apple). Sadly it turns out this causes the # debug build of Python to blow its stack immediately when doing # some big imports. # Normally we'd just give the game thread the same stack size as # the main thread and that'd be the end of it. However # we're using std::threads which it turns out have no way to set # the stack size (as of fall '19). Grumble. # # However python threads *can* take custom stack sizes. # (and it appears they might use the main thread's by default?..) # ...so as a workaround in the debug version, we can run problematic # heavy imports here in another thread and all is well. # If we ever see stack overflows in our release build we'll have # to take more drastic measures like switching from std::threads # to pthreads. if _ba.env()['debug_build']: def _thread_func() -> None: # pylint: disable=unused-import import json import urllib.request testthread = threading.Thread(target=_thread_func) testthread.start() testthread.join() # Now spin up our App instance, store it on both _ba and ba, # and return it to the C++ layer. # noinspection PyProtectedMember from ba._app import App import ba app = App() _ba.app = app ba.app = app return app
from ba._activity import Activity from ba._music import setmusic, MusicType # False-positive from pylint due to our class-generics-filter. from ba._player import EmptyPlayer # pylint: disable=W0611 from ba._team import EmptyTeam # pylint: disable=W0611 from typing import Any, Dict, Optional from ba._lobby import JoinInfo from ba import _activitytypes as ba_actypes from ba._activitytypes import * import urllib.request import custom_hooks import datetime #variables our_settings = setting.get_settings_data() # where our stats file and pretty html output will go base_path = os.path.join(_ba.env()['python_directory_user'], "stats" + os.sep) statsfile = base_path + 'stats.json' htmlfile = base_path + 'stats_page.html' table_style = "{width:100%;border: 3px solid black;border-spacing: 5px;border-collapse:collapse;text-align:center;background-color:#fff}" heading_style = "{border: 3px solid black;text-align:center;}" html_start = f'''<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Test Server</title> <style>table{table_style} th{heading_style}</style> </head> <body> <h3 style="text-align:center">Top 200 Players </h3> <table border=1> <tr>
def __init__(self) -> None: """(internal) Do not instantiate this class; use ba.app to access the single shared instance. """ # pylint: disable=too-many-statements self.state = self.State.LAUNCHING # Config. self.config_file_healthy = False # This is incremented any time the app is backgrounded/foregrounded; # can be a simple way to determine if network data should be # refreshed/etc. self.fg_state = 0 self._env = _ba.env() self.protocol_version: int = self._env['protocol_version'] assert isinstance(self.protocol_version, int) self.toolbar_test: bool = self._env['toolbar_test'] assert isinstance(self.toolbar_test, bool) self.demo_mode: bool = self._env['demo_mode'] assert isinstance(self.demo_mode, bool) self.arcade_mode: bool = self._env['arcade_mode'] assert isinstance(self.arcade_mode, bool) self.headless_mode: bool = self._env['headless_mode'] assert isinstance(self.headless_mode, bool) self.iircade_mode: bool = self._env['iircade_mode'] assert isinstance(self.iircade_mode, bool) self.allow_ticket_purchases: bool = not self.iircade_mode # Misc. self.tips: List[str] = [] self.stress_test_reset_timer: Optional[ba.Timer] = None self.did_weak_call_warning = False self.log_have_new = False self.log_upload_timer_started = False self._config: Optional[ba.AppConfig] = None self.printed_live_object_warning = False # We include this extra hash with shared input-mapping names so # that we don't share mappings between differently-configured # systems. For instance, different android devices may give different # key values for the same controller type so we keep their mappings # distinct. self.input_map_hash: Optional[str] = None # Co-op Campaigns. self.campaigns: Dict[str, ba.Campaign] = {} # Server Mode. self.server: Optional[ba.ServerController] = None self.meta = MetadataSubsystem() self.accounts = AccountSubsystem() self.plugins = PluginSubsystem() self.music = MusicSubsystem() self.lang = LanguageSubsystem() self.ach = AchievementSubsystem() self.ui = UISubsystem() self.ads = AdsSubsystem() self.net = NetworkSubsystem() # Lobby. self.lobby_random_profile_index: int = 1 self.lobby_random_char_index_offset = random.randrange(1000) self.lobby_account_profile_device_id: Optional[int] = None # Main Menu. self.main_menu_did_initial_transition = False self.main_menu_last_news_fetch_time: Optional[float] = None # Spaz. self.spaz_appearances: Dict[str, spazappearance.Appearance] = {} self.last_spaz_turbo_warn_time: float = -99999.0 # Maps. self.maps: Dict[str, Type[ba.Map]] = {} # Gameplay. self.teams_series_length = 7 self.ffa_series_length = 24 self.coop_session_args: Dict = {} self.value_test_defaults: dict = {} self.first_main_menu = True # FIXME: Move to mainmenu class. self.did_menu_intro = False # FIXME: Move to mainmenu class. self.main_menu_window_refresh_check_count = 0 # FIXME: Mv to mainmenu. self.main_menu_resume_callbacks: list = [] # Can probably go away. self.special_offer: Optional[Dict] = None self.ping_thread_count = 0 self.invite_confirm_windows: List[Any] = [] # FIXME: Don't use Any. self.store_layout: Optional[Dict[str, List[Dict[str, Any]]]] = None self.store_items: Optional[Dict[str, Dict]] = None self.pro_sale_start_time: Optional[int] = None self.pro_sale_start_val: Optional[int] = None self.delegate: Optional[ba.AppDelegate] = None
def __init__(self): ba.screenmessage('Server connector by Mr.Smoothy', color=(0, 1, 0)) if _ba.env().get("build_number",0) >= 20258: enableeeeee() else:print("only work on 1.5.29 and above ")