bacommon package

Functionality and data shared by all Ballistica components.

This includes clients, various servers, tools, etc.

Subpackages

Submodules

bacommon.app module

Common high level values/functionality related to Ballistica apps.

class bacommon.app.AppArchitecture(*values)[source]

Bases: Enum

Processor architecture an app can be running on.

ARM = 'arm'
ARM64 = 'arm64'
X86 = 'x86'
X86_64 = 'x64'
class bacommon.app.AppExperience(*values)[source]

Bases: Enum

A particular experience provided by a Ballistica app.

This is one metric used to isolate different playerbases from each other where there might be no technical barriers doing so. For example, a casual one-hand-playable phone game and an augmented reality tabletop game may both use the same scene-versions and networking-protocols and whatnot, but it would make no sense to allow players of one to join servers of the other. AppExperience can be used to keep these player bases separate.

Generally a single Ballistica app targets a single AppExperience. This is not a technical requirement, however. A single app may support multiple experiences, or there may be multiple apps targeting one experience. Cloud components such as leagues are generally associated with an AppExperience so that they are only visible to client apps designed for that play style, and the same is true for games joinable over the local network, bluetooth, etc.

EMPTY = 'empt'

An experience that is supported everywhere. Used for the default empty AppMode when starting the app, etc.

MELEE = 'mlee'

The traditional BombSquad experience - multiple players using game controllers (or touch screen equivalents) in a single arena small enough for all action to be viewed on a single screen.

REMOTE = 'rmt'

The traditional BombSquad Remote experience; buttons on a touch-screen allowing a mobile device to be used as a game controller.

class bacommon.app.AppInstanceInfo(name: str, name_custom: str | None, engine_version: str, engine_build: int, platform: AppPlatform, variant: AppVariant, architecture: AppArchitecture, os_version: str | None, interface_idiom: AppInterfaceIdiom, locale: Locale, device: str | None)[source]

Bases: object

General info about an individual running ballistica app.

architecture: AppArchitecture
device: str | None

OS-specific string describing the device running the app.

engine_build: int
engine_version: str
interface_idiom: AppInterfaceIdiom
locale: Locale
name: str
name_custom: str | None
os_version: str | None
platform: AppPlatform
variant: AppVariant
class bacommon.app.AppInterfaceIdiom(*values)[source]

Bases: Enum

A general form-factor or method of experiencing a Ballistica app.

Note that it may be possible for a running app to switch idioms (for instance if a mobile device or computer is connected to a TV).

DESKTOP = 'dsk'

Large screen with high amount of detail visible; assumed to have keyboard/mouse as primary input.

HANDHELD = 'hnd'

Medium size screen; assumed to have game controller as primary input.

PHONE = 'phn'

Small screen; assumed to have touch as primary input.

TABLET = 'tab'

Medium size screen; assumed to have touch as primary input.

TV = 'tv'

Large screen with medium amount of detail visible; assumed to have game controller as primary input.

XR_HEADSET = 'xrh'

Displayed over or in place of of the real world on a headset; assumed to have hand tracking or spacial controllers as primary input.

XR_SCREEN = 'xrs'

Displayed over or instead of the real world on a screen; assumed to have device movement augmented by physical or touchscreen controls as primary input.

class bacommon.app.AppName(*values)[source]

Bases: Enum

A predefined Ballistica app name.

This encompasses official or well-known apps. Other app projects should set this to CUSTOM and provide a ‘name_custom’ value.

BOMBSQUAD = 'bs'
CUSTOM = 'c'
class bacommon.app.AppPlatform(*values)[source]

Bases: Enum

Overall platform a build can target.

Each distinct flavor of an app has a unique combination of AppPlatform and AppVariant. Generally platform describes a set of hardware, while variant describes a destination or purpose for the build.

ANDROID = 'andr'
IOS = 'ios'
LINUX = 'lin'
MAC = 'mac'
TVOS = 'tvos'
WINDOWS = 'win'
class bacommon.app.AppVariant(*values)[source]

Bases: Enum

A unique Ballistica build type within a single platform.

Each distinct flavor of an app has a unique combination of AppPlatform and AppVariant. Generally platform describes a set of hardware, while variant describes a destination or purpose for the build.

AMAZON_APPSTORE = 'amzn'
APPLE_APP_STORE = 'appl'
ARCADE = 'arcd'
DEMO = 'demo'
EPIC_GAMES_STORE = 'epic'
GENERIC = 'gen'

Default builds.

GOOGLE_PLAY = 'gpl'
META = 'meta'
STEAM = 'stm'
TEST = 'tst'

Builds intended for public testing (may have some extra checks or logging enabled).

WINDOWS_STORE = 'wins'

bacommon.assets module

Functionality related to cloud based assets.

class bacommon.assets.AssetPackageBuildState(in_progress_builds: list[str] = <factory>, initial_build_count: int = 0, error: str | None = None)[source]

Bases: object

Contains info about an in-progress asset cloud build.

error: str | None = None
in_progress_builds: list[str]
initial_build_count: int = 0
class bacommon.assets.AssetPackageFlavor(*values)[source]

Bases: Enum

Flavors for asset package outputs for different platforms/etc.

DESKTOP = 'desktop'
MOBILE = 'mobile'
class bacommon.assets.AssetPackageFlavorManifest(cloudfiles: dict[str, str] = <factory>)[source]

Bases: object

A manifest of asset info for a specific flavor of an asset package.

cloudfiles: dict[str, str]
class bacommon.assets.AssetType(*values)[source]

Bases: Enum

Types for individual assets within a package.

COLLISION_MESH = 'collision_mesh'
CUBE_TEXTURE = 'cube_texture'
DATA = 'data'
MESH = 'mesh'
SOUND = 'sound'
TEXTURE = 'texture'

bacommon.bacloud module

Functionality related to the bacloud tool.

class bacommon.bacloud.RequestData(command: str, token: str | None, payload: dict, tzoffset: float, isatty: bool)[source]

Bases: object

Request sent to bacloud server.

command: str
isatty: bool
payload: dict
token: str | None
tzoffset: float
class bacommon.bacloud.ResponseData(message: str | None = None, message_end: str = '\n', error: str | None = None, delay_seconds: float = 0.0, login: str | None = None, logout: bool = False, dir_manifest: str | None = None, uploads: tuple[list[str], str, dict] | None = None, uploads_inline: list[str] | None = None, deletes: list[str] | None = None, downloads: Downloads | None = None, downloads_inline: dict[str, bytes] | None = None, dir_prune_empty: str | None = None, open_url: str | None = None, input_prompt: tuple[str, bool] | None = None, end_message: str | None = None, end_message_end: str = '\n', end_command: tuple[str, dict] | None = None)[source]

Bases: object

Response sent from the bacloud server to the client.

class Downloads(basepath: str | None, cmd: str, baseargs: dict[str, str], entries: list[Entry])[source]

Bases: object

Info about downloads included in a response.

class Entry(path: str, args: dict[str, str])[source]

Bases: object

Individual download.

args: dict[str, str]

Args include with this particular request (combined with baseargs).

path: str
baseargs: dict[str, str]

Args that should be included with all download requests.

basepath: str | None

If present, will be prepended to all entry paths via os.path.join.

cmd: str

Server command that should be called for each download. The server command is expected to respond with a downloads_inline containing a single ‘default’ entry. In the future this may be expanded to a more streaming-friendly process.

entries: list[Entry]

Everything that should be downloaded.

delay_seconds: float = 0.0

How long to wait before proceeding with remaining response (can be useful when waiting for server progress in a loop).

deletes: list[str] | None = None

If present, file paths that should be deleted on the client.

dir_manifest: str | None = None

If present, client should generate a manifest of this dir. It should be added to end_command args as ‘manifest’.

dir_prune_empty: str | None = None

If present, all empty dirs under this one should be removed.

downloads: Downloads | None = None

If present, describes files the client should individually request from the server if not already present on the client.

downloads_inline: dict[str, bytes] | None = None

If present, pathnames mapped to gzipped data to be written to the client. This should only be used for relatively small files as they are all included inline as part of the response.

end_command: tuple[str, dict] | None = None

If present, this command is run with these args at the end of response processing.

end_message: str | None = None

If present, a message that should be printed after all other response processing is done.

end_message_end: str = '\n'

End arg for end_message print() call.

error: str | None = None

If present, client should abort with this error message.

input_prompt: tuple[str, bool] | None = None

If present, a line of input is read and placed into end_command args as ‘input’. The first value is the prompt printed before reading and the second is whether it should be read as a password (without echoing to the terminal).

login: str | None = None

If present, a token that should be stored client-side and passed with subsequent commands.

logout: bool = False

If True, any existing client-side token should be discarded.

message: str | None = None

If present, client should print this message before any other response processing (including error handling) occurs.

message_end: str = '\n'

End arg for message print() call.

open_url: str | None = None

If present, url to display to the user.

uploads: tuple[list[str], str, dict] | None = None

If present, client should upload the requested files (arg1) individually to a server command (arg2) with provided args (arg3).

uploads_inline: list[str] | None = None

If present, a list of pathnames that should be gzipped and uploaded to an ‘uploads_inline’ bytes dict in end_command args. This should be limited to relatively small files.

bacommon.bacloud.asset_file_cache_path(filehash: str) str[source]

Given a sha256 hex file hash, return a storage path.

bacommon.bs module

BombSquad specific bits.

class bacommon.bs.BasicClientUI(components: list[BasicClientUIComponent], interaction_style: InteractionStyle = InteractionStyle.BUTTON_POSITIVE, button_label_positive: ButtonLabel = ButtonLabel.OK, button_label_negative: ButtonLabel = ButtonLabel.CANCEL)[source]

Bases: ClientUI

A basic UI for the client.

class ButtonLabel(*values)[source]

Bases: Enum

Distinct button labels we support.

ACCEPT = 'ac'
APPLY = 'a'
CANCEL = 'c'
CLAIM = 'cl'
DECLINE = 'dn'
DISCARD = 'd'
IGNORE = 'ig'
OK = 'o'
UNKNOWN = 'u'
class InteractionStyle(*values)[source]

Bases: Enum

Overall interaction styles we support.

BUTTON_POSITIVE = 'p'
BUTTON_POSITIVE_NEGATIVE = 'pn'
UNKNOWN = 'u'
button_label_negative: ButtonLabel = 'c'
button_label_positive: ButtonLabel = 'o'
components: list[BasicClientUIComponent]
contains_unknown_elements() bool[source]

Whether something within us is an unknown type or enum.

classmethod get_type_id() ClientUITypeID[source]

Return the type-id for this subclass.

interaction_style: InteractionStyle = 'p'
class bacommon.bs.BasicClientUIBsClassicTourneyResult(tournament_id: str, game: str, players: int, rank: int, trophy: str | None, prizes: list[DisplayItemWrapper])[source]

Bases: BasicClientUIComponent

Show info about a classic tourney.

game: str
classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

players: int
prizes: list[DisplayItemWrapper]
rank: int
tournament_id: str
trophy: str | None
class bacommon.bs.BasicClientUIComponent[source]

Bases: IOMultiType[BasicClientUIComponentTypeID]

Top level class for our multitype.

classmethod get_type(type_id: BasicClientUIComponentTypeID) type[BasicClientUIComponent][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

classmethod get_unknown_type_fallback() BasicClientUIComponent[source]

Return a fallback object in cases of unrecognized types.

This can allow newer data to remain readable in older environments. Use caution with this option, however, as it effectively modifies data.

Bases: BasicClientUIComponent

Show a link in the inbox message.

classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

label: str
spacing_bottom: float = 0.0
spacing_top: float = 0.0
subs: list[str]
url: str
class bacommon.bs.BasicClientUIComponentText(text: str, subs: list[str] = <factory>, scale: float = 1.0, color: tuple[float, float, float, float] = (1.0, 1.0, 1.0, 1.0), spacing_top: float = 0.0, spacing_bottom: float = 0.0)[source]

Bases: BasicClientUIComponent

Show some text in the inbox message.

color: tuple[float, float, float, float] = (1.0, 1.0, 1.0, 1.0)
classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

scale: float = 1.0
spacing_bottom: float = 0.0
spacing_top: float = 0.0
subs: list[str]
text: str
class bacommon.bs.BasicClientUIComponentTypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

BS_CLASSIC_TOURNEY_RESULT = 'ct'
DISPLAY_ITEMS = 'di'
EXPIRE_TIME = 'd'
TEXT = 't'
UNKNOWN = 'u'
class bacommon.bs.BasicClientUIComponentUnknown[source]

Bases: BasicClientUIComponent

An unknown basic client component type.

In practice these should never show up since the master-server generates these on the fly for the client and so should not send clients one they can’t digest.

classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.BasicClientUIDisplayItems(items: list[DisplayItemWrapper], width: float = 100.0, spacing_top: float = 0.0, spacing_bottom: float = 0.0)[source]

Bases: BasicClientUIComponent

Show some display-items.

classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

items: list[DisplayItemWrapper]
spacing_bottom: float = 0.0
spacing_top: float = 0.0
width: float = 100.0
class bacommon.bs.BasicClientUIExpireTime(time: datetime, spacing_top: float = 0.0, spacing_bottom: float = 0.0)[source]

Bases: BasicClientUIComponent

Show expire-time.

classmethod get_type_id() BasicClientUIComponentTypeID[source]

Return the type-id for this subclass.

spacing_bottom: float = 0.0
spacing_top: float = 0.0
time: datetime
class bacommon.bs.ChestActionMessage(action: Action, token_payment: int, chest_id: str)[source]

Bases: Message

Request action about a chest.

class Action(*values)[source]

Bases: Enum

Types of actions we can request.

AD = 'ad'
UNLOCK = 'u'
action: Action
chest_id: str
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

token_payment: int
class bacommon.bs.ChestActionResponse(tokens_charged: int = 0, contents: list[~bacommon.bs.DisplayItemWrapper] | None = None, prizeindex: int = 0, error: str | None = None, warning: str | None = None, success_msg: str | None = None, effects: list[~bacommon.bs.ClientEffect] = <factory>)[source]

Bases: Response

Here’s the results of that action you asked for, boss.

contents: list[DisplayItemWrapper] | None = None
effects: list[ClientEffect]
error: str | None = None
prizeindex: int = 0
success_msg: str | None = None
tokens_charged: int = 0
warning: str | None = None
class bacommon.bs.ChestDisplayItem(appearance: ClassicChestAppearance)[source]

Bases: DisplayItem

Display a chest.

appearance: ClassicChestAppearance
get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.ChestInfoMessage(chest_id: str)[source]

Bases: Message

Request info about a chest.

chest_id: str
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.bs.ChestInfoResponse(chest: Chest | None, user_tokens: int | None)[source]

Bases: Response

Here’s that chest info you asked for, boss.

class Chest(appearance: ClassicChestAppearance, unlock_tokens: int, unlock_time: datetime.datetime, prizesets: list[PrizeSet], ad_allow: bool)[source]

Bases: object

A lovely chest.

class PrizeSet(weight: float, contents: list[DisplayItemWrapper])[source]

Bases: object

A possible set of prizes for this chest.

contents: list[DisplayItemWrapper]
weight: float
ad_allow: bool
appearance: ClassicChestAppearance
prizesets: list[PrizeSet]
unlock_time: datetime.datetime
unlock_tokens: int
chest: Chest | None
user_tokens: int | None
class bacommon.bs.ClassicAccountLiveData(tickets: int, tokens: int, gold_pass: bool, remove_ads: bool, achievements: int, achievements_total: int, league_type: LeagueType | None, league_num: int | None, league_rank: int | None, level: int, xp: int, xpmax: int, inbox_count: int, inbox_count_is_max: bool, chests: dict[str, Chest])[source]

Bases: object

Live account data fed to the client in the bs classic app mode.

class Chest(appearance: ClassicChestAppearance, unlock_time: datetime, ad_allow_time: datetime | None)[source]

Bases: object

A lovely chest.

ad_allow_time: datetime | None
appearance: ClassicChestAppearance
unlock_time: datetime
class LeagueType(*values)[source]

Bases: Enum

Type of league we are in.

BRONZE = 'b'
DIAMOND = 'd'
GOLD = 'g'
SILVER = 's'
achievements: int
achievements_total: int
chests: dict[str, Chest]
gold_pass: bool
inbox_count: int
inbox_count_is_max: bool
league_num: int | None
league_rank: int | None
league_type: LeagueType | None
level: int
remove_ads: bool
tickets: int
tokens: int
xp: int
xpmax: int
class bacommon.bs.ClassicChestAppearance(*values)[source]

Bases: Enum

Appearances bombsquad classic chests can have.

DEFAULT = 'd'
L1 = 'l1'
L2 = 'l2'
L3 = 'l3'
L4 = 'l4'
L5 = 'l5'
L6 = 'l6'
UNKNOWN = 'u'
property pretty_name: str

Pretty name for the chest in English.

class bacommon.bs.ClientEffect[source]

Bases: IOMultiType[ClientEffectTypeID]

Something that can happen on the client.

This can include screen messages, sounds, visual effects, etc.

classmethod get_type(type_id: ClientEffectTypeID) type[ClientEffect][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

classmethod get_unknown_type_fallback() ClientEffect[source]

Return a fallback object in cases of unrecognized types.

This can allow newer data to remain readable in older environments. Use caution with this option, however, as it effectively modifies data.

class bacommon.bs.ClientEffectChestWaitTimeAnimation(chestid: str, duration: float, startvalue: datetime, endvalue: datetime)[source]

Bases: ClientEffect

Animate chest wait time changing.

chestid: str
duration: float
endvalue: datetime
classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

startvalue: datetime
class bacommon.bs.ClientEffectDelay(seconds: float)[source]

Bases: ClientEffect

Delay effect processing.

classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

seconds: float
class bacommon.bs.ClientEffectScreenMessage(message: str, subs: list[str], color: tuple[float, float, float] = (1.0, 1.0, 1.0))[source]

Bases: ClientEffect

Display a screen-message.

color: tuple[float, float, float] = (1.0, 1.0, 1.0)
classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

message: str
subs: list[str]
class bacommon.bs.ClientEffectSound(sound: Sound, volume: float = 1.0)[source]

Bases: ClientEffect

Play a sound.

class Sound(*values)[source]

Bases: Enum

Sounds that can be made alongside the message.

CASH_REGISTER = 'c'
ERROR = 'e'
GUN_COCKING = 'g'
POWER_DOWN = 'p'
UNKNOWN = 'u'
classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

sound: Sound
volume: float = 1.0
class bacommon.bs.ClientEffectTicketsAnimation(duration: float, startvalue: int, endvalue: int)[source]

Bases: ClientEffect

Animate tickets count.

duration: float
endvalue: int
classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

startvalue: int
class bacommon.bs.ClientEffectTokensAnimation(duration: float, startvalue: int, endvalue: int)[source]

Bases: ClientEffect

Animate tokens count.

duration: float
endvalue: int
classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

startvalue: int
class bacommon.bs.ClientEffectTypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

CHEST_WAIT_TIME_ANIMATION = 't'
DELAY = 'd'
SCREEN_MESSAGE = 'm'
SOUND = 's'
TICKETS_ANIMATION = 'ta'
TOKENS_ANIMATION = 'toa'
UNKNOWN = 'u'
class bacommon.bs.ClientEffectUnknown[source]

Bases: ClientEffect

Fallback substitute for types we don’t recognize.

classmethod get_type_id() ClientEffectTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.ClientUI[source]

Bases: IOMultiType[ClientUITypeID]

Defines some user interface on the client.

classmethod get_type(type_id: ClientUITypeID) type[ClientUI][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() ClientUITypeID[source]

Return the type-id for this subclass.

classmethod get_unknown_type_fallback() ClientUI[source]

Return a fallback object in cases of unrecognized types.

This can allow newer data to remain readable in older environments. Use caution with this option, however, as it effectively modifies data.

class bacommon.bs.ClientUIAction(*values)[source]

Bases: Enum

Types of actions we can run.

BUTTON_PRESS_NEGATIVE = 'n'
BUTTON_PRESS_POSITIVE = 'p'
class bacommon.bs.ClientUIActionMessage(id: str, action: ClientUIAction)[source]

Bases: Message

Do something to a client ui.

action: ClientUIAction
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

id: str
class bacommon.bs.ClientUIActionResponse(error_type: ErrorType | None, error_message: str | None, effects: list[ClientEffect])[source]

Bases: Response

Did something to that inbox entry, boss.

class ErrorType(*values)[source]

Bases: Enum

Types of errors that may have occurred.

EXPIRED = 'e'
INTERNAL = 'i'
UNKNOWN = 'u'
effects: list[ClientEffect]
error_message: str | None
error_type: ErrorType | None
class bacommon.bs.ClientUITypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

BASIC = 'b'
UNKNOWN = 'u'
class bacommon.bs.ClientUIWrapper(id: str, createtime: datetime, ui: ClientUI)[source]

Bases: object

Wrapper for a ClientUI and its common data.

createtime: datetime
id: str
ui: ClientUI
class bacommon.bs.DisplayItem[source]

Bases: IOMultiType[DisplayItemTypeID]

Some amount of something that can be shown or described.

Used to depict chest contents or other rewards or prices.

get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type(type_id: DisplayItemTypeID) type[DisplayItem][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

classmethod get_unknown_type_fallback() DisplayItem[source]

Return a fallback object in cases of unrecognized types.

This can allow newer data to remain readable in older environments. Use caution with this option, however, as it effectively modifies data.

class bacommon.bs.DisplayItemTypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

CHEST = 'c'
TEST = 's'
TICKETS = 't'
TOKENS = 'k'
UNKNOWN = 'u'
class bacommon.bs.DisplayItemWrapper(item: DisplayItem, description: str, description_subs: list[str] | None)[source]

Bases: object

Wraps a DisplayItem and common info.

description: str
description_subs: list[str] | None
classmethod for_display_item(item: DisplayItem) DisplayItemWrapper[source]

Convenience method to wrap a DisplayItem.

item: DisplayItem
class bacommon.bs.InboxRequestMessage[source]

Bases: Message

Message requesting our inbox.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.bs.InboxRequestResponse(wrappers: list[ClientUIWrapper], error: str | None = None)[source]

Bases: Response

Here’s that inbox contents you asked for, boss.

error: str | None = None
wrappers: list[ClientUIWrapper]
class bacommon.bs.PrivatePartyMessage(need_datacode: bool)[source]

Bases: Message

Message asking about info we need for private-party UI.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

need_datacode: bool
class bacommon.bs.PrivatePartyResponse(success: bool, tokens: int, gold_pass: bool, datacode: str | None)[source]

Bases: Response

Here’s that private party UI info you asked for, boss.

datacode: str | None
gold_pass: bool
success: bool
tokens: int
class bacommon.bs.ScoreSubmitMessage(score_token: str)[source]

Bases: Message

Let the server know we got some score in something.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

score_token: str
class bacommon.bs.ScoreSubmitResponse(effects: list[ClientEffect])[source]

Bases: Response

Did something to that inbox entry, boss.

effects: list[ClientEffect]
class bacommon.bs.TestDisplayItem[source]

Bases: DisplayItem

Fills usable space for a display-item - good for calibration.

get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.TicketsDisplayItem(count: int)[source]

Bases: DisplayItem

Some amount of tickets.

count: int
get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.TokensDisplayItem(count: int)[source]

Bases: DisplayItem

Some amount of tokens.

count: int
get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

class bacommon.bs.UnknownClientUI[source]

Bases: ClientUI

Fallback type for unrecognized entries.

classmethod get_type_id() ClientUITypeID[source]

Return the type-id for this subclass.

class bacommon.bs.UnknownDisplayItem[source]

Bases: DisplayItem

Something we don’t know how to display.

get_description() tuple[str, list[tuple[str, str]]][source]

Return a string description and subs for the item.

These decriptions are baked into the DisplayItemWrapper and should be accessed from there when available. This allows clients to give descriptions even for newer display items they don’t recognize.

classmethod get_type_id() DisplayItemTypeID[source]

Return the type-id for this subclass.

bacommon.build module

Functionality related to game builds.

class bacommon.build.BuildInfoSet(builds: list[Entry] = <factory>)[source]

Bases: object

Set of build infos.

class Entry(filename: str, size: int, version: str, build_number: int, checksum: str, createtime: datetime)[source]

Bases: object

Info about a particular app build.

build_number: int
checksum: str
createtime: datetime
filename: str
size: int
version: str
builds: list[Entry]

bacommon.cloud module

Functionality related to cloud functionality.

class bacommon.cloud.LoginProxyCompleteMessage(proxyid: str)[source]

Bases: Message

Just so you know, we’re done with this proxy.

proxyid: str
class bacommon.cloud.LoginProxyRequestMessage[source]

Bases: Message

Request send to the cloud to ask for a login-proxy.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.LoginProxyRequestResponse(url: str, url_overlay: str, proxyid: str, proxykey: str)[source]

Bases: Response

Response to a request for a login proxy.

proxyid: str
proxykey: str
url: str
url_overlay: str
class bacommon.cloud.LoginProxyStateQueryMessage(proxyid: str, proxykey: str)[source]

Bases: Message

Soo.. how is that login proxy going?

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

proxyid: str
proxykey: str
class bacommon.cloud.LoginProxyStateQueryResponse(state: State, credentials: str | None)[source]

Bases: Response

Here’s the info on that login-proxy you asked about, boss.

class State(*values)[source]

Bases: Enum

States a login-proxy can be in.

FAIL = 'fail'
SUCCESS = 'success'
WAITING = 'waiting'
credentials: str | None
state: State
class bacommon.cloud.ManageAccountMessage(weblocation: WebLocation = WebLocation.ACCOUNT_EDITOR)[source]

Bases: Message

Message asking for a manage-account url.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

weblocation: WebLocation = 'e'
class bacommon.cloud.ManageAccountResponse(url: str | None)[source]

Bases: Response

Here’s that sign-in result you asked for, boss.

url: str | None
class bacommon.cloud.MerchAvailabilityMessage[source]

Bases: Message

Can we show merch link?

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.MerchAvailabilityResponse(url: str | None)[source]

Bases: Response

About that merch…

url: str | None
class bacommon.cloud.PingMessage[source]

Bases: Message

Standard ping.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.PingResponse[source]

Bases: Response

pong.

class bacommon.cloud.SecureDataCheckMessage(data: bytes, signature: bytes)[source]

Bases: Message

Was this data signed by the master-server?.

data: bytes
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

signature: bytes
class bacommon.cloud.SecureDataCheckResponse(result: bool)[source]

Bases: Response

Here’s the result of that data check, boss.

result: bool
class bacommon.cloud.SecureDataCheckerRequest[source]

Bases: Message

Can I get a checker over here?.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.SecureDataCheckerResponse(checker: SecureDataChecker)[source]

Bases: Response

Here’s that checker ya asked for, boss.

checker: SecureDataChecker
class bacommon.cloud.SendInfoMessage(description: str)[source]

Bases: Message

User is using the send-info function

description: str
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.SendInfoResponse(handled: bool, message: str | None = None, legacy_code: str | None = None)[source]

Bases: Response

Response to sending into the server.

handled: bool
legacy_code: str | None = None
message: str | None = None
class bacommon.cloud.SignInMessage(login_type: LoginType, sign_in_token: str, description: str, apptime: float)[source]

Bases: Message

Can I sign in please?

apptime: float
description: str
classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

login_type: LoginType
sign_in_token: str
class bacommon.cloud.SignInResponse(credentials: str | None)[source]

Bases: Response

Here’s that sign-in result you asked for, boss.

credentials: str | None
class bacommon.cloud.StoreQueryMessage[source]

Bases: Message

Message asking about purchasable stuff and store related state.

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

class bacommon.cloud.StoreQueryResponse(result: Result, tokens: int, gold_pass: bool, available_purchases: list[Purchase], token_info_url: str)[source]

Bases: Response

Here’s that store info you asked for, boss.

class Purchase(purchaseid: str)[source]

Bases: object

Info about a purchasable thing.

purchaseid: str
class Result(*values)[source]

Bases: Enum

Our overall result.

ERROR = 'e'
SUCCESS = 's'
available_purchases: list[Purchase]
gold_pass: bool
result: Result
token_info_url: str
tokens: int
class bacommon.cloud.TestMessage(testfoo: int)[source]

Bases: Message

Can I get some of that workspace action?

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

testfoo: int
class bacommon.cloud.TestResponse(testfoo: int)[source]

Bases: Response

Here’s that workspace you asked for, boss.

testfoo: int
class bacommon.cloud.WebLocation(*values)[source]

Bases: Enum

Set of places we can be directed on ballistica.net.

ACCOUNT_DELETE_SECTION = 'd'
ACCOUNT_EDITOR = 'e'
class bacommon.cloud.WorkspaceFetchMessage(workspaceid: str, state: WorkspaceFetchState)[source]

Bases: Message

Can I get some of that workspace action?

classmethod get_response_types() list[type[Response] | None][source]

Return all Response types this Message can return when sent.

The default implementation specifies a None return type.

state: WorkspaceFetchState
workspaceid: str
class bacommon.cloud.WorkspaceFetchResponse(state: ~bacommon.cloud.WorkspaceFetchState, deletes: list[str] = <factory>, downloads_inline: dict[str, bytes] = <factory>, done: bool = False)[source]

Bases: Response

Here’s that workspace you asked for, boss.

deletes: list[str]
done: bool = False
downloads_inline: dict[str, bytes]
state: WorkspaceFetchState
class bacommon.cloud.WorkspaceFetchState(manifest: DirectoryManifest, iteration: int = 0, total_deletes: int = 0, total_downloads: int = 0, total_up_to_date: int | None = None)[source]

Bases: object

Common state data for a workspace fetch.

iteration: int = 0
manifest: DirectoryManifest
total_deletes: int = 0
total_downloads: int = 0
total_up_to_date: int | None = None

bacommon.locale module

Functionality for wrangling locale info.

class bacommon.locale.Locale(*values)[source]

Bases: Enum

A distinct combination of language and possibly country/etc.

Note that some locales here may be superseded by other more specific ones (for instance PORTUGUESE -> PORTUGUESE_BRAZIL), but the originals must continue to exist here since they may remain in use in the wild.

ENGLISH = 'en'

bacommon.loggercontrol module

System for managing loggers.

class bacommon.loggercontrol.LoggerControlConfig(levels: dict[str, int] = <factory>)[source]

Bases: object

A logging level configuration that applies to all loggers.

Any loggers not explicitly contained in the configuration will be set to NOTSET.

apply(*, warn_unexpected_loggers: bool = False, warn_missing_loggers: bool = False, ignore_log_prefixes: list[str] | None = None) None[source]

Apply the config to all Python loggers.

If ‘warn_unexpected_loggers’ is True, warnings will be issues for any loggers not explicitly covered by the config. This is useful to help ensure controls for all possible loggers are present in a UI/etc.

If ‘warn_missing_loggers’ is True, warnings will be issued for any loggers present in the config that are not found at apply time. This can be useful for pruning settings for no longer used loggers.

Warnings for any log names beginning with any strings in ‘ignore_log_prefixes’ will be suppressed. This can allow ignoring loggers associated with submodules for a given package and instead presenting only a top level logger (or none at all).

apply_diff(diffconfig: LoggerControlConfig) LoggerControlConfig[source]

Apply a diff config to ourself.

Note that values that resolve to NOTSET are left intact in the output config. This is so all loggers expected by either the base or diff config to exist can be created if desired/etc.

diff(baseconfig: LoggerControlConfig) LoggerControlConfig[source]

Return a config containing only changes compared to a base config.

Note that this omits all NOTSET values that resolve to NOTSET in the base config.

This diffed config can later be used with apply_diff() against the base config to recreate the state represented by self.

classmethod from_current_loggers() Self[source]

Build a config from the current set of loggers.

get_effective_level(logname: str) int[source]

Given a log name, predict its level if this config is applied.

levels: dict[str, int]
sanity_check_effective_levels() None[source]

Checks existing loggers to make sure they line up with us.

This can be called periodically to ensure that a control-config is properly driving log levels and that nothing else is changing them behind our back.

would_make_changes() bool[source]

Return whether calling apply would change anything.

bacommon.logging module

Logging functionality.

bacommon.logging.get_base_logger_control_config_client() LoggerControlConfig[source]

Return the logger-control-config used by the ballistica client.

This should remain consistent since local logger configurations are stored relative to this.

bacommon.login module

Functionality related to cloud based assets.

class bacommon.login.LoginType(*values)[source]

Bases: Enum

Types of logins available.

EMAIL = 'email'

Email/password

GAME_CENTER = 'game_center'

Apple’s Game Center

GPGS = 'gpgs'

Google Play Game Services

property displayname: str

A human readable name for this value.

property displaynameshort: str

A short human readable name for this value.

bacommon.net module

Network related data and functionality.

class bacommon.net.PrivateHostingConfig(session_type: str = 'ffa', playlist_name: str = 'Unknown', randomize: bool = False, tutorial: bool = False, custom_team_names: tuple[str, str] | None = None, custom_team_colors: tuple[tuple[float, float, float], tuple[float, float, float]] | None = None, playlist: list[dict[str, Any]] | None = None, exit_minutes: float = 120.0, exit_minutes_unclean: float = 180.0, exit_minutes_idle: float = 10.0)[source]

Bases: object

Config provided when hosting a private party.

custom_team_colors: tuple[tuple[float, float, float], tuple[float, float, float]] | None = None
custom_team_names: tuple[str, str] | None = None
exit_minutes: float = 120.0
exit_minutes_idle: float = 10.0
exit_minutes_unclean: float = 180.0
playlist: list[dict[str, Any]] | None = None
playlist_name: str = 'Unknown'
randomize: bool = False
session_type: str = 'ffa'
tutorial: bool = False
class bacommon.net.PrivateHostingState(unavailable_error: str | None = None, party_code: str | None = None, tickets_to_host_now: int = 0, tokens_to_host_now: int = 0, minutes_until_free_host: float | None = None, free_host_minutes_remaining: float | None = None)[source]

Bases: object

Combined state of whether we’re hosting, whether we can, etc.

free_host_minutes_remaining: float | None = None
minutes_until_free_host: float | None = None
party_code: str | None = None
tickets_to_host_now: int = 0
tokens_to_host_now: int = 0
unavailable_error: str | None = None
class bacommon.net.PrivatePartyConnectResult(error: str | None = None, address4: str | None = None, address6: str | None = None, port: int | None = None, password: str | None = None)[source]

Bases: object

Info about a server we get back when connecting.

address4: str | None = None
address6: str | None = None
error: str | None = None
password: str | None = None
port: int | None = None
class bacommon.net.ServerNodeEntry(zone: str, latlong: tuple[float, float] | None, address: str, port: int)[source]

Bases: object

Information about a specific server.

address: str
latlong: tuple[float, float] | None
port: int
zone: str
class bacommon.net.ServerNodeQueryResponse(time: ~datetime.datetime, latlong: tuple[float, float] | None, ping_per_dist: float, max_dist: float, debug_log_seconds: float | None = None, error: str | None = None, servers: list[~bacommon.net.ServerNodeEntry] = <factory>)[source]

Bases: object

A response to a query about server-nodes.

debug_log_seconds: float | None = None
error: str | None = None
latlong: tuple[float, float] | None
max_dist: float
ping_per_dist: float
servers: list[ServerNodeEntry]
time: datetime

bacommon.securedata module

Functionality related to verifying ballistica server generated data.

class bacommon.securedata.SecureDataChecker(starttime: datetime, endtime: datetime, publickeys: list[bytes])[source]

Bases: object

Verifies data as being signed by our master server.

check(data: bytes, signature: bytes) bool[source]

Verify data, returning True if successful.

Note that this call imports and uses the cryptography module and can be slow; it generally should be done in a background thread or on a server.

endtime: datetime
publickeys: list[bytes]
starttime: datetime

bacommon.servermanager module

Functionality related to the server manager script.

class bacommon.servermanager.ChatMessageCommand(message: str, clients: list[int] | None)[source]

Bases: ServerCommand

Chat message from the server.

clients: list[int] | None
message: str
class bacommon.servermanager.ClientListCommand[source]

Bases: ServerCommand

Print a list of clients.

class bacommon.servermanager.KickCommand(client_id: int, ban_time: int | None)[source]

Bases: ServerCommand

Kick a client.

ban_time: int | None
client_id: int
class bacommon.servermanager.ScreenMessageCommand(message: str, color: tuple[float, float, float] | None, clients: list[int] | None)[source]

Bases: ServerCommand

Screen-message from the server.

clients: list[int] | None
color: tuple[float, float, float] | None
message: str
class bacommon.servermanager.ServerCommand[source]

Bases: object

Base class for commands that can be sent to the server.

class bacommon.servermanager.ServerConfig(party_name: str = 'FFA', party_is_public: bool = True, authenticate_clients: bool = True, admins: list[str] = <factory>, enable_default_kick_voting: bool = True, public_ipv4_address: str | None = None, public_ipv6_address: str | None = None, port: int = 43210, max_party_size: int = 6, session_max_players_override: int | None = None, session_type: str = 'ffa', playlist_code: int | None = None, playlist_inline: list[dict[str, ~typing.Any]] | None = None, playlist_shuffle: bool = True, auto_balance_teams: bool = True, coop_campaign: str = 'Easy', coop_level: str = 'Onslaught Training', enable_telnet: bool = False, teams_series_length: int = 7, ffa_series_length: int = 24, stats_url: str | None = None, clean_exit_minutes: float | None = None, unclean_exit_minutes: float | None = None, idle_exit_minutes: float | None = None, show_tutorial: bool = False, team_names: tuple[str, str] | None = None, team_colors: tuple[tuple[float, float, float], tuple[float, float, float]] | None = None, enable_queue: bool = True, protocol_version: int | None = None, stress_test_players: int | None = None, player_rejoin_cooldown: float = 10.0, log_levels: dict[str, str] | None = None)[source]

Bases: object

Configuration for the server manager app (<appname>_server).

admins: list[str]
authenticate_clients: bool = True
auto_balance_teams: bool = True
clean_exit_minutes: float | None = None
coop_campaign: str = 'Easy'
coop_level: str = 'Onslaught Training'
enable_default_kick_voting: bool = True
enable_queue: bool = True
enable_telnet: bool = False
ffa_series_length: int = 24
idle_exit_minutes: float | None = None
log_levels: dict[str, str] | None = None
max_party_size: int = 6
party_is_public: bool = True
party_name: str = 'FFA'
player_rejoin_cooldown: float = 10.0
playlist_code: int | None = None
playlist_inline: list[dict[str, Any]] | None = None
playlist_shuffle: bool = True
port: int = 43210
protocol_version: int | None = None
public_ipv4_address: str | None = None
public_ipv6_address: str | None = None
session_max_players_override: int | None = None
session_type: str = 'ffa'
show_tutorial: bool = False
stats_url: str | None = None
stress_test_players: int | None = None
team_colors: tuple[tuple[float, float, float], tuple[float, float, float]] | None = None
team_names: tuple[str, str] | None = None
teams_series_length: int = 7
unclean_exit_minutes: float | None = None
class bacommon.servermanager.ShutdownCommand(reason: ShutdownReason, immediate: bool)[source]

Bases: ServerCommand

Tells the server to shut down.

immediate: bool
reason: ShutdownReason
class bacommon.servermanager.ShutdownReason(*values)[source]

Bases: Enum

Reason a server is shutting down.

NONE = 'none'
RESTARTING = 'restarting'
class bacommon.servermanager.StartServerModeCommand(config: ServerConfig)[source]

Bases: ServerCommand

Tells the app to switch into ‘server’ mode.

config: ServerConfig

bacommon.transfer module

Functionality related to transferring files/data.

class bacommon.transfer.DirectoryManifest(files: dict[str, DirectoryManifestFile], exists: bool)[source]

Bases: object

Contains a summary of files in a directory.

classmethod create_from_disk(path: Path) DirectoryManifest[source]

Create a manifest from a directory on disk.

exists: bool
files: dict[str, DirectoryManifestFile]
validate() None[source]

Log any odd data in the manifest; for debugging.

class bacommon.transfer.DirectoryManifestFile(hash_sha256: str, size: int)[source]

Bases: object

Describes a file in a manifest.

hash_sha256: str
size: int