diff --git a/.efrocachemap b/.efrocachemap index c0efec69..73fb5628 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3932,26 +3932,26 @@ "assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450", "assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e", "assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f", - "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/61/c1/35c60d99bf4867eada2b7ad0dc19", - "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9c/64/f43f7baf75512685ac0dce8e0f1c", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ce/75/e25f75557b05b0de2ab4a281c0de", - "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/32/c6/4503e9fd3e6d7a27e7e1f32f8542", - "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/6b/b7/47e4719f2aef688e62ad2f416406", - "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/93/85/c5c09d5fe4e13655ccb021c44d5a", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/42/7f/46fd7611f88f659d27e827a58c8f", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3e/02/5e9b6ffdc3e242e1ddbcc67c027a", - "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/dc/6d/0a0a41762f27f0f8cdd2a7d2c033", - "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/1d/37/11d275e939854da3e1488360d1fd", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/63/26/e9e64910b7e242129c5006234116", - "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8b/9c/edb852a4d5c7304e39e9618bca93", - "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/22/fb/29e80f93d3899abc57854b3dbe52", - "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c7/fc/4e3c1cfce367e5ace09e5bcbe9fc", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9f/ee/ec4ed4396a600c69202566f2713d", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6e/1c/0d1f8e451d24591b27f15f26a827", - "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d1/79/d3cb45d123726fac04611ce103f9", - "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/70/2a/a1db2d042bbe3c319b2a4bc6c395", - "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f5/8c/bd7cb4286e0dadf7b29211a95560", - "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/4c/62/5797c0590d0128637c419f74cb67", + "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/76/e4/20e36d3f74b4aba6dfbf6c1e7a3c", + "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9f/3b/46c10e31faf30642719e8d051f51", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3c/a7/3ca43775dfe81d796bfa38473303", + "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/ec/c4ebc76cd5f17f974874bcfc7733", + "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/98/f3/55d5e976bf4a5e59b7fb0e1a9049", + "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9d/cf/1abae2d413903ac980e3cfd6e0e3", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/1c/3c/161096b136ac519eaf7ead0d32a1", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/13/1c/c72c01e8e7ed072b2452142fca77", + "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d6/9d/e4a6554a9712cda7840511219df2", + "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/ca/e686c76cc102db57c4df20a0db04", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9a/59/c272db6020c424a96ce01a4f5d56", + "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8a/87/7bbc845d3559609d1b5a411d12e2", + "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5b/77/f45ffd7e36bf3e86d8c8c01c5b72", + "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/83/97/446ffe1f9e6a762d8f006b264654", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2b/29/785e06a7b25ed5b55a9d0e93c6bf", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/ef/3cade90a38e855c8dc9c15295c32", + "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d6/c9/3e3a70a888a785a4f0e9dd483a1f", + "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/8a/1b/4fdf49299324c76e637777ea7e4a", + "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/57/48/fab31e4ac7d9f846245ebaf6fe0a", + "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/e8/b0/841559924243fcada9d7d1cb58de", "build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/bf/393694ea67f3d590dd2706c9955e", "build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/78/cb/bb9ae4f896f862074057c8e36e1d", "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ae/bd/39d7b885f7f01e81d0e96f0f85ce", @@ -3960,12 +3960,12 @@ "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/52/d9/563a6949d2c4db5a915c54460fbc", "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d0/6a/42fe8d2e34f95e1b3282e8422344", "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/50/cf/bad44b07a4022aee3001002086b5", - "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/bd/bc/1e305f3aafb660b0f45256fd07d1", - "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ea/0e/42b6ec781850c69e6bab8e1b14f6", - "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/92/84/7e78c73d0c91d45f92f795155d5f", - "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b9/4e/9fe6ea82f278ace93e724253df84", - "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/15/a4/7e2d2dbc870b286358d34b6e6cee", - "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e3/10/4e2baf04c93a5bc632bdbd7e92f6", - "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/23/f4/c55e363bb00319971d21b2382431", - "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/27/2f/c8895ca79eb249a959578a203ff7" + "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/38/dc/ac069b31a566df1b738adae005b6", + "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c9/96/a75c9739a5cccca60cd74cea22ca", + "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3c/17/f1b4bb490383d9dc43714f39c77b", + "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c2/e0/32f9701738320d592692e9b30869", + "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/43/d779605636305318e68d4eaef10a", + "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/28/b2/7ce9803bf834bf90f3d5927c323e", + "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/be/e4/e37e38122257176c923475c4be83", + "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/eb/51/2ca27968b65c54abe198ff49f164" } \ No newline at end of file diff --git a/assets/src/ba_data/python/ba/_servermode.py b/assets/src/ba_data/python/ba/_servermode.py index a4decb9b..ec540d3b 100644 --- a/assets/src/ba_data/python/ba/_servermode.py +++ b/assets/src/ba_data/python/ba/_servermode.py @@ -335,8 +335,16 @@ class ServerController: _ba.set_public_party_stats_url(self._config.stats_url) _ba.set_public_party_enabled(self._config.party_is_public) - # And here we go. - _ba.new_host_session(sessiontype) + # And here.. we.. go. + if self._config.stress_test_players is not None: + # Special case: run a stress test. + from ba.internal import run_stress_test + run_stress_test(playlist_type='Random', + playlist_name='__default__', + player_count=self._config.stress_test_players, + round_duration=30) + else: + _ba.new_host_session(sessiontype) # Run an access check if we're trying to make a public party. if not self._ran_access_check and self._config.party_is_public: diff --git a/assets/src/server/ballisticacore_server.py b/assets/src/server/ballisticacore_server.py index f7e0309c..632d0953 100755 --- a/assets/src/server/ballisticacore_server.py +++ b/assets/src/server/ballisticacore_server.py @@ -116,8 +116,11 @@ class ServerManagerApp: self._running = True dbgstr = 'debug' if __debug__ else 'opt' - print(f'{Clr.CYN}{Clr.BLD}BallisticaCore server manager {VERSION_STR}' - f' starting up ({dbgstr} mode)...{Clr.RST}') + print( + f'{Clr.CYN}{Clr.BLD}BallisticaCore server manager {VERSION_STR}' + f' starting up ({dbgstr} mode)...{Clr.RST}', + file=sys.stderr, + flush=True) # Python will handle SIGINT for us (as KeyboardInterrupt) but we # need to register a SIGTERM handler so we have a chance to clean @@ -136,11 +139,15 @@ class ServerManagerApp: def _postrun(self) -> None: """Common code at the end of any run.""" - print(f'{Clr.CYN}Server manager shutting down...{Clr.RST}') + print(f'{Clr.CYN}Server manager shutting down...{Clr.RST}', + file=sys.stderr, + flush=True) assert self._subprocess_thread is not None if self._subprocess_thread.is_alive(): - print(f'{Clr.CYN}Waiting for subprocess exit...{Clr.RST}') + print(f'{Clr.CYN}Waiting for subprocess exit...{Clr.RST}', + file=sys.stderr, + flush=True) # Mark ourselves as shutting down and wait for the process to wrap up. self._done = True @@ -181,9 +188,12 @@ class ServerManagerApp: self._prerun() # Print basic usage info for interactive mode. - print(f"{Clr.CYN}Interactive mode enabled; use the 'mgr' object" - f' to interact with the server.\n' - f"Type 'help(mgr)' for more information.{Clr.RST}") + print( + f"{Clr.CYN}Interactive mode enabled; use the 'mgr' object" + f' to interact with the server.\n' + f"Type 'help(mgr)' for more information.{Clr.RST}", + file=sys.stderr, + flush=True) context = {'__name__': '__console__', '__doc__': None, 'mgr': self} @@ -200,8 +210,11 @@ class ServerManagerApp: # left in limbo with our process thread still running. pass except BaseException as exc: - print(f'{Clr.SRED}Unexpected interpreter exception:' - f' {exc} ({type(exc)}){Clr.RST}') + print( + f'{Clr.SRED}Unexpected interpreter exception:' + f' {exc} ({type(exc)}){Clr.RST}', + file=sys.stderr, + flush=True) self._postrun() @@ -450,16 +463,23 @@ class ServerManagerApp: if strict: raise CleanError( f'Error loading config file:\n{exc}') from exc - print(f'{Clr.RED}Error loading config file:\n{exc}.{Clr.RST}') + print(f'{Clr.RED}Error loading config file:\n{exc}.{Clr.RST}', + file=sys.stderr, + flush=True) if trynum == maxtries - 1: - print(f'{Clr.RED}Max-tries reached; giving up.' - f' Existing config values will be used.{Clr.RST}') + print( + f'{Clr.RED}Max-tries reached; giving up.' + f' Existing config values will be used.{Clr.RST}', + file=sys.stderr, + flush=True) break print( f'{Clr.CYN}Please correct the error.' f' Will re-attempt load in {retry_seconds}' - f' seconds. (attempt {trynum+1} of {maxtries-1}).{Clr.RST}' - ) + f' seconds. (attempt {trynum+1} of' + f' {maxtries-1}).{Clr.RST}', + file=sys.stderr, + flush=True) time.sleep(1) @@ -481,9 +501,12 @@ class ServerManagerApp: # missing. if not self._user_provided_config_path: if print_confirmation: - print(f'{Clr.YLW}Default config file not found' - f' (\'{self._config_path}\'); using default' - f' settings.{Clr.RST}') + print( + f'{Clr.YLW}Default config file not found' + f' (\'{self._config_path}\'); using default' + f' settings.{Clr.RST}', + file=sys.stderr, + flush=True) self._config_mtime = None self._last_config_mtime_check_time = time.time() return ServerConfig() @@ -509,7 +532,9 @@ class ServerManagerApp: out = ServerConfig() if print_confirmation: - print(f'{Clr.CYN}Valid server config file loaded.{Clr.RST}') + print(f'{Clr.CYN}Valid server config file loaded.{Clr.RST}', + file=sys.stderr, + flush=True) return out def _enable_tab_completion(self, locs: Dict) -> None: @@ -552,7 +577,9 @@ class ServerManagerApp: # slight behavior tweaks. Hmm; should this be an argument instead? os.environ['BA_SERVER_WRAPPER_MANAGED'] = '1' - print(f'{Clr.CYN}Launching server subprocess...{Clr.RST}') + print(f'{Clr.CYN}Launching server subprocess...{Clr.RST}', + file=sys.stderr, + flush=True) binary_name = ('ballisticacore_headless.exe' if os.name == 'nt' else './ballisticacore_headless') assert self._ba_root_path is not None @@ -663,7 +690,9 @@ class ServerManagerApp: # alive. if (self._subprocess_force_kill_time is not None and time.time() > self._subprocess_force_kill_time): - print(f'{Clr.CYN}Force-killing subprocess...{Clr.RST}') + print(f'{Clr.CYN}Force-killing subprocess...{Clr.RST}', + file=sys.stderr, + flush=True) break # Watch for the server process exiting.. @@ -679,8 +708,11 @@ class ServerManagerApp: self._should_report_subprocess_error = True clr = Clr.CYN if code == 0 else Clr.RED - print(f'{clr}Server subprocess exited' - f' with code {code}.{Clr.RST}') + print( + f'{clr}Server subprocess exited' + f' with code {code}.{Clr.RST}', + file=sys.stderr, + flush=True) self._reset_subprocess_vars() # Avoid super fast death loops. @@ -709,8 +741,11 @@ class ServerManagerApp: else: mtime = None if mtime != self._config_mtime: - print(f'{Clr.CYN}Config-file change detected;' - f' requesting immediate restart.{Clr.RST}') + print( + f'{Clr.CYN}Config-file change detected;' + f' requesting immediate restart.{Clr.RST}', + file=sys.stderr, + flush=True) self.restart(immediate=True) self._subprocess_sent_config_auto_restart = True @@ -724,10 +759,13 @@ class ServerManagerApp: if (minutes_since_launch > clean_exit_minutes and not self._subprocess_sent_clean_exit): opname = 'restart' if self._auto_restart else 'shutdown' - print(f'{Clr.CYN}clean_exit_minutes' - f' ({clean_exit_minutes})' - f' elapsed; requesting soft' - f' {opname}.{Clr.RST}') + print( + f'{Clr.CYN}clean_exit_minutes' + f' ({clean_exit_minutes})' + f' elapsed; requesting soft' + f' {opname}.{Clr.RST}', + file=sys.stderr, + flush=True) if self._auto_restart: self.restart(immediate=False) else: @@ -744,10 +782,13 @@ class ServerManagerApp: if (minutes_since_launch > unclean_exit_minutes and not self._subprocess_sent_unclean_exit): opname = 'restart' if self._auto_restart else 'shutdown' - print(f'{Clr.CYN}unclean_exit_minutes' - f' ({unclean_exit_minutes})' - f' elapsed; requesting immediate' - f' {opname}.{Clr.RST}') + print( + f'{Clr.CYN}unclean_exit_minutes' + f' ({unclean_exit_minutes})' + f' elapsed; requesting immediate' + f' {opname}.{Clr.RST}', + file=sys.stderr, + flush=True) if self._auto_restart: self.restart(immediate=True) else: @@ -768,7 +809,9 @@ class ServerManagerApp: if self._subprocess is None: return - print(f'{Clr.CYN}Stopping subprocess...{Clr.RST}') + print(f'{Clr.CYN}Stopping subprocess...{Clr.RST}', + file=sys.stderr, + flush=True) # First, ask it nicely to die and give it a moment. # If that doesn't work, bring down the hammer. @@ -778,7 +821,9 @@ class ServerManagerApp: except subprocess.TimeoutExpired: self._subprocess.kill() self._reset_subprocess_vars() - print(f'{Clr.CYN}Subprocess stopped.{Clr.RST}') + print(f'{Clr.CYN}Subprocess stopped.{Clr.RST}', + file=sys.stderr, + flush=True) def main() -> None: diff --git a/docs/ba_module.md b/docs/ba_module.md index 1fb63759..5336c9bd 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -
This page documents the Python classes and functions in the 'ba' module, which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!