mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-10-16 12:02:51 +00:00
Initial commit
This commit is contained in:
parent
bc49523c99
commit
44d606cce7
1929 changed files with 612166 additions and 0 deletions
912
bombsquad_server
Normal file
912
bombsquad_server
Normal file
|
|
@ -0,0 +1,912 @@
|
||||||
|
#!/usr/bin/env -S python3.10 -O
|
||||||
|
|
||||||
|
# Released under the MIT License. See LICENSE for details.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
import os,signal,subprocess, sys, time, _thread, logging, platform, shutil, json
|
||||||
|
from pathlib import Path
|
||||||
|
from threading import Lock, Thread, current_thread, Timer
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
from nbstreamreader import NonBlockingStreamReader as NBSR
|
||||||
|
from datetime import datetime
|
||||||
|
#import requests
|
||||||
|
|
||||||
|
ERROR_LOGGING=False
|
||||||
|
|
||||||
|
def migrate_to_aarch():
|
||||||
|
maps = ["BridgitMash.so","FloatingIsland.so","InTheAir.so"]
|
||||||
|
games = ["CanonFight.so","DuelElimination.so","FlappyBird.so","LaserTracer.so","MonkeyClimb.so","OneNightNoStand.so","RealSoccer.so",
|
||||||
|
"SquidRace.so","StumbleRace.so","SubwayRun.so","UFOAttackGame.so"]
|
||||||
|
features = ["StumbledScoreScreen.so"]
|
||||||
|
tools = ["corelib.so"]
|
||||||
|
root = os.path.realpath(".")+"/dist/ba_root"
|
||||||
|
for map in maps:
|
||||||
|
shutil.copy(root+"/mods/aarch64/"+map,root+'/mods/maps/'+map)
|
||||||
|
for game in games:
|
||||||
|
shutil.copyfile(root+"/mods/aarch64/"+game,root+'/mods/games/'+game)
|
||||||
|
for f in features:
|
||||||
|
shutil.copyfile(root+"/mods/aarch64/"+f,root+'/mods/features/'+f)
|
||||||
|
for t in tools:
|
||||||
|
shutil.copyfile(root+"/mods/aarch64/"+t,root+'/mods/tools/'+t)
|
||||||
|
with open(".we_are_good","w") as f:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# by default we have x86_64 setup
|
||||||
|
# if we found aarch64 system copy required files
|
||||||
|
if platform.processor() == 'aarch64':
|
||||||
|
print("We are on aarch64 system")
|
||||||
|
if os.path.exists(".we_are_good"):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
migrate_to_aarch()
|
||||||
|
|
||||||
|
# We make use of the bacommon and efro packages as well as site-packages
|
||||||
|
# included with our bundled Ballistica dist, so we need to add those paths
|
||||||
|
# before we import them.
|
||||||
|
sys.path += [
|
||||||
|
str(Path(Path(__file__).parent, 'dist', 'ba_data', 'python')),
|
||||||
|
str(Path(Path(__file__).parent, 'dist', 'ba_data', 'python-site-packages'))
|
||||||
|
]
|
||||||
|
|
||||||
|
from bacommon.servermanager import ServerConfig, StartServerModeCommand
|
||||||
|
from efro.dataclassio import dataclass_from_dict, dataclass_validate
|
||||||
|
from efro.error import CleanError
|
||||||
|
from efro.terminal import Clr
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing import Optional, Union
|
||||||
|
from types import FrameType
|
||||||
|
from bacommon.servermanager import ServerCommand
|
||||||
|
|
||||||
|
VERSION_STR = '1.3'
|
||||||
|
print("----------------------------------------------------------------------------------------------------------------------------------------")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
class ServerManagerApp:
|
||||||
|
""" An app which manages BallisticaCore server execution.
|
||||||
|
|
||||||
|
Handles configuring, launching, re-launching, and otherwise
|
||||||
|
managing BallisticaCore operating in server mode.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# How many seconds we wait after asking our subprocess to do an immediate
|
||||||
|
# shutdown before bringing down the hammer.
|
||||||
|
IMMEDIATE_SHUTDOWN_TIME_LIMIT = 5.0
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._config_path = 'config.yaml'
|
||||||
|
self._user_provided_config_path = False
|
||||||
|
self._config = ServerConfig()
|
||||||
|
self._ba_root_path = os.path.abspath('dist/ba_root')
|
||||||
|
self._interactive = sys.stdin.isatty()
|
||||||
|
self._wrapper_shutdown_desired = False
|
||||||
|
self._done = False
|
||||||
|
self._subprocess_commands: list[Union[str, ServerCommand]] = []
|
||||||
|
self._subprocess_commands_lock = Lock()
|
||||||
|
self._subprocess_force_kill_time: Optional[float] = None
|
||||||
|
self._auto_restart = True
|
||||||
|
self._config_auto_restart = True
|
||||||
|
self._config_mtime: Optional[float] = None
|
||||||
|
self._last_config_mtime_check_time: Optional[float] = None
|
||||||
|
self._should_report_subprocess_error = False
|
||||||
|
self._running = False
|
||||||
|
self._interpreter_start_time: Optional[float] = None
|
||||||
|
self._subprocess: Optional[subprocess.Popen[bytes]] = None
|
||||||
|
self._subprocess_launch_time: Optional[float] = None
|
||||||
|
self._subprocess_sent_config_auto_restart = False
|
||||||
|
self._subprocess_sent_clean_exit = False
|
||||||
|
self._subprocess_sent_unclean_exit = False
|
||||||
|
self._subprocess_thread: Optional[Thread] = None
|
||||||
|
self._subprocess_exited_cleanly: Optional[bool] = None
|
||||||
|
self.nbsr = None
|
||||||
|
# This may override the above defaults.
|
||||||
|
self._parse_command_line_args()
|
||||||
|
|
||||||
|
# Do an initial config-load. If the config is invalid at this point
|
||||||
|
# we can cleanly die (we're more lenient later on reloads).
|
||||||
|
self.load_config(strict=True, print_confirmation=False)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config(self) -> ServerConfig:
|
||||||
|
"""The current config for the app."""
|
||||||
|
return self._config
|
||||||
|
|
||||||
|
@config.setter
|
||||||
|
def config(self, value: ServerConfig) -> None:
|
||||||
|
dataclass_validate(value)
|
||||||
|
self._config = value
|
||||||
|
|
||||||
|
def _prerun(self) -> None:
|
||||||
|
"""Common code at the start of any run."""
|
||||||
|
|
||||||
|
# Make sure we don't call run multiple times.
|
||||||
|
if self._running:
|
||||||
|
raise RuntimeError('Already running.')
|
||||||
|
self._running = True
|
||||||
|
|
||||||
|
dbgstr = 'debug' if __debug__ else 'opt'
|
||||||
|
logging.info(f'{Clr.CYN}{Clr.BLD}ROCKY AND VORTEX OFFICIAL is {VERSION_STR}'
|
||||||
|
f' starting up in ({dbgstr} mode).{Clr.RST}')
|
||||||
|
|
||||||
|
# Python will handle SIGINT for us (as KeyboardInterrupt) but we
|
||||||
|
# need to register a SIGTERM handler so we have a chance to clean
|
||||||
|
# up our subprocess when someone tells us to die. (and avoid
|
||||||
|
# zombie processes)
|
||||||
|
signal.signal(signal.SIGTERM, self._handle_term_signal)
|
||||||
|
|
||||||
|
# During a run, we make the assumption that cwd is the dir
|
||||||
|
# containing this script, so make that so. Up until now that may
|
||||||
|
# not be the case (we support being called from any location).
|
||||||
|
os.chdir(os.path.abspath(os.path.dirname(__file__)))
|
||||||
|
|
||||||
|
# Fire off a background thread to wrangle our server binaries.
|
||||||
|
self._subprocess_thread = Thread(target=self._bg_thread_main)
|
||||||
|
self._subprocess_thread.start()
|
||||||
|
|
||||||
|
def _postrun(self) -> None:
|
||||||
|
"""Common code at the end of any run."""
|
||||||
|
logging.info(f"{Clr.RED}{Clr.BLD}Server is shutting down.. Please wait!{Clr.RST}")
|
||||||
|
|
||||||
|
assert self._subprocess_thread is not None
|
||||||
|
if self._subprocess_thread.is_alive():
|
||||||
|
logging.info(f"{Clr.RED}{Clr.BLD}Killing all subprocess safely..{Clr.RST}")
|
||||||
|
|
||||||
|
# Mark ourselves as shutting down and wait for the process to wrap up.
|
||||||
|
self._done = True
|
||||||
|
self._subprocess_thread.join()
|
||||||
|
|
||||||
|
# If there's a server error we should care about, exit the
|
||||||
|
# entire wrapper uncleanly.
|
||||||
|
if self._should_report_subprocess_error:
|
||||||
|
raise CleanError('Server subprocess exited uncleanly.')
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
"""Do the thing."""
|
||||||
|
if self._interactive:
|
||||||
|
self._run_interactive()
|
||||||
|
else:
|
||||||
|
self._run_noninteractive()
|
||||||
|
|
||||||
|
def _run_noninteractive(self) -> None:
|
||||||
|
"""Run the app loop to completion noninteractively."""
|
||||||
|
self._prerun()
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
time.sleep(1.234)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
# Gracefully bow out if we kill ourself via keyboard.
|
||||||
|
pass
|
||||||
|
except SystemExit:
|
||||||
|
# We get this from the builtin quit(), our signal handler, etc.
|
||||||
|
# Need to catch this so we can clean up, otherwise we'll be
|
||||||
|
# left in limbo with our process thread still running.
|
||||||
|
pass
|
||||||
|
self._postrun()
|
||||||
|
|
||||||
|
def _run_interactive(self) -> None:
|
||||||
|
"""Run the app loop to completion interactively."""
|
||||||
|
import code
|
||||||
|
self._prerun()
|
||||||
|
|
||||||
|
# Print basic usage info for interactive mode.
|
||||||
|
logging.info(f"{Clr.CYN}{Clr.BLD}Interactive mode enabled use the 'mgr' object to interact with the server. Type 'help(mgr)' for more information.{Clr.RST}")
|
||||||
|
context = {'__name__': '__console__', '__doc__': None, 'mgr': self}
|
||||||
|
|
||||||
|
# Enable tab-completion if possible.
|
||||||
|
self._enable_tab_completion(context)
|
||||||
|
|
||||||
|
# Now just sit in an interpreter.
|
||||||
|
# TODO: make it possible to use IPython if the user has it available.
|
||||||
|
try:
|
||||||
|
self._interpreter_start_time = time.time()
|
||||||
|
code.interact(local=context, banner='', exitmsg='')
|
||||||
|
except SystemExit:
|
||||||
|
# We get this from the builtin quit(), our signal handler, etc.
|
||||||
|
# Need to catch this so we can clean up, otherwise we'll be
|
||||||
|
# left in limbo with our process thread still running.
|
||||||
|
pass
|
||||||
|
except BaseException as exc:
|
||||||
|
print(
|
||||||
|
f'Unexpected interpreter exception:'
|
||||||
|
f' {exc} ({type(exc)})',
|
||||||
|
flush=True)
|
||||||
|
|
||||||
|
self._postrun()
|
||||||
|
|
||||||
|
def cmd(self, statement: str) -> None:
|
||||||
|
"""Exec a Python command on the current running server subprocess.
|
||||||
|
|
||||||
|
Note that commands are executed asynchronously and no status or
|
||||||
|
return value is accessible from this manager app.
|
||||||
|
"""
|
||||||
|
if not isinstance(statement, str):
|
||||||
|
raise TypeError(f'Expected a string arg; got {type(statement)}')
|
||||||
|
with self._subprocess_commands_lock:
|
||||||
|
self._subprocess_commands.append(statement)
|
||||||
|
self._block_for_command_completion()
|
||||||
|
|
||||||
|
def _block_for_command_completion(self) -> None:
|
||||||
|
# Ideally we'd block here until the command was run so our prompt would
|
||||||
|
# print after it's results. We currently don't get any response from
|
||||||
|
# the app so the best we can do is block until our bg thread has sent
|
||||||
|
# it. In the future we can perhaps add a proper 'command port'
|
||||||
|
# interface for proper blocking two way communication.
|
||||||
|
while True:
|
||||||
|
with self._subprocess_commands_lock:
|
||||||
|
if not self._subprocess_commands:
|
||||||
|
break
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# One last short delay so if we come out *just* as the command is sent
|
||||||
|
# we'll hopefully still give it enough time to process/print.
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def screenmessage(self,
|
||||||
|
message: str,
|
||||||
|
color: Optional[tuple[float, float, float]] = None,
|
||||||
|
clients: Optional[list[int]] = None) -> None:
|
||||||
|
"""Display a screen-message.
|
||||||
|
|
||||||
|
This will have no name attached and not show up in chat history.
|
||||||
|
They will show up in replays, however (unless clients is passed).
|
||||||
|
"""
|
||||||
|
from bacommon.servermanager import ScreenMessageCommand
|
||||||
|
self._enqueue_server_command(
|
||||||
|
ScreenMessageCommand(message=message, color=color,
|
||||||
|
clients=clients))
|
||||||
|
|
||||||
|
def chatmessage(self,
|
||||||
|
message: str,
|
||||||
|
clients: Optional[list[int]] = None) -> None:
|
||||||
|
"""Send a chat message from the server.
|
||||||
|
|
||||||
|
This will have the server's name attached and will be logged
|
||||||
|
in client chat windows, just like other chat messages.
|
||||||
|
"""
|
||||||
|
from bacommon.servermanager import ChatMessageCommand
|
||||||
|
self._enqueue_server_command(
|
||||||
|
ChatMessageCommand(message=message, clients=clients))
|
||||||
|
|
||||||
|
def clientlist(self) -> None:
|
||||||
|
"""Print a list of connected clients."""
|
||||||
|
from bacommon.servermanager import ClientListCommand
|
||||||
|
self._enqueue_server_command(ClientListCommand())
|
||||||
|
self._block_for_command_completion()
|
||||||
|
|
||||||
|
def kick(self, client_id: int, ban_time: Optional[int] = None) -> None:
|
||||||
|
"""Kick the client with the provided id.
|
||||||
|
|
||||||
|
If ban_time is provided, the client will be banned for that
|
||||||
|
length of time in seconds. If it is None, ban duration will
|
||||||
|
be determined automatically. Pass 0 or a negative number for no
|
||||||
|
ban time.
|
||||||
|
"""
|
||||||
|
from bacommon.servermanager import KickCommand
|
||||||
|
self._enqueue_server_command(
|
||||||
|
KickCommand(client_id=client_id, ban_time=ban_time))
|
||||||
|
|
||||||
|
def restart(self, immediate: bool = True) -> None:
|
||||||
|
"""Restart the server subprocess.
|
||||||
|
|
||||||
|
By default, the current server process will exit immediately.
|
||||||
|
If 'immediate' is passed as False, however, it will instead exit at
|
||||||
|
the next clean transition point (the end of a series, etc).
|
||||||
|
"""
|
||||||
|
from bacommon.servermanager import ShutdownCommand, ShutdownReason
|
||||||
|
self._enqueue_server_command(
|
||||||
|
ShutdownCommand(reason=ShutdownReason.RESTARTING,
|
||||||
|
immediate=immediate))
|
||||||
|
|
||||||
|
# If we're asking for an immediate restart but don't get one within
|
||||||
|
# the grace period, bring down the hammer.
|
||||||
|
if immediate:
|
||||||
|
self._subprocess_force_kill_time = (
|
||||||
|
time.time() + self.IMMEDIATE_SHUTDOWN_TIME_LIMIT)
|
||||||
|
|
||||||
|
def shutdown(self, immediate: bool = True) -> None:
|
||||||
|
"""Shut down the server subprocess and exit the wrapper.
|
||||||
|
|
||||||
|
By default, the current server process will exit immediately.
|
||||||
|
If 'immediate' is passed as False, however, it will instead exit at
|
||||||
|
the next clean transition point (the end of a series, etc).
|
||||||
|
"""
|
||||||
|
from bacommon.servermanager import ShutdownCommand, ShutdownReason
|
||||||
|
self._enqueue_server_command(
|
||||||
|
ShutdownCommand(reason=ShutdownReason.NONE, immediate=immediate))
|
||||||
|
|
||||||
|
# An explicit shutdown means we know to bail completely once this
|
||||||
|
# subprocess completes.
|
||||||
|
self._wrapper_shutdown_desired = True
|
||||||
|
|
||||||
|
# If we're asking for an immediate shutdown but don't get one within
|
||||||
|
# the grace period, bring down the hammer.
|
||||||
|
if immediate:
|
||||||
|
self._subprocess_force_kill_time = (
|
||||||
|
time.time() + self.IMMEDIATE_SHUTDOWN_TIME_LIMIT)
|
||||||
|
|
||||||
|
def _parse_command_line_args(self) -> None:
|
||||||
|
"""Parse command line args."""
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
argc = len(sys.argv)
|
||||||
|
did_set_interactive = False
|
||||||
|
while i < argc:
|
||||||
|
arg = sys.argv[i]
|
||||||
|
if arg == '--help':
|
||||||
|
self.print_help()
|
||||||
|
sys.exit(0)
|
||||||
|
elif arg == '--config':
|
||||||
|
if i + 1 >= argc:
|
||||||
|
raise CleanError('Expected a config path as next arg.')
|
||||||
|
path = sys.argv[i + 1]
|
||||||
|
if not os.path.exists(path):
|
||||||
|
raise CleanError(
|
||||||
|
f"Supplied path does not exist: '{path}'.")
|
||||||
|
# We need an abs path because we may be in a different
|
||||||
|
# cwd currently than we will be during the run.
|
||||||
|
self._config_path = os.path.abspath(path)
|
||||||
|
self._user_provided_config_path = True
|
||||||
|
i += 2
|
||||||
|
elif arg == '--root':
|
||||||
|
if i + 1 >= argc:
|
||||||
|
raise CleanError('Expected a path as next arg.')
|
||||||
|
path = sys.argv[i + 1]
|
||||||
|
# Unlike config_path, this one doesn't have to exist now.
|
||||||
|
# We do however need an abs path because we may be in a
|
||||||
|
# different cwd currently than we will be during the run.
|
||||||
|
self._ba_root_path = os.path.abspath(path)
|
||||||
|
i += 2
|
||||||
|
elif arg == '--interactive':
|
||||||
|
if did_set_interactive:
|
||||||
|
raise CleanError('interactive/noninteractive can only'
|
||||||
|
' be specified once.')
|
||||||
|
self._interactive = True
|
||||||
|
did_set_interactive = True
|
||||||
|
i += 1
|
||||||
|
elif arg == '--noninteractive':
|
||||||
|
if did_set_interactive:
|
||||||
|
raise CleanError('interactive/noninteractive can only'
|
||||||
|
' be specified once.')
|
||||||
|
self._interactive = False
|
||||||
|
did_set_interactive = True
|
||||||
|
i += 1
|
||||||
|
elif arg == '--no-auto-restart':
|
||||||
|
self._auto_restart = False
|
||||||
|
i += 1
|
||||||
|
elif arg == '--no-config-auto-restart':
|
||||||
|
self._config_auto_restart = False
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
raise CleanError(f"Invalid arg: '{arg}'.")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _par(cls, txt: str) -> str:
|
||||||
|
"""Spit out a pretty paragraph for our help text."""
|
||||||
|
import textwrap
|
||||||
|
ind = ' ' * 2
|
||||||
|
out = textwrap.fill(txt, 80, initial_indent=ind, subsequent_indent=ind)
|
||||||
|
return f'{out}\n'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def print_help(cls) -> None:
|
||||||
|
"""Print app help."""
|
||||||
|
filename = os.path.basename(__file__)
|
||||||
|
out = (
|
||||||
|
f'{Clr.BLD}{filename} usage:{Clr.RST}\n' + cls._par(
|
||||||
|
'This script handles configuring, launching, re-launching,'
|
||||||
|
' and otherwise managing BallisticaCore operating'
|
||||||
|
' in server mode. It can be run with no arguments, but'
|
||||||
|
' accepts the following optional ones:') + f'\n'
|
||||||
|
f'{Clr.BLD}--help:{Clr.RST}\n'
|
||||||
|
f' Show this help.\n'
|
||||||
|
f'\n'
|
||||||
|
f'{Clr.BLD}--config [path]{Clr.RST}\n' + cls._par(
|
||||||
|
'Set the config file read by the server script. The config'
|
||||||
|
' file contains most options for what kind of game to host.'
|
||||||
|
' It should be in yaml format. Note that yaml is backwards'
|
||||||
|
' compatible with json so you can just write json if you'
|
||||||
|
' want to. If not specified, the script will look for a'
|
||||||
|
' file named \'config.yaml\' in the same directory as the'
|
||||||
|
' script.') + '\n'
|
||||||
|
f'{Clr.BLD}--root [path]{Clr.RST}\n' + cls._par(
|
||||||
|
'Set the ballistica root directory. This is where the server'
|
||||||
|
' binary will read and write its caches, state files,'
|
||||||
|
' downloaded assets to, etc. It needs to be a writable'
|
||||||
|
' directory. If not specified, the script will use the'
|
||||||
|
' \'dist/ba_root\' directory relative to itself.') + '\n'
|
||||||
|
f'{Clr.BLD}--interactive{Clr.RST}\n'
|
||||||
|
f'{Clr.BLD}--noninteractive{Clr.RST}\n' + cls._par(
|
||||||
|
'Specify whether the script should run interactively.'
|
||||||
|
' In interactive mode, the script creates a Python interpreter'
|
||||||
|
' and reads commands from stdin, allowing for live interaction'
|
||||||
|
' with the server. The server script will then exit when '
|
||||||
|
'end-of-file is reached in stdin. Noninteractive mode creates'
|
||||||
|
' no interpreter and is more suited to being run in automated'
|
||||||
|
' scenarios. By default, interactive mode will be used if'
|
||||||
|
' a terminal is detected and noninteractive mode otherwise.') +
|
||||||
|
'\n'
|
||||||
|
f'{Clr.BLD}--no-auto-restart{Clr.RST}\n' +
|
||||||
|
cls._par('Auto-restart is enabled by default, which means the'
|
||||||
|
' server manager will restart the server binary whenever'
|
||||||
|
' it exits (even when uncleanly). Disabling auto-restart'
|
||||||
|
' will cause the server manager to instead exit after a'
|
||||||
|
' single run and also to return error codes if the'
|
||||||
|
' server binary did so.') + '\n'
|
||||||
|
f'{Clr.BLD}--no-config-auto-restart{Clr.RST}\n' + cls._par(
|
||||||
|
'By default, when auto-restart is enabled, the server binary'
|
||||||
|
' will be automatically restarted if changes to the server'
|
||||||
|
' config file are detected. This disables that behavior.'))
|
||||||
|
print(out)
|
||||||
|
|
||||||
|
def load_config(self, strict: bool, print_confirmation: bool) -> None:
|
||||||
|
"""Load the config.
|
||||||
|
|
||||||
|
If strict is True, errors will propagate upward.
|
||||||
|
Otherwise, warnings will be printed and repeated attempts will be
|
||||||
|
made to load the config. Eventually the function will give up
|
||||||
|
and leave the existing config as-is.
|
||||||
|
"""
|
||||||
|
retry_seconds = 3
|
||||||
|
maxtries = 11
|
||||||
|
for trynum in range(maxtries):
|
||||||
|
try:
|
||||||
|
self._config = self._load_config_from_file(
|
||||||
|
print_confirmation=print_confirmation)
|
||||||
|
return
|
||||||
|
except Exception as exc:
|
||||||
|
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}',
|
||||||
|
flush=True)
|
||||||
|
if trynum == maxtries - 1:
|
||||||
|
print(
|
||||||
|
f'{Clr.RED}Max-tries reached; giving up.'
|
||||||
|
f' Existing config values will be used.{Clr.RST}',
|
||||||
|
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'
|
||||||
|
f' {maxtries - 1}).{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
|
||||||
|
for _j in range(retry_seconds):
|
||||||
|
# If the app is trying to die, drop what we're doing.
|
||||||
|
if self._done:
|
||||||
|
return
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def _load_config_from_file(self, print_confirmation: bool) -> ServerConfig:
|
||||||
|
|
||||||
|
out: Optional[ServerConfig] = None
|
||||||
|
|
||||||
|
if not os.path.exists(self._config_path):
|
||||||
|
|
||||||
|
# Special case:
|
||||||
|
# If the user didn't specify a particular config file, allow
|
||||||
|
# gracefully falling back to defaults if the default one is
|
||||||
|
# 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}',
|
||||||
|
flush=True)
|
||||||
|
self._config_mtime = None
|
||||||
|
self._last_config_mtime_check_time = time.time()
|
||||||
|
return ServerConfig()
|
||||||
|
|
||||||
|
# Don't be so lenient if the user pointed us at one though.
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Config file not found: '{self._config_path}'.")
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
with open(self._config_path, encoding='utf-8') as infile:
|
||||||
|
user_config_raw = yaml.safe_load(infile.read())
|
||||||
|
|
||||||
|
# An empty config file will yield None, and that's ok.
|
||||||
|
if user_config_raw is not None:
|
||||||
|
out = dataclass_from_dict(ServerConfig, user_config_raw)
|
||||||
|
|
||||||
|
# Update our known mod-time since we know it exists.
|
||||||
|
self._config_mtime = Path(self._config_path).stat().st_mtime
|
||||||
|
self._last_config_mtime_check_time = time.time()
|
||||||
|
|
||||||
|
# Go with defaults if we weren't able to load anything.
|
||||||
|
if out is None:
|
||||||
|
out = ServerConfig()
|
||||||
|
|
||||||
|
if print_confirmation:
|
||||||
|
logging.info(f"{Clr.CYN}{Clr.BLD}Loaded all server configuration files successfully.{Clr.RST}")
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _enable_tab_completion(self, locs: dict) -> None:
|
||||||
|
"""Enable tab-completion on platforms where available (linux/mac)."""
|
||||||
|
try:
|
||||||
|
import readline
|
||||||
|
import rlcompleter
|
||||||
|
readline.set_completer(rlcompleter.Completer(locs).complete)
|
||||||
|
readline.parse_and_bind('tab:complete')
|
||||||
|
except ImportError:
|
||||||
|
# This is expected (readline doesn't exist under windows).
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _bg_thread_main(self) -> None:
|
||||||
|
"""Top level method run by our bg thread."""
|
||||||
|
while not self._done:
|
||||||
|
self._run_server_cycle()
|
||||||
|
|
||||||
|
def _handle_term_signal(self, sig: int, frame: FrameType) -> None:
|
||||||
|
"""Handle signals (will always run in the main thread)."""
|
||||||
|
del sig, frame # Unused.
|
||||||
|
sys.exit(1 if self._should_report_subprocess_error else 0)
|
||||||
|
|
||||||
|
def _run_server_cycle(self) -> None:
|
||||||
|
"""Spin up the server subprocess and run it until exit."""
|
||||||
|
# pylint: disable=consider-using-with
|
||||||
|
|
||||||
|
# Reload our config, and update our overall behavior based on it.
|
||||||
|
# We do non-strict this time to give the user repeated attempts if
|
||||||
|
# if they mess up while modifying the config on the fly.
|
||||||
|
self.load_config(strict=False, print_confirmation=True)
|
||||||
|
|
||||||
|
self._prep_subprocess_environment()
|
||||||
|
|
||||||
|
# Launch the binary and grab its stdin;
|
||||||
|
# we'll use this to feed it commands.
|
||||||
|
self._subprocess_launch_time = time.time()
|
||||||
|
|
||||||
|
# Set an environment var so the server process knows its being
|
||||||
|
# run under us. This causes it to ignore ctrl-c presses and other
|
||||||
|
# slight behavior tweaks. Hmm; should this be an argument instead?
|
||||||
|
os.environ['BA_SERVER_WRAPPER_MANAGED'] = '1'
|
||||||
|
os.environ['BA_DEVICE_NAME'] = self._config.party_name
|
||||||
|
logging.info(f"{Clr.CYN}{Clr.BLD}Launching server sub-process. Hang tight!{Clr.RST}")
|
||||||
|
binary_name = ('BallisticaCoreHeadless.exe'
|
||||||
|
if os.name == 'nt' else './bombsquad_headless')
|
||||||
|
if platform.processor() == 'aarch64':
|
||||||
|
binary_name = './bombsquad_headless_aarch64'
|
||||||
|
assert self._ba_root_path is not None
|
||||||
|
self._subprocess = None
|
||||||
|
|
||||||
|
# Launch!
|
||||||
|
try:
|
||||||
|
if ERROR_LOGGING:
|
||||||
|
self._subprocess = subprocess.Popen(
|
||||||
|
[binary_name, '-cfgdir', self._ba_root_path],
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
cwd='dist')
|
||||||
|
|
||||||
|
self.nbsr = NBSR(self._subprocess.stdout)
|
||||||
|
self.nbsrerr = NBSR(self._subprocess.stderr)
|
||||||
|
else:
|
||||||
|
self._subprocess = subprocess.Popen(
|
||||||
|
[binary_name, '-cfgdir', self._ba_root_path],
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
cwd='dist')
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
self._subprocess_exited_cleanly = False
|
||||||
|
print(
|
||||||
|
f'{Clr.RED}Error launching server subprocess: {exc}{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
|
||||||
|
# Do the thing.
|
||||||
|
try:
|
||||||
|
self._run_subprocess_until_exit()
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
print(f'{Clr.RED}Error running server subprocess: {exc}{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
|
||||||
|
self._kill_subprocess()
|
||||||
|
|
||||||
|
assert self._subprocess_exited_cleanly is not None
|
||||||
|
|
||||||
|
# EW: it seems that if we die before the main thread has fully started
|
||||||
|
# up the interpreter, its possible that it will not break out of its
|
||||||
|
# loop via the usual SystemExit that gets sent when we die.
|
||||||
|
if self._interactive:
|
||||||
|
while (self._interpreter_start_time is None
|
||||||
|
or time.time() - self._interpreter_start_time < 0.5):
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# Avoid super fast death loops.
|
||||||
|
if (not self._subprocess_exited_cleanly and self._auto_restart
|
||||||
|
and not self._done):
|
||||||
|
time.sleep(5.0)
|
||||||
|
|
||||||
|
# If they don't want auto-restart, we'll exit the whole wrapper.
|
||||||
|
# (and with an error code if things ended badly).
|
||||||
|
if not self._auto_restart:
|
||||||
|
self._wrapper_shutdown_desired = True
|
||||||
|
if not self._subprocess_exited_cleanly:
|
||||||
|
self._should_report_subprocess_error = True
|
||||||
|
|
||||||
|
self._reset_subprocess_vars()
|
||||||
|
|
||||||
|
# If we want to die completely after this subprocess has ended,
|
||||||
|
# tell the main thread to die.
|
||||||
|
if self._wrapper_shutdown_desired:
|
||||||
|
|
||||||
|
# Only do this if the main thread is not already waiting for
|
||||||
|
# us to die; otherwise it can lead to deadlock.
|
||||||
|
# (we hang in os.kill while main thread is blocked in Thread.join)
|
||||||
|
if not self._done:
|
||||||
|
self._done = True
|
||||||
|
|
||||||
|
# This should break the main thread out of its blocking
|
||||||
|
# interpreter call.
|
||||||
|
os.kill(os.getpid(), signal.SIGTERM)
|
||||||
|
|
||||||
|
def _prep_subprocess_environment(self) -> None:
|
||||||
|
"""Write files that must exist at process launch."""
|
||||||
|
|
||||||
|
assert self._ba_root_path is not None
|
||||||
|
os.makedirs(self._ba_root_path, exist_ok=True)
|
||||||
|
cfgpath = os.path.join(self._ba_root_path, 'config.json')
|
||||||
|
if os.path.exists(cfgpath):
|
||||||
|
with open(cfgpath, encoding='utf-8') as infile:
|
||||||
|
bincfg = json.loads(infile.read())
|
||||||
|
else:
|
||||||
|
bincfg = {}
|
||||||
|
|
||||||
|
# Some of our config values translate directly into the
|
||||||
|
# ballisticacore config file; the rest we pass at runtime.
|
||||||
|
bincfg['Port'] = self._config.port
|
||||||
|
bincfg['Auto Balance Teams'] = self._config.auto_balance_teams
|
||||||
|
bincfg['Show Tutorial'] = self._config.show_tutorial
|
||||||
|
|
||||||
|
if self._config.team_names is not None:
|
||||||
|
bincfg['Custom Team Names'] = self._config.team_names
|
||||||
|
elif 'Custom Team Names' in bincfg:
|
||||||
|
del bincfg['Custom Team Names']
|
||||||
|
|
||||||
|
if self._config.team_colors is not None:
|
||||||
|
bincfg['Custom Team Colors'] = self._config.team_colors
|
||||||
|
elif 'Custom Team Colors' in bincfg:
|
||||||
|
del bincfg['Custom Team Colors']
|
||||||
|
|
||||||
|
bincfg['Idle Exit Minutes'] = self._config.idle_exit_minutes
|
||||||
|
with open(cfgpath, 'w', encoding='utf-8') as outfile:
|
||||||
|
outfile.write(json.dumps(bincfg))
|
||||||
|
|
||||||
|
def _enqueue_server_command(self, command: ServerCommand) -> None:
|
||||||
|
"""Enqueue a command to be sent to the server.
|
||||||
|
|
||||||
|
Can be called from any thread.
|
||||||
|
"""
|
||||||
|
with self._subprocess_commands_lock:
|
||||||
|
self._subprocess_commands.append(command)
|
||||||
|
|
||||||
|
def _send_server_command(self, command: ServerCommand) -> None:
|
||||||
|
"""Send a command to the server.
|
||||||
|
|
||||||
|
Must be called from the server process thread.
|
||||||
|
"""
|
||||||
|
import pickle
|
||||||
|
assert current_thread() is self._subprocess_thread
|
||||||
|
assert self._subprocess is not None
|
||||||
|
assert self._subprocess.stdin is not None
|
||||||
|
val = repr(pickle.dumps(command))
|
||||||
|
assert '\n' not in val
|
||||||
|
execcode = (f'import ba._servermode;'
|
||||||
|
f' ba._servermode._cmd({val})\n').encode()
|
||||||
|
self._subprocess.stdin.write(execcode)
|
||||||
|
self._subprocess.stdin.flush()
|
||||||
|
|
||||||
|
def _run_subprocess_until_exit(self) -> None:
|
||||||
|
if self._subprocess is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
assert current_thread() is self._subprocess_thread
|
||||||
|
assert self._subprocess.stdin is not None
|
||||||
|
|
||||||
|
# Send the initial server config which should kick things off.
|
||||||
|
# (but make sure its values are still valid first)
|
||||||
|
dataclass_validate(self._config)
|
||||||
|
self._send_server_command(StartServerModeCommand(self._config))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
# If the app is trying to shut down, nope out immediately.
|
||||||
|
if self._done:
|
||||||
|
break
|
||||||
|
# output=self._subprocess.stdout.readline()
|
||||||
|
# print(output)
|
||||||
|
if ERROR_LOGGING:
|
||||||
|
out = self.nbsr.readline(0.1)
|
||||||
|
out2 = self.nbsrerr.readline(0.1)
|
||||||
|
if out:
|
||||||
|
sys.stdout.write(out.decode("utf-8"))
|
||||||
|
_thread.start_new_thread(dump_logs, (out.decode("utf-8"),))
|
||||||
|
if out2:
|
||||||
|
sys.stdout.write(out2.decode("utf-8"))
|
||||||
|
_thread.start_new_thread(dump_logs, (out2.decode("utf-8"),))
|
||||||
|
# Pass along any commands to our process.
|
||||||
|
with self._subprocess_commands_lock:
|
||||||
|
for incmd in self._subprocess_commands:
|
||||||
|
# If we're passing a raw string to exec, no need to wrap it
|
||||||
|
# in any proper structure.
|
||||||
|
if isinstance(incmd, str):
|
||||||
|
self._subprocess.stdin.write((incmd + '\n').encode())
|
||||||
|
self._subprocess.stdin.flush()
|
||||||
|
else:
|
||||||
|
self._send_server_command(incmd)
|
||||||
|
self._subprocess_commands = []
|
||||||
|
|
||||||
|
# Request restarts/shut-downs for various reasons.
|
||||||
|
self._request_shutdowns_or_restarts()
|
||||||
|
|
||||||
|
# If they want to force-kill our subprocess, simply exit this
|
||||||
|
# loop; the cleanup code will kill the process if its still
|
||||||
|
# alive.
|
||||||
|
|
||||||
|
if (self._subprocess_force_kill_time is not None
|
||||||
|
and time.time() > self._subprocess_force_kill_time):
|
||||||
|
print(
|
||||||
|
f'{Clr.CYN}Immediate shutdown time limit'
|
||||||
|
f' ({self.IMMEDIATE_SHUTDOWN_TIME_LIMIT:.1f} seconds)'
|
||||||
|
f' expired; force-killing subprocess...{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
break
|
||||||
|
|
||||||
|
# Watch for the server process exiting..
|
||||||
|
code: Optional[int] = self._subprocess.poll()
|
||||||
|
if code is not None:
|
||||||
|
clr = Clr.CYN if code == 0 else Clr.RED
|
||||||
|
print(
|
||||||
|
f'{clr}Server subprocess exited'
|
||||||
|
f' with code {code}.{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
self._subprocess_exited_cleanly = (code == 0)
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(0.25)
|
||||||
|
|
||||||
|
def _request_shutdowns_or_restarts(self) -> None:
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
assert current_thread() is self._subprocess_thread
|
||||||
|
assert self._subprocess_launch_time is not None
|
||||||
|
now = time.time()
|
||||||
|
minutes_since_launch = (now - self._subprocess_launch_time) / 60.0
|
||||||
|
|
||||||
|
# If we're doing auto-restart with config changes, handle that.
|
||||||
|
if (self._auto_restart and self._config_auto_restart
|
||||||
|
and not self._subprocess_sent_config_auto_restart):
|
||||||
|
if (self._last_config_mtime_check_time is None
|
||||||
|
or (now - self._last_config_mtime_check_time) > 3.123):
|
||||||
|
self._last_config_mtime_check_time = now
|
||||||
|
mtime: Optional[float]
|
||||||
|
if os.path.isfile(self._config_path):
|
||||||
|
mtime = Path(self._config_path).stat().st_mtime
|
||||||
|
else:
|
||||||
|
mtime = None
|
||||||
|
if mtime != self._config_mtime:
|
||||||
|
print(
|
||||||
|
f'{Clr.CYN}Config-file change detected;'
|
||||||
|
f' requesting immediate restart.{Clr.RST}',
|
||||||
|
flush=True)
|
||||||
|
self.restart(immediate=True)
|
||||||
|
self._subprocess_sent_config_auto_restart = True
|
||||||
|
|
||||||
|
# Attempt clean exit if our clean-exit-time passes.
|
||||||
|
# (and enforce a 6 hour max if not provided)
|
||||||
|
clean_exit_minutes = 360.0
|
||||||
|
if self._config.clean_exit_minutes is not None:
|
||||||
|
clean_exit_minutes = min(clean_exit_minutes,
|
||||||
|
self._config.clean_exit_minutes)
|
||||||
|
if clean_exit_minutes is not None:
|
||||||
|
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}',
|
||||||
|
flush=True)
|
||||||
|
if self._auto_restart:
|
||||||
|
self.restart(immediate=False)
|
||||||
|
else:
|
||||||
|
self.shutdown(immediate=False)
|
||||||
|
self._subprocess_sent_clean_exit = True
|
||||||
|
|
||||||
|
# Attempt unclean exit if our unclean-exit-time passes.
|
||||||
|
# (and enforce a 7 hour max if not provided)
|
||||||
|
unclean_exit_minutes = 420.0
|
||||||
|
if self._config.unclean_exit_minutes is not None:
|
||||||
|
unclean_exit_minutes = min(unclean_exit_minutes,
|
||||||
|
self._config.unclean_exit_minutes)
|
||||||
|
if unclean_exit_minutes is not None:
|
||||||
|
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}',
|
||||||
|
flush=True)
|
||||||
|
if self._auto_restart:
|
||||||
|
self.restart(immediate=True)
|
||||||
|
else:
|
||||||
|
self.shutdown(immediate=True)
|
||||||
|
self._subprocess_sent_unclean_exit = True
|
||||||
|
|
||||||
|
def _reset_subprocess_vars(self) -> None:
|
||||||
|
self._subprocess = None
|
||||||
|
self._subprocess_launch_time = None
|
||||||
|
self._subprocess_sent_config_auto_restart = False
|
||||||
|
self._subprocess_sent_clean_exit = False
|
||||||
|
self._subprocess_sent_unclean_exit = False
|
||||||
|
self._subprocess_force_kill_time = None
|
||||||
|
self._subprocess_exited_cleanly = None
|
||||||
|
|
||||||
|
def _kill_subprocess(self) -> None:
|
||||||
|
"""End the server subprocess if it still exists."""
|
||||||
|
assert current_thread() is self._subprocess_thread
|
||||||
|
if self._subprocess is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
# First, ask it nicely to die and give it a moment.
|
||||||
|
# If that doesn't work, bring down the hammer.
|
||||||
|
self._subprocess.terminate()
|
||||||
|
try:
|
||||||
|
self._subprocess.wait(timeout=10)
|
||||||
|
self._subprocess_exited_cleanly = (
|
||||||
|
self._subprocess.returncode == 0)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
self._subprocess_exited_cleanly = False
|
||||||
|
self._subprocess.kill()
|
||||||
|
logging.info(f"{Clr.RED}{Clr.BLD}Server shut down completed successfully!{Clr.RST}")
|
||||||
|
|
||||||
|
|
||||||
|
#PING THE SERVER STATUS SERVER
|
||||||
|
#WE NEED TO AGREE ON THE SERVER ID'S
|
||||||
|
# import requests
|
||||||
|
# from threading import Timer
|
||||||
|
|
||||||
|
# def ping_online_server():
|
||||||
|
# try:
|
||||||
|
# r = requests.get(url="https://serverstatus.professorfish.repl.co/statuses")
|
||||||
|
# data = r.json()
|
||||||
|
# except Exception as e:
|
||||||
|
# print(e)
|
||||||
|
# print("FAILED TO PING THE SERVER STATUS SERVER")
|
||||||
|
# finally:
|
||||||
|
# Timer(10, ping_online_server).start()
|
||||||
|
def main() -> None:
|
||||||
|
"""Run the BallisticaCore server manager."""
|
||||||
|
try:
|
||||||
|
# ping_online_server()
|
||||||
|
ServerManagerApp().run()
|
||||||
|
|
||||||
|
|
||||||
|
except CleanError as exc:
|
||||||
|
# For clean errors, do a simple print and fail; no tracebacks/etc.
|
||||||
|
# Any others will bubble up and give us the usual mess.
|
||||||
|
exc.pretty_print()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def dump_logs(msg):
|
||||||
|
if os.path.isfile('logs.log'):
|
||||||
|
size = os.path.getsize('logs.log')
|
||||||
|
|
||||||
|
if size > 2000000:
|
||||||
|
os.remove('logs.log')
|
||||||
|
|
||||||
|
with open("logs.log", "a") as f:
|
||||||
|
f.write(msg)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
133
config.yaml
Normal file
133
config.yaml
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
# To configure your server, create a config.yaml file in the same directory
|
||||||
|
# as the ballisticacore_server script. The config_template.yaml file can be
|
||||||
|
# copied or renamed as a convenient starting point.
|
||||||
|
|
||||||
|
# Uncomment any of these values to override defaults.
|
||||||
|
|
||||||
|
# Name of our server in the public parties list.
|
||||||
|
party_name: "VORTEX AND HONOR BANG xD"
|
||||||
|
|
||||||
|
# If true, your party will show up in the global public party list
|
||||||
|
# Otherwise it will still be joinable via LAN or connecting by IP address.
|
||||||
|
party_is_public: true
|
||||||
|
|
||||||
|
# If true, all connecting clients will be authenticated through the master
|
||||||
|
# server to screen for fake account info. Generally this should always
|
||||||
|
# be enabled unless you are hosting on a LAN with no internet connection.
|
||||||
|
authenticate_clients: true
|
||||||
|
|
||||||
|
# IDs of server admins. Server admins are not kickable through the default
|
||||||
|
# kick vote system and they are able to kick players without a vote. To get
|
||||||
|
# your account id, enter 'getaccountid' in settings->advanced->enter-code.
|
||||||
|
admins:
|
||||||
|
- pb-JiNJARFeXENAVF5FEkFQXFVBGUJWTlVH
|
||||||
|
|
||||||
|
# Whether the default kick-voting system is enabled.
|
||||||
|
enable_default_kick_voting: true
|
||||||
|
|
||||||
|
# UDP port to host on. Change this to work around firewalls or run multiple
|
||||||
|
# servers on one machine.
|
||||||
|
# 43210 is the default and the only port that will show up in the LAN
|
||||||
|
# browser tab.
|
||||||
|
port: 43211
|
||||||
|
|
||||||
|
# Max devices in the party. Note that this does *NOT* mean max players.
|
||||||
|
# Any device in the party can have more than one player on it if they have
|
||||||
|
# multiple controllers. Also, this number currently includes the server so
|
||||||
|
# generally make it 1 bigger than you need. Max-players is not currently
|
||||||
|
# exposed but I'll try to add that soon.
|
||||||
|
max_party_size: 12
|
||||||
|
|
||||||
|
# Options here are 'ffa' (free-for-all), 'teams' and 'coop' (cooperative)
|
||||||
|
# This value is ignored if you supply a playlist_code (see below).
|
||||||
|
#session_type: ffa
|
||||||
|
|
||||||
|
# Playlist-code for teams or free-for-all mode sessions.
|
||||||
|
# To host your own custom playlists, use the 'share' functionality in the
|
||||||
|
# playlist editor in the regular version of the game.
|
||||||
|
# This will give you a numeric code you can enter here to host that
|
||||||
|
# playlist.
|
||||||
|
playlist_code: 445446
|
||||||
|
|
||||||
|
# Alternately, you can embed playlist data here instead of using codes.
|
||||||
|
# Make sure to set session_type to the correct type for the data here.
|
||||||
|
#playlist_inline: []
|
||||||
|
|
||||||
|
# Whether to shuffle the playlist or play its games in designated order.
|
||||||
|
#playlist_shuffle: true
|
||||||
|
|
||||||
|
# If true, keeps team sizes equal by disallowing joining the largest team
|
||||||
|
# (teams mode only).
|
||||||
|
#auto_balance_teams: true
|
||||||
|
|
||||||
|
# The campaign used when in co-op session mode.
|
||||||
|
# Do print(ba.app.campaigns) to see available campaign names.
|
||||||
|
#coop_campaign: Easy
|
||||||
|
|
||||||
|
# The level name within the campaign used in co-op session mode.
|
||||||
|
# For campaign name FOO, do print(ba.app.campaigns['FOO'].levels) to see
|
||||||
|
# available level names.
|
||||||
|
#coop_level: Onslaught Training
|
||||||
|
|
||||||
|
# Whether to enable telnet access.
|
||||||
|
# IMPORTANT: This option is no longer available, as it was being used
|
||||||
|
# for exploits. Live access to the running server is still possible through
|
||||||
|
# the mgr.cmd() function in the server script. Run your server through
|
||||||
|
# tools such as 'screen' or 'tmux' and you can reconnect to it remotely
|
||||||
|
# over a secure ssh connection.
|
||||||
|
#enable_telnet: false
|
||||||
|
|
||||||
|
# Series length in teams mode (7 == 'best-of-7' series; a team must
|
||||||
|
# get 4 wins)
|
||||||
|
teams_series_length: 7
|
||||||
|
|
||||||
|
# Points to win in free-for-all mode (Points are awarded per game based on
|
||||||
|
# performance)
|
||||||
|
ffa_series_length: 24
|
||||||
|
|
||||||
|
# If you have a custom stats webpage for your server, you can use this
|
||||||
|
# to provide a convenient in-game link to it in the server-browser
|
||||||
|
# alongside the server name.
|
||||||
|
# if ${ACCOUNT} is present in the string, it will be replaced by the
|
||||||
|
# currently-signed-in account's id. To fetch info about an account,
|
||||||
|
# your back-end server can use the following url:
|
||||||
|
# http://bombsquadgame.com/accountquery?id=ACCOUNT_ID_HERE
|
||||||
|
stats_url: https://discord.gg/MUj97D2QMZ
|
||||||
|
|
||||||
|
# If present, the server subprocess will attempt to gracefully exit after
|
||||||
|
# this amount of time. A graceful exit can occur at the end of a series
|
||||||
|
# or other opportune time. Server-managers set to auto-restart (the
|
||||||
|
# default) will then spin up a fresh subprocess. This mechanism can be
|
||||||
|
# useful to clear out any memory leaks or other accumulated bad state
|
||||||
|
# in the server subprocess.
|
||||||
|
#clean_exit_minutes: 60
|
||||||
|
|
||||||
|
# If present, the server subprocess will shut down immediately after this
|
||||||
|
# amount of time. This can be useful as a fallback for clean_exit_time.
|
||||||
|
# The server manager will then spin up a fresh server subprocess if
|
||||||
|
# auto-restart is enabled (the default).
|
||||||
|
#unclean_exit_minutes: 90
|
||||||
|
|
||||||
|
# If present, the server subprocess will shut down immediately if this
|
||||||
|
# amount of time passes with no activity from any players. The server
|
||||||
|
# manager will then spin up a fresh server subprocess if auto-restart is
|
||||||
|
# enabled (the default).
|
||||||
|
#idle_exit_minutes: 20
|
||||||
|
|
||||||
|
# Should the tutorial be shown at the beginning of games?
|
||||||
|
#show_tutorial: false
|
||||||
|
|
||||||
|
# Team names (teams mode only).
|
||||||
|
team_names:
|
||||||
|
- vortex
|
||||||
|
- Honor
|
||||||
|
|
||||||
|
# Team colors (teams mode only).
|
||||||
|
team_colors:
|
||||||
|
- [0.8, 0.0, 0.6]
|
||||||
|
- [0, 1, 0.8]
|
||||||
|
|
||||||
|
# Whether to enable the queue where players can line up before entering
|
||||||
|
# your server. Disabling this can be used as a workaround to deal with
|
||||||
|
# queue spamming attacks.
|
||||||
|
#enable_queue: true
|
||||||
1
dist/.keys
vendored
Normal file
1
dist/.keys
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"private_key": "iB3jjwHM1sDlk7_gyOH6ix26x6xiI70af0XLAxSlQwY", "public_key": "BNH1Bw4rzMMfDEXRZ8CsgIve7oe7gd8hzfgDXANAv1S1r_goQ1PpbqFUyjcHX5mOEJhG0qhNd14bZ8lbOJqwNSc"}
|
||||||
1813
dist/ba_data/data/langdata.json
vendored
Normal file
1813
dist/ba_data/data/langdata.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1882
dist/ba_data/data/languages/arabic.json
vendored
Normal file
1882
dist/ba_data/data/languages/arabic.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1876
dist/ba_data/data/languages/belarussian.json
vendored
Normal file
1876
dist/ba_data/data/languages/belarussian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1908
dist/ba_data/data/languages/chinese.json
vendored
Normal file
1908
dist/ba_data/data/languages/chinese.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1878
dist/ba_data/data/languages/chinesetraditional.json
vendored
Normal file
1878
dist/ba_data/data/languages/chinesetraditional.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1880
dist/ba_data/data/languages/croatian.json
vendored
Normal file
1880
dist/ba_data/data/languages/croatian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1903
dist/ba_data/data/languages/czech.json
vendored
Normal file
1903
dist/ba_data/data/languages/czech.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1626
dist/ba_data/data/languages/danish.json
vendored
Normal file
1626
dist/ba_data/data/languages/danish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1965
dist/ba_data/data/languages/dutch.json
vendored
Normal file
1965
dist/ba_data/data/languages/dutch.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1893
dist/ba_data/data/languages/english.json
vendored
Normal file
1893
dist/ba_data/data/languages/english.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1610
dist/ba_data/data/languages/esperanto.json
vendored
Normal file
1610
dist/ba_data/data/languages/esperanto.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1883
dist/ba_data/data/languages/filipino.json
vendored
Normal file
1883
dist/ba_data/data/languages/filipino.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1989
dist/ba_data/data/languages/french.json
vendored
Normal file
1989
dist/ba_data/data/languages/french.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
2026
dist/ba_data/data/languages/german.json
vendored
Normal file
2026
dist/ba_data/data/languages/german.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
2039
dist/ba_data/data/languages/gibberish.json
vendored
Normal file
2039
dist/ba_data/data/languages/gibberish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1884
dist/ba_data/data/languages/greek.json
vendored
Normal file
1884
dist/ba_data/data/languages/greek.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1888
dist/ba_data/data/languages/hindi.json
vendored
Normal file
1888
dist/ba_data/data/languages/hindi.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1892
dist/ba_data/data/languages/hungarian.json
vendored
Normal file
1892
dist/ba_data/data/languages/hungarian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1893
dist/ba_data/data/languages/indonesian.json
vendored
Normal file
1893
dist/ba_data/data/languages/indonesian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1985
dist/ba_data/data/languages/italian.json
vendored
Normal file
1985
dist/ba_data/data/languages/italian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1883
dist/ba_data/data/languages/korean.json
vendored
Normal file
1883
dist/ba_data/data/languages/korean.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1878
dist/ba_data/data/languages/malay.json
vendored
Normal file
1878
dist/ba_data/data/languages/malay.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1892
dist/ba_data/data/languages/persian.json
vendored
Normal file
1892
dist/ba_data/data/languages/persian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1981
dist/ba_data/data/languages/polish.json
vendored
Normal file
1981
dist/ba_data/data/languages/polish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
2016
dist/ba_data/data/languages/portuguese.json
vendored
Normal file
2016
dist/ba_data/data/languages/portuguese.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1888
dist/ba_data/data/languages/romanian.json
vendored
Normal file
1888
dist/ba_data/data/languages/romanian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1985
dist/ba_data/data/languages/russian.json
vendored
Normal file
1985
dist/ba_data/data/languages/russian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1880
dist/ba_data/data/languages/serbian.json
vendored
Normal file
1880
dist/ba_data/data/languages/serbian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1875
dist/ba_data/data/languages/slovak.json
vendored
Normal file
1875
dist/ba_data/data/languages/slovak.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
2008
dist/ba_data/data/languages/spanish.json
vendored
Normal file
2008
dist/ba_data/data/languages/spanish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1756
dist/ba_data/data/languages/swedish.json
vendored
Normal file
1756
dist/ba_data/data/languages/swedish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1883
dist/ba_data/data/languages/tamil.json
vendored
Normal file
1883
dist/ba_data/data/languages/tamil.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1876
dist/ba_data/data/languages/thai.json
vendored
Normal file
1876
dist/ba_data/data/languages/thai.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1889
dist/ba_data/data/languages/turkish.json
vendored
Normal file
1889
dist/ba_data/data/languages/turkish.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1889
dist/ba_data/data/languages/ukrainian.json
vendored
Normal file
1889
dist/ba_data/data/languages/ukrainian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1875
dist/ba_data/data/languages/venetian.json
vendored
Normal file
1875
dist/ba_data/data/languages/venetian.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
1872
dist/ba_data/data/languages/vietnamese.json
vendored
Normal file
1872
dist/ba_data/data/languages/vietnamese.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
85
dist/ba_data/data/maps/big_g.json
vendored
Normal file
85
dist/ba_data/data/maps/big_g.json
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-0.4, 2.33, -0.54], "size": [19.12, 10.2, 23.5]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [3.14, 1.17, 6.17], "size": [4.74, 1.0, 1.03]},
|
||||||
|
{"center": [5.42, 1.18, -0.17], "size": [2.95, 0.62, 0.5]},
|
||||||
|
{"center": [-0.37, 2.89, -6.91], "size": [7.58, 0.62, 0.5]},
|
||||||
|
{"center": [-2.39, 1.12, -3.42], "size": [2.93, 0.62, 0.98]},
|
||||||
|
{"center": [-7.46, 2.86, 4.94], "size": [0.87, 0.62, 2.23]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [7.56, 2.89, -7.21]},
|
||||||
|
{"center": [7.7, 1.1, 6.1]},
|
||||||
|
{"center": [-8.12, 2.84, 6.1]},
|
||||||
|
{"center": [-8.02, 2.84, -6.2]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-7.56, 2.85, 0.09]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-0.19, 8.76, 0.2], "size": [27.42, 18.47, 22.17]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [7.83, 2.12, -0.05]},
|
||||||
|
{"center": [-5.19, 1.48, -3.8]},
|
||||||
|
{"center": [-8.54, 3.76, -7.28]},
|
||||||
|
{"center": [7.37, 3.76, -3.09]},
|
||||||
|
{"center": [-8.69, 3.69, 6.63]}
|
||||||
|
],
|
||||||
|
"race_mine": [
|
||||||
|
{"center": [-0.06, 1.12, 4.97]},
|
||||||
|
{"center": [-0.06, 1.12, 7.0]},
|
||||||
|
{"center": [-0.73, 1.12, -2.83]},
|
||||||
|
{"center": [-3.29, 1.12, 0.85]},
|
||||||
|
{"center": [5.08, 2.85, -5.25]},
|
||||||
|
{"center": [6.29, 2.85, -5.25]},
|
||||||
|
{"center": [0.97, 2.85, -7.89]},
|
||||||
|
{"center": [-2.98, 2.85, -6.24]},
|
||||||
|
{"center": [-6.96, 2.85, -2.12]},
|
||||||
|
{"center": [-6.87, 2.85, 2.72]}
|
||||||
|
],
|
||||||
|
"race_point": [
|
||||||
|
{"center": [2.28, 1.17, 6.02], "size": [0.71, 4.67, 1.32]},
|
||||||
|
{"center": [4.85, 1.17, 6.04], "size": [0.39, 4.58, 1.35]},
|
||||||
|
{"center": [6.91, 1.17, 1.14], "size": [1.61, 3.52, 0.11]},
|
||||||
|
{"center": [2.68, 1.17, 0.77], "size": [0.65, 3.6, 0.11]},
|
||||||
|
{"center": [-0.38, 1.23, 1.92], "size": [0.11, 4.25, 0.59]},
|
||||||
|
{"center": [-4.37, 1.17, -0.36], "size": [1.63, 4.55, 0.11]},
|
||||||
|
{"center": [0.41, 1.17, -3.39], "size": [0.11, 4.95, 1.31]},
|
||||||
|
{"center": [4.27, 2.2, -3.34], "size": [0.11, 4.39, 1.2]},
|
||||||
|
{"center": [2.55, 2.88, -7.12], "size": [0.11, 5.51, 1.0]},
|
||||||
|
{"center": [-4.2, 2.88, -7.11], "size": [0.11, 5.5, 1.03]},
|
||||||
|
{"center": [-7.63, 2.88, -3.62], "size": [1.44, 5.16, 0.06]},
|
||||||
|
{"center": [-7.54, 2.88, 3.29], "size": [1.67, 5.52, 0.06]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-0.22, 0.29, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-0.22, 0.88, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-0.22, 6.31, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-0.22, 9.47, 2.68]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [7.18, 2.86, -4.41], "size": [0.76, 1.0, 1.82]},
|
||||||
|
{"center": [5.88, 1.14, 6.17], "size": [1.82, 1.0, 0.77]}
|
||||||
|
],
|
||||||
|
"spawn_by_flag": [
|
||||||
|
{"center": [7.18, 2.86, -4.41], "size": [0.76, 1.0, 1.82]},
|
||||||
|
{"center": [5.88, 1.14, 6.17], "size": [1.82, 1.0, 0.77]},
|
||||||
|
{"center": [-6.67, 3.55, 5.82], "size": [1.1, 1.0, 1.29]},
|
||||||
|
{"center": [-6.84, 3.55, -6.17], "size": [0.82, 1.0, 1.29]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-3.4, 2.07, -1.9]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
95
dist/ba_data/data/maps/bridgit.json
vendored
Normal file
95
dist/ba_data/data/maps/bridgit.json
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"globals": {
|
||||||
|
"ambient_color": [1.1, 1.2, 1.3],
|
||||||
|
"tint": [1.1, 1.2, 1.3],
|
||||||
|
"vignette_inner": [0.9, 0.9, 0.93],
|
||||||
|
"vignette_outer": [0.65, 0.6, 0.55]
|
||||||
|
},
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-0.25, 3.83, -1.53], "size": [19.15, 7.31, 8.44]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-5.87, 3.72, -1.62], "size": [0.94, 1.0, 1.82]},
|
||||||
|
{"center": [5.16, 3.76, -1.44], "size": [0.77, 1.0, 1.82]},
|
||||||
|
{"center": [-0.43, 3.76, -1.56], "size": [4.03, 1.0, 0.27]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-7.35, 3.77, -1.62]},
|
||||||
|
{"center": [6.89, 3.77, -1.44]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-0.22, 3.8, -1.56]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-0.19, 7.48, -1.31], "size": [27.42, 18.47, 19.52]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [6.83, 4.66, 0.19]},
|
||||||
|
{"center": [-7.25, 4.73, 0.25]},
|
||||||
|
{"center": [6.83, 4.66, -3.46]},
|
||||||
|
{"center": [-7.25, 4.73, -3.4]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-0.22, 2.83, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-0.22, 3.5, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-0.22, 6.31, 2.68]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-0.22, 9.47, 2.68]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-5.87, 3.72, -1.62], "size": [0.94, 1.0, 1.82]},
|
||||||
|
{"center": [5.16, 3.76, -1.44], "size": [0.77, 1.0, 1.82]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": "Bridgit",
|
||||||
|
"play_types": ["melee", "team_flag", "keep_away"],
|
||||||
|
"preview_texture": "bridgitPreview",
|
||||||
|
"terrain_nodes": [
|
||||||
|
{
|
||||||
|
"collide_model": "bridgitLevelBottom",
|
||||||
|
"color_texture": "bridgitLevelColor",
|
||||||
|
"comment": "Top portion of bridge.",
|
||||||
|
"materials": ["footing"],
|
||||||
|
"model": "bridgitLevelTop"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color_texture": "bridgitLevelColor",
|
||||||
|
"comment": "Bottom portion of bridge with no lighting effects.",
|
||||||
|
"lighting": false,
|
||||||
|
"model": "bridgitLevelBottom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"background": true,
|
||||||
|
"color_texture": "natureBackgroundColor",
|
||||||
|
"comment": "Visible background.",
|
||||||
|
"lighting": false,
|
||||||
|
"model": "natureBackground"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"background": true,
|
||||||
|
"color_texture": "model_bg_tex",
|
||||||
|
"comment": "360 degree bg for vr.",
|
||||||
|
"lighting": false,
|
||||||
|
"model": "bg_vr_fill_model",
|
||||||
|
"vr_only": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bumper": true,
|
||||||
|
"collide_model": "railing_collide_model",
|
||||||
|
"comment": "Invisible railing to help prevent falls.",
|
||||||
|
"materials": ["railing"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collide_model": "collide_bg",
|
||||||
|
"comment": "Collision shape for bg",
|
||||||
|
"materials": ["footing", "friction@10", "death"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
130
dist/ba_data/data/maps/courtyard.json
vendored
Normal file
130
dist/ba_data/data/maps/courtyard.json
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.35, 3.96, -2.18], "size": [16.38, 7.76, 13.39]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom": [
|
||||||
|
{"center": [-0.06, 2.81, 1.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_half_left": [
|
||||||
|
{"center": [-2.05, 2.81, 1.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_half_right": [
|
||||||
|
{"center": [1.86, 2.81, 1.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_left": [
|
||||||
|
{"center": [-3.68, 2.81, 1.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_right": [
|
||||||
|
{"center": [3.59, 2.81, 1.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_left": [
|
||||||
|
{"center": [-6.45, 2.81, -2.32]}
|
||||||
|
],
|
||||||
|
"bot_spawn_left_lower": [
|
||||||
|
{"center": [-6.45, 2.81, -1.51]}
|
||||||
|
],
|
||||||
|
"bot_spawn_left_lower_more": [
|
||||||
|
{"center": [-6.45, 2.81, -0.48]}
|
||||||
|
],
|
||||||
|
"bot_spawn_left_upper": [
|
||||||
|
{"center": [-6.45, 2.81, -3.18]}
|
||||||
|
],
|
||||||
|
"bot_spawn_left_upper_more": [
|
||||||
|
{"center": [-6.45, 2.81, -4.01]}
|
||||||
|
],
|
||||||
|
"bot_spawn_right": [
|
||||||
|
{"center": [6.54, 2.81, -2.32]}
|
||||||
|
],
|
||||||
|
"bot_spawn_right_lower": [
|
||||||
|
{"center": [6.54, 2.81, -1.4]}
|
||||||
|
],
|
||||||
|
"bot_spawn_right_lower_more": [
|
||||||
|
{"center": [6.54, 2.81, -0.36]}
|
||||||
|
],
|
||||||
|
"bot_spawn_right_upper": [
|
||||||
|
{"center": [6.54, 2.81, -3.13]}
|
||||||
|
],
|
||||||
|
"bot_spawn_right_upper_more": [
|
||||||
|
{"center": [6.54, 2.81, -3.98]}
|
||||||
|
],
|
||||||
|
"bot_spawn_top": [
|
||||||
|
{"center": [-0.06, 2.81, -5.83]}
|
||||||
|
],
|
||||||
|
"bot_spawn_top_half_left": [
|
||||||
|
{"center": [-1.49, 2.81, -5.83]}
|
||||||
|
],
|
||||||
|
"bot_spawn_top_half_right": [
|
||||||
|
{"center": [1.6, 2.81, -5.83]}
|
||||||
|
],
|
||||||
|
"bot_spawn_top_left": [
|
||||||
|
{"center": [-3.12, 2.81, -5.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_top_right": [
|
||||||
|
{"center": [3.4, 2.81, -5.95]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_bottom_left": [
|
||||||
|
{"center": [-6.13, 3.33, 1.91]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_bottom_right": [
|
||||||
|
{"center": [6.37, 3.33, 1.8]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_top_left": [
|
||||||
|
{"center": [-6.13, 3.33, -6.57]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_top_middle": [
|
||||||
|
{"center": [0.08, 4.27, -8.52]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_top_middle_left": [
|
||||||
|
{"center": [-1.27, 4.27, -8.52]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_top_middle_right": [
|
||||||
|
{"center": [1.13, 4.27, -8.52]}
|
||||||
|
],
|
||||||
|
"bot_spawn_turret_top_right": [
|
||||||
|
{"center": [6.37, 3.33, -6.6]}
|
||||||
|
],
|
||||||
|
"edge_box": [
|
||||||
|
{"center": [0.0, 1.04, -2.14], "size": [12.02, 11.41, 7.81]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-6.23, 3.77, -5.16], "size": [1.48, 1.0, 0.07]},
|
||||||
|
{"center": [6.29, 3.77, -4.92], "size": [1.42, 1.0, 0.07]},
|
||||||
|
{"center": [-0.02, 4.4, -6.96], "size": [1.51, 1.0, 0.25]},
|
||||||
|
{"center": [-0.02, 3.79, 3.45], "size": [4.99, 1.0, 0.15]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-5.97, 2.82, -2.43]},
|
||||||
|
{"center": [5.91, 2.8, -2.22]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.25, 2.78, -2.64]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.26, 4.9, -3.54], "size": [29.24, 14.2, 29.93]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-3.56, 3.17, 0.37]},
|
||||||
|
{"center": [3.63, 3.17, 0.41]},
|
||||||
|
{"center": [3.63, 3.17, -4.99]},
|
||||||
|
{"center": [-3.56, 3.17, -5.02]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [0.52, 0.02, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [0.52, 1.21, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [0.52, 6.36, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [0.52, 10.12, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-7.51, 3.8, -2.1], "size": [0.09, 1.0, 2.2]},
|
||||||
|
{"center": [7.46, 3.77, -1.84], "size": [0.03, 1.0, 2.22]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
48
dist/ba_data/data/maps/crag_castle.json
vendored
Normal file
48
dist/ba_data/data/maps/crag_castle.json
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.7, 6.56, -3.15], "size": [16.74, 14.95, 11.6]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-4.04, 7.55, -3.54], "size": [2.47, 1.16, 0.18]},
|
||||||
|
{"center": [5.43, 7.58, -3.5], "size": [2.42, 1.13, 0.18]},
|
||||||
|
{"center": [4.86, 9.31, -6.01], "size": [1.62, 1.13, 0.18]},
|
||||||
|
{"center": [-3.63, 9.31, -6.01], "size": [1.62, 1.13, 0.18]},
|
||||||
|
{"center": [-2.41, 5.93, 0.03], "size": [1.62, 1.13, 0.18]},
|
||||||
|
{"center": [3.52, 5.93, 0.03], "size": [1.62, 1.13, 0.18]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-1.9, 9.36, -6.44]},
|
||||||
|
{"center": [3.24, 9.32, -6.39]},
|
||||||
|
{"center": [-6.88, 7.48, 0.21]},
|
||||||
|
{"center": [8.19, 7.48, 0.15]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.63, 6.22, -0.04]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.48, 9.09, -3.27], "size": [22.96, 9.91, 14.18]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [7.92, 7.84, -5.99]},
|
||||||
|
{"center": [-0.7, 7.88, -6.07]},
|
||||||
|
{"center": [1.86, 7.89, -6.08]},
|
||||||
|
{"center": [-6.67, 7.99, -6.12]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-5.17, 7.55, -3.54], "size": [1.06, 1.16, 0.18]},
|
||||||
|
{"center": [6.2, 7.58, -3.5], "size": [1.01, 1.13, 0.18]}
|
||||||
|
],
|
||||||
|
"spawn_by_flag": [
|
||||||
|
{"center": [-2.87, 9.36, -6.04]},
|
||||||
|
{"center": [4.31, 9.36, -6.04]},
|
||||||
|
{"center": [-6.63, 7.51, -0.59]},
|
||||||
|
{"center": [7.87, 7.51, -0.59]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-5.04, 10.01, -6.16]},
|
||||||
|
{"center": [6.2, 10.01, -6.16]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
46
dist/ba_data/data/maps/doom_shroom.json
vendored
Normal file
46
dist/ba_data/data/maps/doom_shroom.json
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.47, 2.32, -3.22], "size": [21.35, 10.26, 14.67]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-5.83, 2.3, -3.45], "size": [1.0, 1.0, 2.68]},
|
||||||
|
{"center": [6.5, 2.4, -3.57], "size": [1.0, 1.0, 2.68]},
|
||||||
|
{"center": [0.88, 2.31, -0.36], "size": [4.46, 1.0, 0.27]},
|
||||||
|
{"center": [0.88, 2.31, -7.12], "size": [4.46, 1.0, 0.27]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-7.15, 2.25, -3.43]},
|
||||||
|
{"center": [8.1, 2.32, -3.55]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.6, 2.37, -4.24]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.46, 1.33, -3.81], "size": [27.75, 14.45, 22.99]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [5.18, 4.28, -7.28]},
|
||||||
|
{"center": [-3.24, 4.16, -0.32]},
|
||||||
|
{"center": [5.08, 4.16, -0.32]},
|
||||||
|
{"center": [-3.4, 4.28, -7.43]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [0.6, -0.23, 3.37]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [0.6, 0.7, 3.37]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [0.6, 5.41, 3.37]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [0.6, 7.89, 3.37]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-5.83, 2.3, -3.45], "size": [1.0, 1.0, 2.68]},
|
||||||
|
{"center": [6.5, 2.4, -3.57], "size": [1.0, 1.0, 2.68]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
42
dist/ba_data/data/maps/football_stadium.json
vendored
Normal file
42
dist/ba_data/data/maps/football_stadium.json
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.0, 1.19, 0.43], "size": [29.82, 11.57, 18.89]}
|
||||||
|
],
|
||||||
|
"edge_box": [
|
||||||
|
{"center": [-0.1, 0.41, 0.43], "size": [22.48, 1.29, 8.99]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-0.08, 0.02, -4.37], "size": [8.9, 1.0, 0.44]},
|
||||||
|
{"center": [-0.08, 0.02, 4.08], "size": [8.9, 1.0, 0.44]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-10.99, 0.06, 0.11]},
|
||||||
|
{"center": [11.01, 0.04, 0.11]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-0.1, 0.04, 0.11]}
|
||||||
|
],
|
||||||
|
"goal": [
|
||||||
|
{"center": [12.22, 1.0, 0.11], "size": [2.0, 2.0, 12.97]},
|
||||||
|
{"center": [-12.16, 1.0, 0.11], "size": [2.0, 2.0, 13.12]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.0, 1.19, 0.43], "size": [42.1, 22.81, 29.77]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [5.41, 0.95, -5.04]},
|
||||||
|
{"center": [-5.56, 0.95, -5.04]},
|
||||||
|
{"center": [5.41, 0.95, 5.15]},
|
||||||
|
{"center": [-5.74, 0.95, 5.15]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-10.04, 0.02, 0.0], "size": [0.5, 1.0, 4.0]},
|
||||||
|
{"center": [9.82, 0.01, 0.0], "size": [0.5, 1.0, 4.0]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-0.08, 0.95, -0.78]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
44
dist/ba_data/data/maps/happy_thoughts.json
vendored
Normal file
44
dist/ba_data/data/maps/happy_thoughts.json
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-1.05, 12.68, -5.4], "size": [34.46, 20.94, 0.69]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-9.3, 8.01, -5.44], "size": [1.56, 1.45, 0.12]},
|
||||||
|
{"center": [7.48, 8.17, -5.61], "size": [1.55, 1.45, 0.04]},
|
||||||
|
{"center": [9.56, 11.31, -5.61], "size": [1.34, 1.45, 0.04]},
|
||||||
|
{"center": [-11.56, 10.99, -5.61], "size": [1.34, 1.45, 0.04]},
|
||||||
|
{"center": [-1.88, 9.46, -5.61], "size": [1.34, 1.45, 0.04]},
|
||||||
|
{"center": [-0.49, 5.08, -5.52], "size": [1.88, 1.45, 0.01]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-11.75, 8.06, -5.52]},
|
||||||
|
{"center": [9.84, 8.19, -5.52]},
|
||||||
|
{"center": [-0.22, 5.01, -5.52]},
|
||||||
|
{"center": [-0.05, 12.73, -5.52]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-0.04, 12.72, -5.52]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-0.87, 9.21, -5.73], "size": [36.1, 26.2, 7.9]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [1.16, 6.75, -5.47]},
|
||||||
|
{"center": [-1.9, 10.56, -5.51]},
|
||||||
|
{"center": [10.56, 12.25, -5.58]},
|
||||||
|
{"center": [-12.34, 12.25, -5.58]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-9.3, 8.01, -5.44], "size": [1.56, 1.45, 0.12]},
|
||||||
|
{"center": [7.48, 8.17, -5.61], "size": [1.55, 1.45, 0.04]}
|
||||||
|
],
|
||||||
|
"spawn_by_flag": [
|
||||||
|
{"center": [-9.3, 8.01, -5.44], "size": [1.56, 1.45, 0.12]},
|
||||||
|
{"center": [7.48, 8.17, -5.61], "size": [1.55, 1.45, 0.04]},
|
||||||
|
{"center": [-1.46, 5.04, -5.54], "size": [0.95, 0.67, 0.09]},
|
||||||
|
{"center": [0.49, 12.74, -5.6], "size": [0.52, 0.52, 0.02]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
39
dist/ba_data/data/maps/hockey_stadium.json
vendored
Normal file
39
dist/ba_data/data/maps/hockey_stadium.json
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.0, 0.8, 0.0], "size": [30.8, 0.6, 13.88]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-0.0, 0.02, -3.82], "size": [7.83, 1.0, 0.16]},
|
||||||
|
{"center": [-0.0, 0.02, 3.56], "size": [7.83, 1.0, 0.06]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-11.22, 0.1, -0.08]},
|
||||||
|
{"center": [11.08, 0.04, -0.08]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-0.02, 0.06, -0.08]}
|
||||||
|
],
|
||||||
|
"goal": [
|
||||||
|
{"center": [8.45, 1.0, 0.0], "size": [0.43, 1.6, 3.0]},
|
||||||
|
{"center": [-8.45, 1.0, 0.0], "size": [0.43, 1.6, 3.0]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.0, 0.8, -0.47], "size": [35.16, 12.19, 21.53]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-3.65, 1.08, -4.77]},
|
||||||
|
{"center": [-3.65, 1.08, 4.6]},
|
||||||
|
{"center": [2.88, 1.08, -4.77]},
|
||||||
|
{"center": [2.88, 1.08, 4.6]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-6.84, 0.02, 0.0], "size": [1.0, 1.0, 3.0]},
|
||||||
|
{"center": [6.86, 0.04, 0.0], "size": [1.0, 1.0, 3.0]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-0.06, 1.08, -4.77]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
84
dist/ba_data/data/maps/lake_frigid.json
vendored
Normal file
84
dist/ba_data/data/maps/lake_frigid.json
vendored
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.62, 3.96, -2.49], "size": [20.62, 7.76, 12.33]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-5.78, 2.6, -2.12], "size": [0.49, 1.0, 2.99]},
|
||||||
|
{"center": [8.33, 2.56, -2.36], "size": [0.49, 1.0, 2.59]},
|
||||||
|
{"center": [-0.02, 2.62, -6.52], "size": [4.45, 1.0, 0.25]},
|
||||||
|
{"center": [-0.02, 2.62, 2.15], "size": [4.99, 1.0, 0.15]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-5.97, 2.61, -2.43]},
|
||||||
|
{"center": [7.47, 2.6, -2.22]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.58, 2.59, -6.08]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.67, 6.09, -2.48], "size": [26.78, 12.5, 19.09]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-3.18, 3.17, 1.53]},
|
||||||
|
{"center": [3.63, 3.17, 1.56]},
|
||||||
|
{"center": [3.63, 3.17, -5.77]},
|
||||||
|
{"center": [-3.18, 3.17, -5.81]}
|
||||||
|
],
|
||||||
|
"race_mine": [
|
||||||
|
{"center": [-5.3, 2.52, 1.96]},
|
||||||
|
{"center": [-5.29, 2.52, -5.87]},
|
||||||
|
{"center": [6.49, 2.52, 1.53]},
|
||||||
|
{"center": [6.78, 2.52, -4.81]},
|
||||||
|
{"center": [1.53, 2.52, -7.24]},
|
||||||
|
{"center": [-1.55, 2.52, -6.39]},
|
||||||
|
{"center": [-4.36, 2.52, -2.05]},
|
||||||
|
{"center": [-0.71, 2.52, -0.13]},
|
||||||
|
{"center": [-0.71, 2.52, 1.28]},
|
||||||
|
{"center": [-0.71, 2.52, 3.11]},
|
||||||
|
{"center": [9.39, 2.52, -1.65]},
|
||||||
|
{"center": [5.75, 2.52, -2.3]},
|
||||||
|
{"center": [6.21, 2.52, -0.81]},
|
||||||
|
{"center": [5.38, 2.52, -4.17]},
|
||||||
|
{"center": [1.5, 2.52, -5.82]},
|
||||||
|
{"center": [-1.69, 2.52, -5.24]},
|
||||||
|
{"center": [-3.87, 2.52, -4.15]},
|
||||||
|
{"center": [-7.41, 2.52, -1.5]},
|
||||||
|
{"center": [-2.19, 2.52, 1.86]},
|
||||||
|
{"center": [8.03, 2.52, -0.01]},
|
||||||
|
{"center": [7.38, 2.52, -5.78]},
|
||||||
|
{"center": [-4.57, 2.52, -5.03]},
|
||||||
|
{"center": [-5.87, 2.52, -0.28]},
|
||||||
|
{"center": [2.79, 2.52, -7.9]},
|
||||||
|
{"center": [5.82, 2.52, -6.59]},
|
||||||
|
{"center": [-3.97, 2.52, -0.04]}
|
||||||
|
],
|
||||||
|
"race_point": [
|
||||||
|
{"center": [0.59, 2.54, 1.54], "size": [0.28, 3.95, 2.29]},
|
||||||
|
{"center": [4.75, 2.49, 1.1], "size": [0.28, 3.95, 2.39]},
|
||||||
|
{"center": [7.45, 2.6, -2.25], "size": [2.17, 3.95, 0.26]},
|
||||||
|
{"center": [5.06, 2.49, -5.82], "size": [0.28, 3.95, 2.39]},
|
||||||
|
{"center": [0.59, 2.68, -6.17], "size": [0.28, 3.95, 2.16]},
|
||||||
|
{"center": [-3.06, 2.49, -6.11], "size": [0.28, 3.95, 2.32]},
|
||||||
|
{"center": [-5.81, 2.58, -2.25], "size": [2.04, 3.95, 0.26]},
|
||||||
|
{"center": [-2.96, 2.49, 1.36], "size": [0.28, 3.95, 2.53]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [0.52, 1.52, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [0.52, 2.52, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [0.52, 4.54, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [0.52, 5.92, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-5.95, 2.52, -2.1], "size": [0.09, 1.0, 2.2]},
|
||||||
|
{"center": [8.08, 2.51, -2.36], "size": [0.03, 1.0, 2.22]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
46
dist/ba_data/data/maps/monkey_face.json
vendored
Normal file
46
dist/ba_data/data/maps/monkey_face.json
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-1.66, 4.13, -1.58], "size": [17.36, 10.49, 12.31]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-8.03, 3.35, -2.54], "size": [0.95, 0.95, 1.18]},
|
||||||
|
{"center": [4.73, 3.31, -2.76], "size": [0.93, 1.0, 1.22]},
|
||||||
|
{"center": [-1.91, 3.33, -6.57], "size": [4.08, 1.0, 0.29]},
|
||||||
|
{"center": [-1.67, 3.33, 2.41], "size": [3.87, 1.0, 0.29]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-8.97, 3.36, -2.8]},
|
||||||
|
{"center": [5.95, 3.35, -2.66]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-1.69, 3.39, -2.24]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-1.62, 6.83, -2.2], "size": [22.52, 12.21, 15.91]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-6.86, 4.43, -6.59]},
|
||||||
|
{"center": [-5.42, 4.23, 2.8]},
|
||||||
|
{"center": [3.15, 4.43, -6.59]},
|
||||||
|
{"center": [1.83, 4.23, 2.8]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-1.88, 0.99, 5.5]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-1.88, 2.88, 5.5]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-1.88, 6.17, 5.5]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-1.88, 10.25, 5.5]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-8.03, 3.35, -2.54], "size": [0.95, 0.95, 1.18]},
|
||||||
|
{"center": [4.73, 3.31, -2.76], "size": [0.93, 1.0, 1.22]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
45
dist/ba_data/data/maps/rampage.json
vendored
Normal file
45
dist/ba_data/data/maps/rampage.json
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.35, 5.62, -4.07], "size": [19.9, 10.34, 8.16]}
|
||||||
|
],
|
||||||
|
"edge_box": [
|
||||||
|
{"center": [0.35, 5.44, -4.1], "size": [12.58, 4.65, 3.61]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [0.5, 5.05, -5.79], "size": [6.63, 1.0, 0.34]},
|
||||||
|
{"center": [0.5, 5.05, -2.44], "size": [6.63, 1.0, 0.34]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-5.89, 5.11, -4.25]},
|
||||||
|
{"center": [6.7, 5.1, -4.26]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.32, 5.11, -4.29]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.45, 4.9, -3.54], "size": [23.55, 14.2, 12.08]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-2.65, 6.43, -4.23]},
|
||||||
|
{"center": [3.54, 6.55, -4.2]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [5.58, 3.14, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [5.58, 4.32, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [5.27, 8.43, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [5.27, 11.93, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-4.75, 5.05, -4.25], "size": [0.92, 1.0, 0.52]},
|
||||||
|
{"center": [5.84, 5.05, -4.26], "size": [0.92, 1.0, 0.52]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
46
dist/ba_data/data/maps/roundabout.json
vendored
Normal file
46
dist/ba_data/data/maps/roundabout.json
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-1.55, 3.19, -2.41], "size": [11.96, 8.86, 9.53]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-4.06, 3.86, -4.61], "size": [0.94, 1.0, 1.42]},
|
||||||
|
{"center": [0.91, 3.85, -4.67], "size": [0.92, 1.0, 1.42]},
|
||||||
|
{"center": [-1.5, 1.5, -0.73], "size": [5.73, 1.0, 0.19]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-3.02, 3.85, -6.7]},
|
||||||
|
{"center": [-0.01, 3.83, -6.68]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-1.51, 1.45, -1.44]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-1.62, 8.76, -2.66], "size": [20.49, 18.92, 13.8]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-6.79, 2.66, 0.01]},
|
||||||
|
{"center": [3.61, 2.66, 0.01]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-1.85, 0.63, 2.27]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-1.85, 1.08, 2.27]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-1.85, 6.05, 2.27]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-1.85, 9.19, 2.27]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-4.06, 3.86, -4.61], "size": [0.94, 1.0, 1.42]},
|
||||||
|
{"center": [0.91, 3.85, -4.67], "size": [0.92, 1.0, 1.42]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-1.51, 2.46, 0.23]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
59
dist/ba_data/data/maps/step_right_up.json
vendored
Normal file
59
dist/ba_data/data/maps/step_right_up.json
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.35, 6.08, -2.27], "size": [22.55, 10.15, 14.66]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-6.99, 5.82, -4.0], "size": [0.41, 1.0, 3.63]},
|
||||||
|
{"center": [7.31, 5.87, -4.0], "size": [0.41, 1.0, 3.63]},
|
||||||
|
{"center": [2.64, 4.79, -4.0], "size": [0.41, 1.0, 3.63]},
|
||||||
|
{"center": [-2.36, 4.79, -4.0], "size": [0.41, 1.0, 3.63]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-6.01, 5.82, -8.18]},
|
||||||
|
{"center": [6.67, 5.82, -0.32]},
|
||||||
|
{"center": [-2.11, 4.79, -3.94]},
|
||||||
|
{"center": [2.69, 4.79, -3.94]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.25, 4.16, -3.69]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.26, 4.9, -3.54], "size": [29.24, 14.2, 29.93]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-5.25, 4.73, 2.82]},
|
||||||
|
{"center": [5.69, 4.73, 2.82]},
|
||||||
|
{"center": [7.9, 6.31, -0.72]},
|
||||||
|
{"center": [-7.22, 6.31, -7.94]},
|
||||||
|
{"center": [-1.83, 5.25, -7.96]},
|
||||||
|
{"center": [2.53, 5.25, -0.41]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [0.52, 2.6, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [0.52, 3.78, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [0.52, 7.32, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [0.52, 11.09, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-4.27, 5.46, -4.0], "size": [0.41, 1.0, 2.2]},
|
||||||
|
{"center": [5.07, 5.44, -4.06], "size": [0.35, 1.0, 2.22]}
|
||||||
|
],
|
||||||
|
"spawn_by_flag": [
|
||||||
|
{"center": [-6.66, 5.98, -6.17], "size": [0.75, 1.0, 0.85]},
|
||||||
|
{"center": [7.39, 5.98, -1.71], "size": [0.75, 1.0, 0.85]},
|
||||||
|
{"center": [-2.11, 4.8, -3.95], "size": [0.75, 1.0, 0.85]},
|
||||||
|
{"center": [2.7, 4.8, -3.95], "size": [0.75, 1.0, 0.85]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [0.26, 4.83, -4.31]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
49
dist/ba_data/data/maps/the_pad.json
vendored
Normal file
49
dist/ba_data/data/maps/the_pad.json
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.35, 4.49, -2.52], "size": [16.65, 8.06, 18.5]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-3.81, 4.38, -8.96], "size": [2.37, 1.0, 0.87]},
|
||||||
|
{"center": [4.47, 4.41, -9.01], "size": [2.71, 1.0, 0.87]},
|
||||||
|
{"center": [6.97, 4.38, -7.42], "size": [0.49, 1.0, 1.6]},
|
||||||
|
{"center": [-6.37, 4.38, -7.42], "size": [0.49, 1.0, 1.6]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-7.03, 4.31, -6.3]},
|
||||||
|
{"center": [7.63, 4.37, -6.29]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.46, 4.38, 3.68]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.26, 4.9, -3.54], "size": [29.24, 14.2, 29.93]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-4.17, 5.28, -6.43]},
|
||||||
|
{"center": [4.43, 5.34, -6.33]},
|
||||||
|
{"center": [-4.2, 5.12, 0.44]},
|
||||||
|
{"center": [4.76, 5.12, 0.35]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-0.29, 2.02, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-0.29, 3.21, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-0.29, 6.06, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-0.29, 9.83, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-3.9, 4.38, -8.96], "size": [1.66, 1.0, 0.87]},
|
||||||
|
{"center": [4.78, 4.41, -9.01], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [0.46, 4.04, -6.57]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
49
dist/ba_data/data/maps/tip_top.json
vendored
Normal file
49
dist/ba_data/data/maps/tip_top.json
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [0.0, 7.14, -0.02], "size": [21.13, 4.96, 16.69]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-4.21, 6.97, -3.79], "size": [0.39, 1.16, 0.3]},
|
||||||
|
{"center": [7.38, 5.21, -2.79], "size": [1.16, 1.16, 1.16]},
|
||||||
|
{"center": [-7.26, 5.46, -3.1], "size": [1.16, 1.16, 1.16]},
|
||||||
|
{"center": [0.02, 5.37, 4.08], "size": [1.88, 1.16, 0.2]},
|
||||||
|
{"center": [-1.57, 7.04, -0.48], "size": [0.39, 1.16, 0.3]},
|
||||||
|
{"center": [1.69, 7.04, -0.48], "size": [0.39, 1.16, 0.3]},
|
||||||
|
{"center": [4.4, 6.97, -3.8], "size": [0.39, 1.16, 0.3]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-7.01, 5.42, -2.72]},
|
||||||
|
{"center": [7.17, 5.17, -2.65]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.07, 8.87, -4.99]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-0.21, 7.75, -0.38], "size": [23.81, 13.86, 16.38]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [1.66, 8.05, -1.22]},
|
||||||
|
{"center": [-1.49, 7.91, -1.23]},
|
||||||
|
{"center": [2.63, 6.36, 1.4]},
|
||||||
|
{"center": [-2.7, 6.36, 1.43]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [0.07, 4.0, 6.32]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [0.07, 4.75, 6.32]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [0.07, 9.15, 6.32]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [0.07, 13.82, 6.32]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-7.26, 5.46, -3.1], "size": [1.16, 1.16, 1.16]},
|
||||||
|
{"center": [7.38, 5.21, -2.79], "size": [1.16, 1.16, 1.16]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
76
dist/ba_data/data/maps/tower_d.json
vendored
Normal file
76
dist/ba_data/data/maps/tower_d.json
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-0.47, 2.89, -1.51], "size": [17.9, 6.19, 15.96]}
|
||||||
|
],
|
||||||
|
"b": [
|
||||||
|
{"center": [-4.83, 2.58, -2.35], "size": [0.94, 2.75, 7.27]},
|
||||||
|
{"center": [4.74, 2.58, -3.34], "size": [0.82, 2.75, 7.22]},
|
||||||
|
{"center": [6.42, 2.58, -4.42], "size": [0.83, 4.53, 9.17]},
|
||||||
|
{"center": [-6.65, 3.23, -3.06], "size": [0.94, 2.75, 8.93]},
|
||||||
|
{"center": [3.54, 2.58, -2.37], "size": [0.63, 2.75, 5.33]},
|
||||||
|
{"center": [5.76, 2.58, 1.15], "size": [2.3, 2.18, 0.5]},
|
||||||
|
{"center": [-2.87, 2.58, -1.56], "size": [0.94, 2.75, 5.92]},
|
||||||
|
{"center": [-0.69, 4.76, -5.32], "size": [24.86, 9.0, 13.43]},
|
||||||
|
{"center": [-0.02, 2.86, -0.95], "size": [4.9, 3.04, 6.14]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_left": [
|
||||||
|
{"center": [-7.4, 1.62, 5.38], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"bot_spawn_bottom_right": [
|
||||||
|
{"center": [6.49, 1.62, 5.38], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"bot_spawn_start": [
|
||||||
|
{"center": [-9.0, 3.15, 0.31], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"edge_box": [
|
||||||
|
{"center": [-0.65, 3.19, 4.1], "size": [14.24, 1.47, 2.9]},
|
||||||
|
{"center": [-0.14, 2.3, 0.35], "size": [1.74, 1.06, 4.91]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [0.1, 2.71, -0.36], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-7.75, 3.14, 0.27]},
|
||||||
|
{"center": [6.85, 2.25, 0.38]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [0.02, 2.23, -6.31]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [0.26, 4.9, -3.54], "size": [29.24, 14.2, 29.93]}
|
||||||
|
],
|
||||||
|
"powerup_region": [
|
||||||
|
{"center": [0.35, 4.04, 3.41], "size": [12.49, 0.38, 1.62]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [-4.93, 2.4, 2.88]},
|
||||||
|
{"center": [-1.96, 2.4, 3.75]},
|
||||||
|
{"center": [1.65, 2.4, 3.75]},
|
||||||
|
{"center": [4.4, 2.4, 2.88]}
|
||||||
|
],
|
||||||
|
"score_region": [
|
||||||
|
{"center": [8.38, 3.05, 0.51], "size": [1.28, 1.37, 0.69]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-0.29, 0.95, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-0.29, 2.13, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-0.45, 6.06, 5.34]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-0.29, 9.83, 5.34]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [0.1, 2.71, -0.36], "size": [1.66, 1.0, 0.87]},
|
||||||
|
{"center": [0.14, 2.74, -0.34], "size": [1.66, 1.0, 0.87]}
|
||||||
|
],
|
||||||
|
"tnt_loc": [
|
||||||
|
{"center": [0.01, 2.78, 3.89]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
57
dist/ba_data/data/maps/zig_zag.json
vendored
Normal file
57
dist/ba_data/data/maps/zig_zag.json
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
{
|
||||||
|
"format": ["stdmap", 1],
|
||||||
|
"locations": {
|
||||||
|
"area_of_interest_bounds": [
|
||||||
|
{"center": [-1.81, 3.94, -1.61], "size": [23.01, 13.28, 10.01]}
|
||||||
|
],
|
||||||
|
"ffa_spawn": [
|
||||||
|
{"center": [-9.52, 4.65, -3.19], "size": [0.85, 1.0, 1.3]},
|
||||||
|
{"center": [6.22, 4.63, -3.19], "size": [0.88, 1.0, 1.3]},
|
||||||
|
{"center": [-4.43, 3.01, -4.91], "size": [1.53, 1.0, 0.76]},
|
||||||
|
{"center": [1.46, 3.01, -4.91], "size": [1.53, 1.0, 0.76]}
|
||||||
|
],
|
||||||
|
"flag": [
|
||||||
|
{"center": [-9.97, 4.65, -4.97]},
|
||||||
|
{"center": [6.84, 4.65, -4.95]},
|
||||||
|
{"center": [1.16, 2.97, -4.89]},
|
||||||
|
{"center": [-4.22, 3.01, -4.89]}
|
||||||
|
],
|
||||||
|
"flag_default": [
|
||||||
|
{"center": [-1.43, 3.02, 0.88]}
|
||||||
|
],
|
||||||
|
"map_bounds": [
|
||||||
|
{"center": [-1.57, 8.76, -1.31], "size": [28.77, 17.65, 19.52]}
|
||||||
|
],
|
||||||
|
"powerup_spawn": [
|
||||||
|
{"center": [2.56, 4.37, -4.8]},
|
||||||
|
{"center": [-6.02, 4.37, -4.8]},
|
||||||
|
{"center": [5.56, 5.38, -4.8]},
|
||||||
|
{"center": [-8.79, 5.38, -4.82]}
|
||||||
|
],
|
||||||
|
"shadow_lower_bottom": [
|
||||||
|
{"center": [-1.43, 1.68, 4.79]}
|
||||||
|
],
|
||||||
|
"shadow_lower_top": [
|
||||||
|
{"center": [-1.43, 2.55, 4.79]}
|
||||||
|
],
|
||||||
|
"shadow_upper_bottom": [
|
||||||
|
{"center": [-1.43, 6.8, 4.79]}
|
||||||
|
],
|
||||||
|
"shadow_upper_top": [
|
||||||
|
{"center": [-1.43, 8.78, 4.79]}
|
||||||
|
],
|
||||||
|
"spawn": [
|
||||||
|
{"center": [-9.52, 4.65, -3.19], "size": [0.85, 1.0, 1.3]},
|
||||||
|
{"center": [6.22, 4.63, -3.19], "size": [0.88, 1.0, 1.3]}
|
||||||
|
],
|
||||||
|
"spawn_by_flag": [
|
||||||
|
{"center": [-9.52, 4.65, -3.19], "size": [0.85, 1.0, 1.3]},
|
||||||
|
{"center": [6.22, 4.63, -3.19], "size": [0.88, 1.0, 1.3]},
|
||||||
|
{"center": [1.46, 3.01, -4.91], "size": [1.53, 1.0, 0.76]},
|
||||||
|
{"center": [-4.43, 3.01, -4.91], "size": [1.53, 1.0, 0.76]}
|
||||||
|
],
|
||||||
|
"tnt": [
|
||||||
|
{"center": [-1.43, 4.05, 0.04]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
dist/ba_data/fonts/fontSmall0.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall0.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall1.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall1.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall2.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall2.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall3.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall3.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall4.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall4.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall5.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall5.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall6.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall6.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/fonts/fontSmall7.fdata
vendored
Normal file
BIN
dist/ba_data/fonts/fontSmall7.fdata
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/alwaysLandLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/alwaysLandLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/bigGBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/bigGBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/bigGCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/bigGCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/bridgitLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/bridgitLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/bridgitLevelRailingCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/bridgitLevelRailingCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/courtyardLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/courtyardLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/courtyardPlayerWall.cob
vendored
Normal file
BIN
dist/ba_data/models/courtyardPlayerWall.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/cragCastleLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/cragCastleLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/cragCastleLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/cragCastleLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/doomShroomLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/doomShroomLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/doomShroomStemCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/doomShroomStemCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/footballStadiumCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/footballStadiumCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/hockeyStadiumCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/hockeyStadiumCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/lakeFrigidCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/lakeFrigidCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/monkeyFaceLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/monkeyFaceLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/monkeyFaceLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/monkeyFaceLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/natureBackgroundCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/natureBackgroundCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/rampageBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/rampageBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/rampageLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/rampageLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/roundaboutLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/roundaboutLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/roundaboutLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/roundaboutLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/stepRightUpLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/stepRightUpLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/thePadLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/thePadLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/thePadLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/thePadLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/tipTopLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/tipTopLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/tipTopLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/tipTopLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/towerDLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/towerDLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/towerDPlayerWall.cob
vendored
Normal file
BIN
dist/ba_data/models/towerDPlayerWall.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/zigZagLevelBumper.cob
vendored
Normal file
BIN
dist/ba_data/models/zigZagLevelBumper.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/models/zigZagLevelCollide.cob
vendored
Normal file
BIN
dist/ba_data/models/zigZagLevelCollide.cob
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/python-site-packages/__pycache__/filelock.cpython-310.opt-1.pyc
vendored
Normal file
BIN
dist/ba_data/python-site-packages/__pycache__/filelock.cpython-310.opt-1.pyc
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/python-site-packages/__pycache__/typing_extensions.cpython-310.opt-1.pyc
vendored
Normal file
BIN
dist/ba_data/python-site-packages/__pycache__/typing_extensions.cpython-310.opt-1.pyc
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/python-site-packages/_cffi_backend.cpython-310-aarch64-linux-gnu.so
vendored
Normal file
BIN
dist/ba_data/python-site-packages/_cffi_backend.cpython-310-aarch64-linux-gnu.so
vendored
Normal file
Binary file not shown.
BIN
dist/ba_data/python-site-packages/_cffi_backend.cpython-310-x86_64-linux-gnu.so
vendored
Normal file
BIN
dist/ba_data/python-site-packages/_cffi_backend.cpython-310-x86_64-linux-gnu.so
vendored
Normal file
Binary file not shown.
33
dist/ba_data/python-site-packages/_yaml/__init__.py
vendored
Normal file
33
dist/ba_data/python-site-packages/_yaml/__init__.py
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# This is a stub package designed to roughly emulate the _yaml
|
||||||
|
# extension module, which previously existed as a standalone module
|
||||||
|
# and has been moved into the `yaml` package namespace.
|
||||||
|
# It does not perfectly mimic its old counterpart, but should get
|
||||||
|
# close enough for anyone who's relying on it even when they shouldn't.
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
# in some circumstances, the yaml module we imoprted may be from a different version, so we need
|
||||||
|
# to tread carefully when poking at it here (it may not have the attributes we expect)
|
||||||
|
if not getattr(yaml, '__with_libyaml__', False):
|
||||||
|
from sys import version_info
|
||||||
|
|
||||||
|
exc = ModuleNotFoundError if version_info >= (3, 6) else ImportError
|
||||||
|
raise exc("No module named '_yaml'")
|
||||||
|
else:
|
||||||
|
from yaml._yaml import *
|
||||||
|
import warnings
|
||||||
|
warnings.warn(
|
||||||
|
'The _yaml extension module is now located at yaml._yaml'
|
||||||
|
' and its location is subject to change. To use the'
|
||||||
|
' LibYAML-based parser and emitter, import from `yaml`:'
|
||||||
|
' `from yaml import CLoader as Loader, CDumper as Dumper`.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
del warnings
|
||||||
|
# Don't `del yaml` here because yaml is actually an existing
|
||||||
|
# namespace member of _yaml.
|
||||||
|
|
||||||
|
__name__ = '_yaml'
|
||||||
|
# If the module is top-level (i.e. not a part of any specific package)
|
||||||
|
# then the attribute should be set to ''.
|
||||||
|
# https://docs.python.org/3.8/library/types.html
|
||||||
|
__package__ = ''
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue