mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-10-20 00:00:39 +00:00
sync changes with master
This commit is contained in:
parent
03034e4aa0
commit
de0199ad50
178 changed files with 2191 additions and 1481 deletions
3
dist/ba_data/python/ba/__init__.py
vendored
3
dist/ba_data/python/ba/__init__.py
vendored
|
|
@ -24,6 +24,7 @@ from ba._actor import Actor
|
|||
from ba._player import PlayerInfo, Player, EmptyPlayer, StandLocation
|
||||
from ba._nodeactor import NodeActor
|
||||
from ba._app import App
|
||||
from ba._cloud import CloudSubsystem
|
||||
from ba._coopgame import CoopGameActivity
|
||||
from ba._coopsession import CoopSession
|
||||
from ba._dependency import (Dependency, DependencyComponent, DependencySet,
|
||||
|
|
@ -89,7 +90,7 @@ __all__ = [
|
|||
'clipboard_get_text', 'clipboard_has_text', 'clipboard_is_supported',
|
||||
'clipboard_set_text', 'CollideModel', 'Collision', 'columnwidget',
|
||||
'containerwidget', 'Context', 'ContextCall', 'ContextError',
|
||||
'CoopGameActivity', 'CoopSession', 'Data', 'DeathType',
|
||||
'CloudSubsystem', 'CoopGameActivity', 'CoopSession', 'Data', 'DeathType',
|
||||
'DelegateNotFoundError', 'Dependency', 'DependencyComponent',
|
||||
'DependencyError', 'DependencySet', 'DieMessage', 'do_once', 'DropMessage',
|
||||
'DroppedMessage', 'DualTeamSession', 'emitfx', 'EmptyPlayer', 'EmptyTeam',
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/_accountv1.py
vendored
8
dist/ba_data/python/ba/_accountv1.py
vendored
|
|
@ -11,7 +11,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class AccountV1Subsystem:
|
||||
|
|
@ -23,12 +23,12 @@ class AccountV1Subsystem:
|
|||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.account_tournament_list: Optional[tuple[int, list[str]]] = None
|
||||
self.account_tournament_list: tuple[int, list[str]] | None = None
|
||||
|
||||
# FIXME: should abstract/structure these.
|
||||
self.tournament_info: dict = {}
|
||||
self.league_rank_cache: dict = {}
|
||||
self.last_post_purchase_message_time: Optional[float] = None
|
||||
self.last_post_purchase_message_time: float | None = None
|
||||
|
||||
# If we try to run promo-codes due to launch-args/etc we might
|
||||
# not be signed in yet; go ahead and queue them up in that case.
|
||||
|
|
@ -73,7 +73,7 @@ class AccountV1Subsystem:
|
|||
return self.league_rank_cache.get('info', None)
|
||||
|
||||
def get_league_rank_points(self,
|
||||
data: Optional[dict[str, Any]],
|
||||
data: dict[str, Any] | None,
|
||||
subset: str = None) -> int:
|
||||
"""(internal)"""
|
||||
if data is None:
|
||||
|
|
|
|||
77
dist/ba_data/python/ba/_accountv2.py
vendored
77
dist/ba_data/python/ba/_accountv2.py
vendored
|
|
@ -6,8 +6,10 @@ from __future__ import annotations
|
|||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
class AccountV2Subsystem:
|
||||
|
|
@ -18,10 +20,20 @@ class AccountV2Subsystem:
|
|||
Access the single shared instance of this class at 'ba.app.accounts_v2'.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
||||
# Whether or not everything related to an initial login
|
||||
# (or lack thereof) has completed. This includes things like
|
||||
# workspace syncing. Completion of this is what flips the app
|
||||
# into 'running' state.
|
||||
self._initial_login_completed = False
|
||||
|
||||
self._kicked_off_workspace_load = False
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Should be called at standard on_app_launch time."""
|
||||
|
||||
def set_primary_credentials(self, credentials: Optional[str]) -> None:
|
||||
def set_primary_credentials(self, credentials: str | None) -> None:
|
||||
"""Set credentials for the primary app account."""
|
||||
raise RuntimeError('This should be overridden.')
|
||||
|
||||
|
|
@ -35,17 +47,74 @@ class AccountV2Subsystem:
|
|||
raise RuntimeError('This should be overridden.')
|
||||
|
||||
@property
|
||||
def primary(self) -> Optional[AccountV2Handle]:
|
||||
def primary(self) -> AccountV2Handle | None:
|
||||
"""The primary account for the app, or None if not logged in."""
|
||||
return None
|
||||
|
||||
def get_primary(self) -> Optional[AccountV2Handle]:
|
||||
def do_get_primary(self) -> AccountV2Handle | None:
|
||||
"""Internal - should be overridden by subclass."""
|
||||
return None
|
||||
|
||||
def on_primary_account_changed(self,
|
||||
account: AccountV2Handle | None) -> None:
|
||||
"""Callback run after the primary account changes.
|
||||
|
||||
Will be called with None on log-outs or when new credentials
|
||||
are set but have not yet been verified.
|
||||
"""
|
||||
# Currently don't do anything special on sign-outs.
|
||||
if account is None:
|
||||
return
|
||||
|
||||
# If this new account has a workspace, update it and ask to be
|
||||
# informed when that process completes.
|
||||
if account.workspaceid is not None:
|
||||
assert account.workspacename is not None
|
||||
if (not self._initial_login_completed
|
||||
and not self._kicked_off_workspace_load):
|
||||
self._kicked_off_workspace_load = True
|
||||
_ba.app.workspaces.set_active_workspace(
|
||||
workspaceid=account.workspaceid,
|
||||
workspacename=account.workspacename,
|
||||
on_completed=self._on_set_active_workspace_completed)
|
||||
else:
|
||||
# Don't activate workspaces if we've already told the game
|
||||
# that initial-log-in is done or if we've already kicked
|
||||
# off a workspace load.
|
||||
_ba.screenmessage(
|
||||
f'\'{account.workspacename}\''
|
||||
f' will be activated at next app launch.',
|
||||
color=(1, 1, 0))
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
return
|
||||
|
||||
# Ok; no workspace to worry about; carry on.
|
||||
if not self._initial_login_completed:
|
||||
self._initial_login_completed = True
|
||||
_ba.app.on_initial_login_completed()
|
||||
|
||||
def on_no_initial_primary_account(self) -> None:
|
||||
"""Callback run if the app has no primary account after launch.
|
||||
|
||||
Either this callback or on_primary_account_changed will be called
|
||||
within a few seconds of app launch; the app can move forward
|
||||
with the startup sequence at that point.
|
||||
"""
|
||||
if not self._initial_login_completed:
|
||||
self._initial_login_completed = True
|
||||
_ba.app.on_initial_login_completed()
|
||||
|
||||
def _on_set_active_workspace_completed(self) -> None:
|
||||
if not self._initial_login_completed:
|
||||
self._initial_login_completed = True
|
||||
_ba.app.on_initial_login_completed()
|
||||
|
||||
|
||||
class AccountV2Handle:
|
||||
"""Handle for interacting with a v2 account."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.tag = '?'
|
||||
|
||||
self.workspacename: str | None = None
|
||||
self.workspaceid: str | None = None
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/_achievement.py
vendored
8
dist/ba_data/python/ba/_achievement.py
vendored
|
|
@ -9,7 +9,7 @@ import _ba
|
|||
from ba._error import print_exception
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Union, Optional
|
||||
from typing import Any, Sequence
|
||||
import ba
|
||||
|
||||
# This could use some cleanup.
|
||||
|
|
@ -73,7 +73,7 @@ class AchievementSubsystem:
|
|||
def __init__(self) -> None:
|
||||
self.achievements: list[Achievement] = []
|
||||
self.achievements_to_display: (list[tuple[ba.Achievement, bool]]) = []
|
||||
self.achievement_display_timer: Optional[_ba.Timer] = None
|
||||
self.achievement_display_timer: _ba.Timer | None = None
|
||||
self.last_achievement_display_time: float = 0.0
|
||||
self.achievement_completion_banner_slots: set[int] = set()
|
||||
self._init_achievements()
|
||||
|
|
@ -450,7 +450,7 @@ class Achievement:
|
|||
self._icon_name = icon_name
|
||||
self._icon_color: Sequence[float] = list(icon_color) + [1]
|
||||
self._level_name = level_name
|
||||
self._completion_banner_slot: Optional[int] = None
|
||||
self._completion_banner_slot: int | None = None
|
||||
self._award = award
|
||||
self._hard_mode_only = hard_mode_only
|
||||
|
||||
|
|
@ -534,7 +534,7 @@ class Achievement:
|
|||
def display_name(self) -> ba.Lstr:
|
||||
"""Return a ba.Lstr for this Achievement's name."""
|
||||
from ba._language import Lstr
|
||||
name: Union[ba.Lstr, str]
|
||||
name: ba.Lstr | str
|
||||
try:
|
||||
if self._level_name != '':
|
||||
from ba._campaign import getcampaign
|
||||
|
|
|
|||
16
dist/ba_data/python/ba/_activity.py
vendored
16
dist/ba_data/python/ba/_activity.py
vendored
|
|
@ -16,7 +16,7 @@ from ba._general import Call, verify_object_death
|
|||
from ba._messages import UNHANDLED
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any
|
||||
from typing import Any
|
||||
import ba
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
|
|
@ -139,7 +139,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
|||
assert isinstance(settings, dict)
|
||||
assert _ba.getactivity() is self
|
||||
|
||||
self._globalsnode: Optional[ba.Node] = None
|
||||
self._globalsnode: ba.Node | None = None
|
||||
|
||||
# Player/Team types should have been specified as type args;
|
||||
# grab those.
|
||||
|
|
@ -148,7 +148,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
|||
self._setup_player_and_team_types()
|
||||
|
||||
# FIXME: Relocate or remove the need for this stuff.
|
||||
self.paused_text: Optional[ba.Actor] = None
|
||||
self.paused_text: ba.Actor | None = None
|
||||
|
||||
self._session = weakref.ref(_ba.getsession())
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
|||
self._has_transitioned_in = False
|
||||
self._has_begun = False
|
||||
self._has_ended = False
|
||||
self._activity_death_check_timer: Optional[ba.Timer] = None
|
||||
self._activity_death_check_timer: ba.Timer | None = None
|
||||
self._expired = False
|
||||
self._delay_delete_players: list[PlayerType] = []
|
||||
self._delay_delete_teams: list[TeamType] = []
|
||||
|
|
@ -177,14 +177,14 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
|||
self._actor_refs: list[ba.Actor] = []
|
||||
self._actor_weak_refs: list[weakref.ref[ba.Actor]] = []
|
||||
self._last_prune_dead_actors_time = _ba.time()
|
||||
self._prune_dead_actors_timer: Optional[ba.Timer] = None
|
||||
self._prune_dead_actors_timer: ba.Timer | None = None
|
||||
|
||||
self.teams = []
|
||||
self.players = []
|
||||
|
||||
self.lobby = None
|
||||
self._stats: Optional[ba.Stats] = None
|
||||
self._customdata: Optional[dict] = {}
|
||||
self._stats: ba.Stats | None = None
|
||||
self._customdata: dict | None = {}
|
||||
|
||||
def __del__(self) -> None:
|
||||
|
||||
|
|
@ -396,7 +396,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
|||
"""Return whether ba.Activity.on_transition_out() has been called."""
|
||||
return self._transitioning_out
|
||||
|
||||
def transition_in(self, prev_globals: Optional[ba.Node]) -> None:
|
||||
def transition_in(self, prev_globals: ba.Node | None) -> None:
|
||||
"""Called by Session to kick off transition-in.
|
||||
|
||||
(internal)
|
||||
|
|
|
|||
19
dist/ba_data/python/ba/_activitytypes.py
vendored
19
dist/ba_data/python/ba/_activitytypes.py
vendored
|
|
@ -14,7 +14,6 @@ from ba._player import EmptyPlayer # pylint: disable=W0611
|
|||
from ba._team import EmptyTeam # pylint: disable=W0611
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
import ba
|
||||
from ba._lobby import JoinInfo
|
||||
|
||||
|
|
@ -65,9 +64,9 @@ class JoinActivity(Activity[EmptyPlayer, EmptyTeam]):
|
|||
# In vr mode we don't want stuff moving around.
|
||||
self.use_fixed_vr_overlay = True
|
||||
|
||||
self._background: Optional[ba.Actor] = None
|
||||
self._tips_text: Optional[ba.Actor] = None
|
||||
self._join_info: Optional[JoinInfo] = None
|
||||
self._background: ba.Actor | None = None
|
||||
self._tips_text: ba.Actor | None = None
|
||||
self._join_info: JoinInfo | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
|
|
@ -99,7 +98,7 @@ class TransitionActivity(Activity[EmptyPlayer, EmptyTeam]):
|
|||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._background: Optional[ba.Actor] = None
|
||||
self._background: ba.Actor | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
|
|
@ -127,20 +126,20 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]):
|
|||
inherits_vr_camera_offset = True
|
||||
use_fixed_vr_overlay = True
|
||||
|
||||
default_music: Optional[MusicType] = MusicType.SCORES
|
||||
default_music: MusicType | None = MusicType.SCORES
|
||||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._birth_time = _ba.time()
|
||||
self._min_view_time = 5.0
|
||||
self._allow_server_transition = False
|
||||
self._background: Optional[ba.Actor] = None
|
||||
self._tips_text: Optional[ba.Actor] = None
|
||||
self._background: ba.Actor | None = None
|
||||
self._tips_text: ba.Actor | None = None
|
||||
self._kicked_off_server_shutdown = False
|
||||
self._kicked_off_server_restart = False
|
||||
self._default_show_tips = True
|
||||
self._custom_continue_message: Optional[ba.Lstr] = None
|
||||
self._server_transitioning: Optional[bool] = None
|
||||
self._custom_continue_message: ba.Lstr | None = None
|
||||
self._server_transitioning: bool | None = None
|
||||
|
||||
def on_player_join(self, player: EmptyPlayer) -> None:
|
||||
from ba._general import WeakCall
|
||||
|
|
|
|||
6
dist/ba_data/python/ba/_actor.py
vendored
6
dist/ba_data/python/ba/_actor.py
vendored
|
|
@ -12,7 +12,7 @@ from ba._messages import DieMessage, DeathType, OutOfBoundsMessage, UNHANDLED
|
|||
from ba._error import print_exception, ActivityNotFoundError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Literal
|
||||
from typing import Any, Literal
|
||||
import ba
|
||||
|
||||
TA = TypeVar('TA', bound='Actor')
|
||||
|
|
@ -187,10 +187,10 @@ class Actor:
|
|||
...
|
||||
|
||||
@overload
|
||||
def getactivity(self, doraise: Literal[False]) -> Optional[ba.Activity]:
|
||||
def getactivity(self, doraise: Literal[False]) -> ba.Activity | None:
|
||||
...
|
||||
|
||||
def getactivity(self, doraise: bool = True) -> Optional[ba.Activity]:
|
||||
def getactivity(self, doraise: bool = True) -> ba.Activity | None:
|
||||
"""Return the ba.Activity this Actor is associated with.
|
||||
|
||||
If the Activity no longer exists, raises a ba.ActivityNotFoundError
|
||||
|
|
|
|||
10
dist/ba_data/python/ba/_ads.py
vendored
10
dist/ba_data/python/ba/_ads.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Callable, Any
|
||||
from typing import Callable, Any
|
||||
|
||||
|
||||
class AdsSubsystem:
|
||||
|
|
@ -23,11 +23,11 @@ class AdsSubsystem:
|
|||
def __init__(self) -> None:
|
||||
self.last_ad_network = 'unknown'
|
||||
self.last_ad_network_set_time = time.time()
|
||||
self.ad_amt: Optional[float] = None
|
||||
self.ad_amt: float | None = None
|
||||
self.last_ad_purpose = 'invalid'
|
||||
self.attempted_first_ad = False
|
||||
self.last_in_game_ad_remove_message_show_time: Optional[float] = None
|
||||
self.last_ad_completion_time: Optional[float] = None
|
||||
self.last_in_game_ad_remove_message_show_time: float | None = None
|
||||
self.last_ad_completion_time: float | None = None
|
||||
self.last_ad_was_short = False
|
||||
|
||||
def do_remove_in_game_ads_message(self) -> None:
|
||||
|
|
@ -89,7 +89,7 @@ class AdsSubsystem:
|
|||
show = False # Never show ads during tournaments.
|
||||
|
||||
if show:
|
||||
interval: Optional[float]
|
||||
interval: float | None
|
||||
launch_count = app.config.get('launchCount', 0)
|
||||
|
||||
# If we're seeing short ads we may want to space them differently.
|
||||
|
|
|
|||
94
dist/ba_data/python/ba/_app.py
vendored
94
dist/ba_data/python/ba/_app.py
vendored
|
|
@ -19,13 +19,14 @@ from ba._accountv1 import AccountV1Subsystem
|
|||
from ba._meta import MetadataSubsystem
|
||||
from ba._ads import AdsSubsystem
|
||||
from ba._net import NetworkSubsystem
|
||||
from ba._workspace import WorkspaceSubsystem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import asyncio
|
||||
from typing import Optional, Any, Callable
|
||||
from typing import Any, Callable
|
||||
|
||||
import ba
|
||||
from ba.cloud import CloudSubsystem
|
||||
from ba._cloud import CloudSubsystem
|
||||
from bastd.actor import spazappearance
|
||||
from ba._accountv2 import AccountV2Subsystem
|
||||
|
||||
|
|
@ -49,10 +50,21 @@ class App:
|
|||
|
||||
class State(Enum):
|
||||
"""High level state the app can be in."""
|
||||
|
||||
# Python-level systems being inited but should not interact.
|
||||
LAUNCHING = 0
|
||||
RUNNING = 1
|
||||
PAUSED = 2
|
||||
SHUTTING_DOWN = 3
|
||||
|
||||
# Initial account logins, workspace & asset downloads, etc.
|
||||
LOADING = 1
|
||||
|
||||
# Normal running state.
|
||||
RUNNING = 2
|
||||
|
||||
# App is backgrounded or otherwise suspended.
|
||||
PAUSED = 3
|
||||
|
||||
# App is shutting down.
|
||||
SHUTTING_DOWN = 4
|
||||
|
||||
@property
|
||||
def aioloop(self) -> asyncio.AbstractEventLoop:
|
||||
|
|
@ -208,7 +220,9 @@ class App:
|
|||
|
||||
self.state = self.State.LAUNCHING
|
||||
|
||||
self._app_launched = False
|
||||
self._launch_completed = False
|
||||
self._initial_login_completed = False
|
||||
self._called_on_app_running = False
|
||||
self._app_paused = False
|
||||
|
||||
# Config.
|
||||
|
|
@ -219,7 +233,7 @@ class App:
|
|||
# refreshed/etc.
|
||||
self.fg_state = 0
|
||||
|
||||
self._aioloop: Optional[asyncio.AbstractEventLoop] = None
|
||||
self._aioloop: asyncio.AbstractEventLoop | None = None
|
||||
|
||||
self._env = _ba.env()
|
||||
self.protocol_version: int = self._env['protocol_version']
|
||||
|
|
@ -243,12 +257,12 @@ class App:
|
|||
|
||||
# Misc.
|
||||
self.tips: list[str] = []
|
||||
self.stress_test_reset_timer: Optional[ba.Timer] = None
|
||||
self.stress_test_reset_timer: ba.Timer | None = None
|
||||
self.did_weak_call_warning = False
|
||||
|
||||
self.log_have_new = False
|
||||
self.log_upload_timer_started = False
|
||||
self._config: Optional[ba.AppConfig] = None
|
||||
self._config: ba.AppConfig | None = None
|
||||
self.printed_live_object_warning = False
|
||||
|
||||
# We include this extra hash with shared input-mapping names so
|
||||
|
|
@ -256,13 +270,13 @@ class App:
|
|||
# systems. For instance, different android devices may give different
|
||||
# key values for the same controller type so we keep their mappings
|
||||
# distinct.
|
||||
self.input_map_hash: Optional[str] = None
|
||||
self.input_map_hash: str | None = None
|
||||
|
||||
# Co-op Campaigns.
|
||||
self.campaigns: dict[str, ba.Campaign] = {}
|
||||
|
||||
# Server Mode.
|
||||
self.server: Optional[ba.ServerController] = None
|
||||
self.server: ba.ServerController | None = None
|
||||
|
||||
self.meta = MetadataSubsystem()
|
||||
self.accounts_v1 = AccountV1Subsystem()
|
||||
|
|
@ -273,15 +287,16 @@ class App:
|
|||
self.ui = UISubsystem()
|
||||
self.ads = AdsSubsystem()
|
||||
self.net = NetworkSubsystem()
|
||||
self.workspaces = WorkspaceSubsystem()
|
||||
|
||||
# Lobby.
|
||||
self.lobby_random_profile_index: int = 1
|
||||
self.lobby_random_char_index_offset = random.randrange(1000)
|
||||
self.lobby_account_profile_device_id: Optional[int] = None
|
||||
self.lobby_account_profile_device_id: int | None = None
|
||||
|
||||
# Main Menu.
|
||||
self.main_menu_did_initial_transition = False
|
||||
self.main_menu_last_news_fetch_time: Optional[float] = None
|
||||
self.main_menu_last_news_fetch_time: float | None = None
|
||||
|
||||
# Spaz.
|
||||
self.spaz_appearances: dict[str, spazappearance.Appearance] = {}
|
||||
|
|
@ -300,19 +315,19 @@ class App:
|
|||
self.did_menu_intro = False # FIXME: Move to mainmenu class.
|
||||
self.main_menu_window_refresh_check_count = 0 # FIXME: Mv to mainmenu.
|
||||
self.main_menu_resume_callbacks: list = [] # Can probably go away.
|
||||
self.special_offer: Optional[dict] = None
|
||||
self.special_offer: dict | None = None
|
||||
self.ping_thread_count = 0
|
||||
self.invite_confirm_windows: list[Any] = [] # FIXME: Don't use Any.
|
||||
self.store_layout: Optional[dict[str, list[dict[str, Any]]]] = None
|
||||
self.store_items: Optional[dict[str, dict]] = None
|
||||
self.pro_sale_start_time: Optional[int] = None
|
||||
self.pro_sale_start_val: Optional[int] = None
|
||||
self.store_layout: dict[str, list[dict[str, Any]]] | None = None
|
||||
self.store_items: dict[str, dict] | None = None
|
||||
self.pro_sale_start_time: int | None = None
|
||||
self.pro_sale_start_val: int | None = None
|
||||
|
||||
self.delegate: Optional[ba.AppDelegate] = None
|
||||
self._asyncio_timer: Optional[ba.Timer] = None
|
||||
self.delegate: ba.AppDelegate | None = None
|
||||
self._asyncio_timer: ba.Timer | None = None
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Runs after the app finishes bootstrapping.
|
||||
"""Runs after the app finishes low level bootstrapping.
|
||||
|
||||
(internal)"""
|
||||
# pylint: disable=cyclic-import
|
||||
|
|
@ -326,8 +341,7 @@ class App:
|
|||
from bastd import maps as stdmaps
|
||||
from bastd.actor import spazappearance
|
||||
from ba._generated.enums import TimeType
|
||||
import custom_hooks
|
||||
custom_hooks.on_app_launch()
|
||||
|
||||
|
||||
self._aioloop = _asyncio.setup_asyncio()
|
||||
|
||||
|
|
@ -400,19 +414,25 @@ class App:
|
|||
if not self.headless_mode:
|
||||
_ba.timer(3.0, check_special_offer, timetype=TimeType.REAL)
|
||||
|
||||
self.meta.on_app_launch()
|
||||
self.accounts_v2.on_app_launch()
|
||||
self.accounts_v1.on_app_launch()
|
||||
self.plugins.on_app_launch()
|
||||
|
||||
# See note below in on_app_pause.
|
||||
if self.state != self.State.LAUNCHING:
|
||||
logging.error('on_app_launch found state %s; expected LAUNCHING.',
|
||||
self.state)
|
||||
|
||||
self._app_launched = True
|
||||
self._launch_completed = True
|
||||
self._update_state()
|
||||
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when initially entering the running state."""
|
||||
|
||||
self.meta.on_app_running()
|
||||
self.plugins.on_app_running()
|
||||
import custom_hooks
|
||||
custom_hooks.on_app_running()
|
||||
|
||||
# from ba._dependency import test_depset
|
||||
# test_depset()
|
||||
if bool(False):
|
||||
|
|
@ -422,8 +442,13 @@ class App:
|
|||
if self._app_paused:
|
||||
self.state = self.State.PAUSED
|
||||
else:
|
||||
if self._app_launched:
|
||||
if self._initial_login_completed:
|
||||
self.state = self.State.RUNNING
|
||||
if not self._called_on_app_running:
|
||||
self._called_on_app_running = True
|
||||
self.on_app_running()
|
||||
elif self._launch_completed:
|
||||
self.state = self.State.LOADING
|
||||
else:
|
||||
self.state = self.State.LAUNCHING
|
||||
|
||||
|
|
@ -461,7 +486,7 @@ class App:
|
|||
If there's a foreground host-activity that says it's pausable, tell it
|
||||
to pause ..we now no longer pause if there are connected clients.
|
||||
"""
|
||||
activity: Optional[ba.Activity] = _ba.get_foreground_host_activity()
|
||||
activity: ba.Activity | None = _ba.get_foreground_host_activity()
|
||||
if (activity is not None and activity.allow_pausing
|
||||
and not _ba.have_connected_clients()):
|
||||
from ba._language import Lstr
|
||||
|
|
@ -525,7 +550,7 @@ class App:
|
|||
|
||||
# If we're in a host-session, tell them to end.
|
||||
# This lets them tear themselves down gracefully.
|
||||
host_session: Optional[ba.Session] = _ba.get_foreground_host_session()
|
||||
host_session: ba.Session | None = _ba.get_foreground_host_session()
|
||||
if host_session is not None:
|
||||
|
||||
# Kick off a little transaction so we'll hopefully have all the
|
||||
|
|
@ -611,6 +636,17 @@ class App:
|
|||
_ba.screenmessage(Lstr(resource='errorText'), color=(1, 0, 0))
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
|
||||
def on_initial_login_completed(self) -> None:
|
||||
"""Callback to be run after initial login process (or lack thereof).
|
||||
|
||||
This period includes things such as syncing account workspaces
|
||||
or other data so it may take a substantial amount of time.
|
||||
This should also run after a short amount of time if no login
|
||||
has occurred.
|
||||
"""
|
||||
self._initial_login_completed = True
|
||||
self._update_state()
|
||||
|
||||
def _test_https(self) -> None:
|
||||
"""Testing https support.
|
||||
|
||||
|
|
|
|||
6
dist/ba_data/python/ba/_appdelegate.py
vendored
6
dist/ba_data/python/ba/_appdelegate.py
vendored
|
|
@ -6,7 +6,7 @@ from __future__ import annotations
|
|||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Callable
|
||||
from typing import Callable
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -18,8 +18,8 @@ class AppDelegate:
|
|||
|
||||
def create_default_game_settings_ui(
|
||||
self, gameclass: type[ba.GameActivity],
|
||||
sessiontype: type[ba.Session], settings: Optional[dict],
|
||||
completion_call: Callable[[Optional[dict]], None]) -> None:
|
||||
sessiontype: type[ba.Session], settings: dict | None,
|
||||
completion_call: Callable[[dict | None], None]) -> None:
|
||||
"""Launch a UI to configure the given game config.
|
||||
|
||||
It should manipulate the contents of config and call completion_call
|
||||
|
|
|
|||
5
dist/ba_data/python/ba/_asyncio.py
vendored
5
dist/ba_data/python/ba/_asyncio.py
vendored
|
|
@ -13,12 +13,11 @@ from typing import TYPE_CHECKING
|
|||
import asyncio
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
import ba
|
||||
|
||||
# Our timer and event loop for the ballistica game thread.
|
||||
_asyncio_timer: Optional[ba.Timer] = None
|
||||
_asyncio_event_loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
_asyncio_timer: ba.Timer | None = None
|
||||
_asyncio_event_loop: asyncio.AbstractEventLoop | None = None
|
||||
|
||||
|
||||
def setup_asyncio() -> asyncio.AbstractEventLoop:
|
||||
|
|
|
|||
93
dist/ba_data/python/ba/_cloud.py
vendored
Normal file
93
dist/ba_data/python/ba/_cloud.py
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Functionality related to the cloud."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, overload
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any
|
||||
|
||||
from efro.message import Message, Response
|
||||
import bacommon.cloud
|
||||
|
||||
# TODO: Should make it possible to define a protocol in bacommon.cloud and
|
||||
# autogenerate this. That would give us type safety between this and
|
||||
# internal protocols.
|
||||
|
||||
|
||||
class CloudSubsystem:
|
||||
"""Manages communication with cloud components."""
|
||||
|
||||
def is_connected(self) -> bool:
|
||||
"""Return whether a connection to the cloud is present.
|
||||
|
||||
This is a good indicator (though not for certain) that sending
|
||||
messages will succeed.
|
||||
"""
|
||||
return False # Needs to be overridden
|
||||
|
||||
@overload
|
||||
def send_message_cb(
|
||||
self,
|
||||
msg: bacommon.cloud.LoginProxyRequestMessage,
|
||||
on_response: Callable[
|
||||
[bacommon.cloud.LoginProxyRequestResponse | Exception], None],
|
||||
) -> None:
|
||||
...
|
||||
|
||||
@overload
|
||||
def send_message_cb(
|
||||
self,
|
||||
msg: bacommon.cloud.LoginProxyStateQueryMessage,
|
||||
on_response: Callable[
|
||||
[bacommon.cloud.LoginProxyStateQueryResponse | Exception], None],
|
||||
) -> None:
|
||||
...
|
||||
|
||||
@overload
|
||||
def send_message_cb(
|
||||
self,
|
||||
msg: bacommon.cloud.LoginProxyCompleteMessage,
|
||||
on_response: Callable[[None | Exception], None],
|
||||
) -> None:
|
||||
...
|
||||
|
||||
def send_message_cb(
|
||||
self,
|
||||
msg: Message,
|
||||
on_response: Callable[[Any], None],
|
||||
) -> None:
|
||||
"""Asynchronously send a message to the cloud from the logic thread.
|
||||
|
||||
The provided on_response call will be run in the logic thread
|
||||
and passed either the response or the error that occurred.
|
||||
"""
|
||||
from ba._general import Call
|
||||
del msg # Unused.
|
||||
|
||||
_ba.pushcall(
|
||||
Call(on_response,
|
||||
RuntimeError('Cloud functionality is not available.')))
|
||||
|
||||
@overload
|
||||
def send_message(
|
||||
self, msg: bacommon.cloud.WorkspaceFetchMessage
|
||||
) -> bacommon.cloud.WorkspaceFetchResponse:
|
||||
...
|
||||
|
||||
@overload
|
||||
def send_message(
|
||||
self,
|
||||
msg: bacommon.cloud.TestMessage) -> bacommon.cloud.TestResponse:
|
||||
...
|
||||
|
||||
def send_message(self, msg: Message) -> Response | None:
|
||||
"""Synchronously send a message to the cloud.
|
||||
|
||||
Must be called from a background thread.
|
||||
"""
|
||||
raise RuntimeError('Cloud functionality is not available.')
|
||||
6
dist/ba_data/python/ba/_coopgame.py
vendored
6
dist/ba_data/python/ba/_coopgame.py
vendored
|
|
@ -10,7 +10,7 @@ from ba._gameactivity import GameActivity
|
|||
from ba._general import WeakCall
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
import ba
|
||||
|
||||
|
|
@ -40,8 +40,8 @@ class CoopGameActivity(GameActivity[PlayerType, TeamType]):
|
|||
# Cache these for efficiency.
|
||||
self._achievements_awarded: set[str] = set()
|
||||
|
||||
self._life_warning_beep: Optional[ba.Actor] = None
|
||||
self._life_warning_beep_timer: Optional[ba.Timer] = None
|
||||
self._life_warning_beep: ba.Actor | None = None
|
||||
self._life_warning_beep_timer: ba.Timer | None = None
|
||||
self._warn_beeps_sound = _ba.getsound('warnBeeps')
|
||||
|
||||
def on_begin(self) -> None:
|
||||
|
|
|
|||
18
dist/ba_data/python/ba/_coopsession.py
vendored
18
dist/ba_data/python/ba/_coopsession.py
vendored
|
|
@ -9,7 +9,7 @@ import _ba
|
|||
from ba._session import Session
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Callable, Sequence
|
||||
from typing import Any, Callable, Sequence
|
||||
import ba
|
||||
|
||||
TEAM_COLORS = [(0.2, 0.4, 1.6)]
|
||||
|
|
@ -37,7 +37,10 @@ class CoopSession(Session):
|
|||
|
||||
# Note: even though these are instance vars, we annotate them at the
|
||||
# class level so that docs generation can access their types.
|
||||
campaign: Optional[ba.Campaign]
|
||||
|
||||
campaign: ba.Campaign | None
|
||||
"""The ba.Campaign instance this Session represents, or None if
|
||||
there is no associated Campaign."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Instantiate a co-op mode session."""
|
||||
|
|
@ -69,21 +72,21 @@ class CoopSession(Session):
|
|||
max_players=max_players)
|
||||
|
||||
# Tournament-ID if we correspond to a co-op tournament (otherwise None)
|
||||
self.tournament_id: Optional[str] = (
|
||||
self.tournament_id: str | None = (
|
||||
app.coop_session_args.get('tournament_id'))
|
||||
|
||||
self.campaign = getcampaign(app.coop_session_args['campaign'])
|
||||
self.campaign_level_name: str = app.coop_session_args['level']
|
||||
|
||||
self._ran_tutorial_activity = False
|
||||
self._tutorial_activity: Optional[ba.Activity] = None
|
||||
self._tutorial_activity: ba.Activity | None = None
|
||||
self._custom_menu_ui: list[dict[str, Any]] = []
|
||||
|
||||
# Start our joining screen.
|
||||
self.setactivity(_ba.newactivity(CoopJoinActivity))
|
||||
|
||||
self._next_game_instance: Optional[ba.GameActivity] = None
|
||||
self._next_game_level_name: Optional[str] = None
|
||||
self._next_game_instance: ba.GameActivity | None = None
|
||||
self._next_game_level_name: str | None = None
|
||||
self._update_on_deck_game_instances()
|
||||
|
||||
def get_current_game_instance(self) -> ba.GameActivity:
|
||||
|
|
@ -126,7 +129,8 @@ class CoopSession(Session):
|
|||
levels = self.campaign.levels
|
||||
level = self.campaign.getlevel(self.campaign_level_name)
|
||||
|
||||
nextlevel: Optional[ba.Level]
|
||||
|
||||
nextlevel: ba.Level | None
|
||||
# if level.index < len(levels) - 1:
|
||||
# nextlevel = levels[level.index + 1]
|
||||
# else:
|
||||
|
|
|
|||
6
dist/ba_data/python/ba/_dependency.py
vendored
6
dist/ba_data/python/ba/_dependency.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import (Generic, TypeVar, TYPE_CHECKING)
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any
|
||||
from typing import Any
|
||||
import ba
|
||||
|
||||
T = TypeVar('T', bound='DependencyComponent')
|
||||
|
|
@ -39,7 +39,7 @@ class Dependency(Generic[T]):
|
|||
"""
|
||||
self.cls: type[T] = cls
|
||||
self.config = config
|
||||
self._hash: Optional[int] = None
|
||||
self._hash: int | None = None
|
||||
|
||||
def get_hash(self) -> int:
|
||||
"""Return the dependency's hash, calculating it if necessary."""
|
||||
|
|
@ -133,7 +133,7 @@ class DependencyEntry:
|
|||
|
||||
# Arbitrary data for use by dependencies in the resolved set
|
||||
# (the static instance for static-deps, etc).
|
||||
self.component: Optional[DependencyComponent] = None
|
||||
self.component: DependencyComponent | None = None
|
||||
|
||||
# Weakref to the depset that includes us (to avoid ref loop).
|
||||
self.depset = weakref.ref(depset)
|
||||
|
|
|
|||
72
dist/ba_data/python/ba/_gameactivity.py
vendored
72
dist/ba_data/python/ba/_gameactivity.py
vendored
|
|
@ -19,7 +19,7 @@ from ba._player import PlayerInfo
|
|||
from ba import _map
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Callable, Sequence, Union
|
||||
from typing import Any, Callable, Sequence
|
||||
from bastd.actor.playerspaz import PlayerSpaz
|
||||
from bastd.actor.bomb import TNTSpawner
|
||||
import ba
|
||||
|
|
@ -38,19 +38,19 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
# pylint: disable=too-many-public-methods
|
||||
|
||||
# Tips to be presented to the user at the start of the game.
|
||||
tips: list[Union[str, ba.GameTip]] = []
|
||||
tips: list[str | ba.GameTip] = []
|
||||
|
||||
# Default getname() will return this if not None.
|
||||
name: Optional[str] = None
|
||||
name: str | None = None
|
||||
|
||||
# Default get_description() will return this if not None.
|
||||
description: Optional[str] = None
|
||||
description: str | None = None
|
||||
|
||||
# Default get_available_settings() will return this if not None.
|
||||
available_settings: Optional[list[ba.Setting]] = None
|
||||
available_settings: list[ba.Setting] | None = None
|
||||
|
||||
# Default getscoreconfig() will return this if not None.
|
||||
scoreconfig: Optional[ba.ScoreConfig] = None
|
||||
scoreconfig: ba.ScoreConfig | None = None
|
||||
|
||||
# Override some defaults.
|
||||
allow_pausing = True
|
||||
|
|
@ -61,14 +61,14 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
|
||||
# If not None, the music type that should play in on_transition_in()
|
||||
# (unless overridden by the map).
|
||||
default_music: Optional[ba.MusicType] = None
|
||||
default_music: ba.MusicType | None = None
|
||||
|
||||
@classmethod
|
||||
def create_settings_ui(
|
||||
cls,
|
||||
sessiontype: type[ba.Session],
|
||||
settings: Optional[dict],
|
||||
completion_call: Callable[[Optional[dict]], None],
|
||||
settings: dict | None,
|
||||
completion_call: Callable[[dict | None], None],
|
||||
) -> None:
|
||||
"""Launch an in-game UI to configure settings for a game type.
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
return cls.name if cls.name is not None else 'Untitled Game'
|
||||
|
||||
@classmethod
|
||||
def get_display_string(cls, settings: Optional[dict] = None) -> ba.Lstr:
|
||||
def get_display_string(cls, settings: dict | None = None) -> ba.Lstr:
|
||||
"""Return a descriptive name for this game/settings combo.
|
||||
|
||||
Subclasses should override getname(); not this.
|
||||
|
|
@ -214,28 +214,28 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
|
||||
# Holds some flattened info about the player set at the point
|
||||
# when on_begin() is called.
|
||||
self.initialplayerinfos: Optional[list[ba.PlayerInfo]] = None
|
||||
self.initialplayerinfos: list[ba.PlayerInfo] | None = None
|
||||
|
||||
# Go ahead and get our map loading.
|
||||
self._map_type = _map.get_map_class(self._calc_map_name(settings))
|
||||
|
||||
self._spawn_sound = _ba.getsound('spawn')
|
||||
self._map_type.preload()
|
||||
self._map: Optional[ba.Map] = None
|
||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||
self._tnt_spawners: Optional[dict[int, TNTSpawner]] = None
|
||||
self._tnt_drop_timer: Optional[ba.Timer] = None
|
||||
self._game_scoreboard_name_text: Optional[ba.Actor] = None
|
||||
self._game_scoreboard_description_text: Optional[ba.Actor] = None
|
||||
self._standard_time_limit_time: Optional[int] = None
|
||||
self._standard_time_limit_timer: Optional[ba.Timer] = None
|
||||
self._standard_time_limit_text: Optional[ba.NodeActor] = None
|
||||
self._standard_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit: Optional[int] = None
|
||||
self._tournament_time_limit_timer: Optional[ba.Timer] = None
|
||||
self._tournament_time_limit_title_text: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit_text: Optional[ba.NodeActor] = None
|
||||
self._tournament_time_limit_text_input: Optional[ba.NodeActor] = None
|
||||
self._map: ba.Map | None = None
|
||||
self._powerup_drop_timer: ba.Timer | None = None
|
||||
self._tnt_spawners: dict[int, TNTSpawner] | None = None
|
||||
self._tnt_drop_timer: ba.Timer | None = None
|
||||
self._game_scoreboard_name_text: ba.Actor | None = None
|
||||
self._game_scoreboard_description_text: ba.Actor | None = None
|
||||
self._standard_time_limit_time: int | None = None
|
||||
self._standard_time_limit_timer: ba.Timer | None = None
|
||||
self._standard_time_limit_text: ba.NodeActor | None = None
|
||||
self._standard_time_limit_text_input: ba.NodeActor | None = None
|
||||
self._tournament_time_limit: int | None = None
|
||||
self._tournament_time_limit_timer: ba.Timer | None = None
|
||||
self._tournament_time_limit_title_text: ba.NodeActor | None = None
|
||||
self._tournament_time_limit_text: ba.NodeActor | None = None
|
||||
self._tournament_time_limit_text_input: ba.NodeActor | None = None
|
||||
self._zoom_message_times: dict[int, float] = {}
|
||||
self._is_waiting_for_continue = False
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
print_error('error getting campaign level name')
|
||||
return self.get_instance_display_string()
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
"""Return a description for this game instance, in English.
|
||||
|
||||
This is shown in the center of the screen below the game name at the
|
||||
|
|
@ -306,7 +306,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
"""
|
||||
return self.get_description(type(self.session))
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
"""Return a short description for this game instance in English.
|
||||
|
||||
This description is used above the game scoreboard in the
|
||||
|
|
@ -461,8 +461,8 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
callback=WeakCall(self._on_tournament_query_response),
|
||||
)
|
||||
|
||||
def _on_tournament_query_response(self, data: Optional[dict[str,
|
||||
Any]]) -> None:
|
||||
def _on_tournament_query_response(self,
|
||||
data: dict[str, Any] | None) -> None:
|
||||
if data is not None:
|
||||
data_t = data['t'] # This used to be the whole payload.
|
||||
|
||||
|
|
@ -662,8 +662,8 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
tip = self.tips.pop(random.randrange(len(self.tips)))
|
||||
tip_title = Lstr(value='${A}:',
|
||||
subs=[('${A}', Lstr(resource='tipText'))])
|
||||
icon: Optional[ba.Texture] = None
|
||||
sound: Optional[ba.Sound] = None
|
||||
icon: ba.Texture | None = None
|
||||
sound: ba.Sound | None = None
|
||||
if isinstance(tip, GameTip):
|
||||
icon = tip.icon
|
||||
sound = tip.sound
|
||||
|
|
@ -781,7 +781,7 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
|
||||
def respawn_player(self,
|
||||
player: PlayerType,
|
||||
respawn_time: Optional[float] = None) -> None:
|
||||
respawn_time: float | None = None) -> None:
|
||||
"""
|
||||
Given a ba.Player, sets up a standard respawn timer,
|
||||
along with the standard counter display, etc.
|
||||
|
|
@ -853,9 +853,13 @@ class GameActivity(Activity[PlayerType, TeamType]):
|
|||
color = player.color
|
||||
highlight = player.highlight
|
||||
|
||||
playerspaztype = getattr(player, 'playerspaztype', PlayerSpaz)
|
||||
if not issubclass(playerspaztype, PlayerSpaz):
|
||||
playerspaztype = PlayerSpaz
|
||||
|
||||
light_color = _math.normalized_color(color)
|
||||
display_color = _ba.safecolor(color, target_intensity=0.75)
|
||||
spaz = PlayerSpaz(color=color,
|
||||
spaz = playerspaztype(color=color,
|
||||
highlight=highlight,
|
||||
character=player.character,
|
||||
player=player)
|
||||
|
|
|
|||
29
dist/ba_data/python/ba/_gameresults.py
vendored
29
dist/ba_data/python/ba/_gameresults.py
vendored
|
|
@ -12,14 +12,14 @@ from efro.util import asserttype
|
|||
from ba._team import Team, SessionTeam
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional
|
||||
from typing import Sequence
|
||||
import ba
|
||||
|
||||
|
||||
@dataclass
|
||||
class WinnerGroup:
|
||||
"""Entry for a winning team or teams calculated by game-results."""
|
||||
score: Optional[int]
|
||||
score: int | None
|
||||
teams: Sequence[ba.SessionTeam]
|
||||
|
||||
|
||||
|
|
@ -36,13 +36,13 @@ class GameResults:
|
|||
def __init__(self) -> None:
|
||||
self._game_set = False
|
||||
self._scores: dict[int, tuple[weakref.ref[ba.SessionTeam],
|
||||
Optional[int]]] = {}
|
||||
self._sessionteams: Optional[list[weakref.ref[ba.SessionTeam]]] = None
|
||||
self._playerinfos: Optional[list[ba.PlayerInfo]] = None
|
||||
self._lower_is_better: Optional[bool] = None
|
||||
self._score_label: Optional[str] = None
|
||||
self._none_is_winner: Optional[bool] = None
|
||||
self._scoretype: Optional[ba.ScoreType] = None
|
||||
int | None]] = {}
|
||||
self._sessionteams: list[weakref.ref[ba.SessionTeam]] | None = None
|
||||
self._playerinfos: list[ba.PlayerInfo] | None = None
|
||||
self._lower_is_better: bool | None = None
|
||||
self._score_label: str | None = None
|
||||
self._none_is_winner: bool | None = None
|
||||
self._scoretype: ba.ScoreType | None = None
|
||||
|
||||
def set_game(self, game: ba.GameActivity) -> None:
|
||||
"""Set the game instance these results are applying to."""
|
||||
|
|
@ -59,7 +59,7 @@ class GameResults:
|
|||
self._none_is_winner = scoreconfig.none_is_winner
|
||||
self._scoretype = scoreconfig.scoretype
|
||||
|
||||
def set_team_score(self, team: ba.Team, score: Optional[int]) -> None:
|
||||
def set_team_score(self, team: ba.Team, score: int | None) -> None:
|
||||
"""Set the score for a given team.
|
||||
|
||||
This can be a number or None.
|
||||
|
|
@ -69,8 +69,7 @@ class GameResults:
|
|||
sessionteam = team.sessionteam
|
||||
self._scores[sessionteam.id] = (weakref.ref(sessionteam), score)
|
||||
|
||||
def get_sessionteam_score(self,
|
||||
sessionteam: ba.SessionTeam) -> Optional[int]:
|
||||
def get_sessionteam_score(self, sessionteam: ba.SessionTeam) -> int | None:
|
||||
"""Return the score for a given ba.SessionTeam."""
|
||||
assert isinstance(sessionteam, SessionTeam)
|
||||
for score in list(self._scores.values()):
|
||||
|
|
@ -157,7 +156,7 @@ class GameResults:
|
|||
return self._lower_is_better
|
||||
|
||||
@property
|
||||
def winning_sessionteam(self) -> Optional[ba.SessionTeam]:
|
||||
def winning_sessionteam(self) -> ba.SessionTeam | None:
|
||||
"""The winning ba.SessionTeam if there is exactly one, or else None."""
|
||||
if not self._game_set:
|
||||
raise RuntimeError("Can't get winners until game is set.")
|
||||
|
|
@ -184,7 +183,7 @@ class GameResults:
|
|||
team = score[0]()
|
||||
assert team is not None
|
||||
sval.append(team)
|
||||
results: list[tuple[Optional[int],
|
||||
results: list[tuple[int | None,
|
||||
list[ba.SessionTeam]]] = list(winners.items())
|
||||
results.sort(reverse=not self._lower_is_better,
|
||||
key=lambda x: asserttype(x[0], int))
|
||||
|
|
@ -199,7 +198,7 @@ class GameResults:
|
|||
# Add the Nones to the list (either as winners or losers
|
||||
# depending on the rules).
|
||||
if none_sessionteams:
|
||||
nones: list[tuple[Optional[int], list[ba.SessionTeam]]] = [
|
||||
nones: list[tuple[int | None, list[ba.SessionTeam]]] = [
|
||||
(None, none_sessionteams)
|
||||
]
|
||||
if self._none_is_winner:
|
||||
|
|
|
|||
6
dist/ba_data/python/ba/_gameutils.py
vendored
6
dist/ba_data/python/ba/_gameutils.py
vendored
|
|
@ -12,7 +12,7 @@ from ba._generated.enums import TimeType, TimeFormat, SpecialChar, UIScale
|
|||
from ba._error import ActivityNotFoundError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional
|
||||
from typing import Sequence
|
||||
import ba
|
||||
|
||||
TROPHY_CHARS = {
|
||||
|
|
@ -32,8 +32,8 @@ class GameTip:
|
|||
Category: **Gameplay Classes**
|
||||
"""
|
||||
text: str
|
||||
icon: Optional[ba.Texture] = None
|
||||
sound: Optional[ba.Sound] = None
|
||||
icon: ba.Texture | None = None
|
||||
sound: ba.Sound | None = None
|
||||
|
||||
|
||||
def get_trophy_string(trophy_id: str) -> str:
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/_general.py
vendored
8
dist/ba_data/python/ba/_general.py
vendored
|
|
@ -17,7 +17,7 @@ from ba._generated.enums import TimeType
|
|||
|
||||
if TYPE_CHECKING:
|
||||
from types import FrameType
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
from efro.call import Call as Call # 'as Call' so we re-export.
|
||||
|
||||
|
||||
|
|
@ -37,15 +37,15 @@ ExistableType = TypeVar('ExistableType', bound=Existable)
|
|||
T = TypeVar('T')
|
||||
|
||||
|
||||
def existing(obj: Optional[ExistableType]) -> Optional[ExistableType]:
|
||||
def existing(obj: ExistableType | None) -> ExistableType | None:
|
||||
"""Convert invalid references to None for any ba.Existable object.
|
||||
|
||||
Category: **Gameplay Functions**
|
||||
|
||||
To best support type checking, it is important that invalid references
|
||||
not be passed around and instead get converted to values of None.
|
||||
That way the type checker can properly flag attempts to pass dead
|
||||
objects (Optional[FooType]) into functions expecting only live ones
|
||||
That way the type checker can properly flag attempts to pass possibly-dead
|
||||
objects (FooType | None) into functions expecting only live ones
|
||||
(FooType), etc. This call can be used on any 'existable' object
|
||||
(one with an exists() method) and will convert it to a None value
|
||||
if it does not exist.
|
||||
|
|
|
|||
5
dist/ba_data/python/ba/_hooks.py
vendored
5
dist/ba_data/python/ba/_hooks.py
vendored
|
|
@ -18,7 +18,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional, Any
|
||||
from typing import Sequence, Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -325,7 +325,8 @@ def party_invite_revoke(invite_id: str) -> None:
|
|||
transition='out_right')
|
||||
|
||||
import custom_hooks as chooks
|
||||
def filter_chat_message(msg: str, client_id: int) -> Optional[str]:
|
||||
def filter_chat_message(msg: str, client_id: int) -> str | None:
|
||||
|
||||
"""Intercept/filter chat messages.
|
||||
|
||||
Called for all chat messages while hosting.
|
||||
|
|
|
|||
14
dist/ba_data/python/ba/_language.py
vendored
14
dist/ba_data/python/ba/_language.py
vendored
|
|
@ -11,7 +11,7 @@ import _ba
|
|||
|
||||
if TYPE_CHECKING:
|
||||
import ba
|
||||
from typing import Any, Optional, Union, Sequence
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class LanguageSubsystem:
|
||||
|
|
@ -23,8 +23,8 @@ class LanguageSubsystem:
|
|||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.language_target: Optional[AttrDict] = None
|
||||
self.language_merged: Optional[AttrDict] = None
|
||||
self.language_target: AttrDict | None = None
|
||||
self.language_merged: AttrDict | None = None
|
||||
self.default_language = self._get_default_language()
|
||||
|
||||
def _can_display_language(self, language: str) -> bool:
|
||||
|
|
@ -139,7 +139,7 @@ class LanguageSubsystem:
|
|||
if self._can_display_language(name))
|
||||
|
||||
def setlanguage(self,
|
||||
language: Optional[str],
|
||||
language: str | None,
|
||||
print_change: bool = True,
|
||||
store_to_config: bool = True) -> None:
|
||||
"""Set the active language used for the game.
|
||||
|
|
@ -408,7 +408,7 @@ class Lstr:
|
|||
resource: str,
|
||||
fallback_resource: str = '',
|
||||
fallback_value: str = '',
|
||||
subs: Sequence[tuple[str, Union[str, Lstr]]] = []) -> None:
|
||||
subs: Sequence[tuple[str, str | Lstr]] = []) -> None:
|
||||
"""Create an Lstr from a string resource."""
|
||||
|
||||
# noinspection PyShadowingNames,PyDefaultArgument
|
||||
|
|
@ -416,7 +416,7 @@ class Lstr:
|
|||
def __init__(self,
|
||||
*,
|
||||
translate: tuple[str, str],
|
||||
subs: Sequence[tuple[str, Union[str, Lstr]]] = []) -> None:
|
||||
subs: Sequence[tuple[str, str | Lstr]] = []) -> None:
|
||||
"""Create an Lstr by translating a string in a category."""
|
||||
|
||||
# noinspection PyDefaultArgument
|
||||
|
|
@ -424,7 +424,7 @@ class Lstr:
|
|||
def __init__(self,
|
||||
*,
|
||||
value: str,
|
||||
subs: Sequence[tuple[str, Union[str, Lstr]]] = []) -> None:
|
||||
subs: Sequence[tuple[str, str | Lstr]] = []) -> None:
|
||||
"""Create an Lstr from a raw string value."""
|
||||
|
||||
# pylint: enable=redefined-outer-name, dangerous-default-value
|
||||
|
|
|
|||
10
dist/ba_data/python/ba/_level.py
vendored
10
dist/ba_data/python/ba/_level.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -31,9 +31,9 @@ class Level:
|
|||
self._settings = settings
|
||||
self._preview_texture_name = preview_texture_name
|
||||
self._displayname = displayname
|
||||
self._campaign: Optional[weakref.ref[ba.Campaign]] = None
|
||||
self._index: Optional[int] = None
|
||||
self._score_version_string: Optional[str] = None
|
||||
self._campaign: weakref.ref[ba.Campaign] | None = None
|
||||
self._index: int | None = None
|
||||
self._score_version_string: str | None = None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
cls = type(self)
|
||||
|
|
@ -78,7 +78,7 @@ class Level:
|
|||
return self._gametype
|
||||
|
||||
@property
|
||||
def campaign(self) -> Optional[ba.Campaign]:
|
||||
def campaign(self) -> ba.Campaign | None:
|
||||
"""The ba.Campaign this Level is associated with, or None."""
|
||||
return None if self._campaign is None else self._campaign()
|
||||
|
||||
|
|
|
|||
16
dist/ba_data/python/ba/_lobby.py
vendored
16
dist/ba_data/python/ba/_lobby.py
vendored
|
|
@ -16,7 +16,7 @@ from ba._generated.enums import SpecialChar, InputType
|
|||
from ba._profile import get_player_profile_colors
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
import ba
|
||||
|
||||
MAX_QUICK_CHANGE_COUNT = 30
|
||||
|
|
@ -32,12 +32,10 @@ class JoinInfo:
|
|||
from ba._nodeactor import NodeActor
|
||||
from ba._general import WeakCall
|
||||
self._state = 0
|
||||
self._press_to_punch: Union[str,
|
||||
ba.Lstr] = ('C' if _ba.app.iircade_mode
|
||||
else _ba.charstr(
|
||||
self._press_to_punch: str | ba.Lstr = ('C' if _ba.app.iircade_mode else
|
||||
_ba.charstr(
|
||||
SpecialChar.LEFT_BUTTON))
|
||||
self._press_to_bomb: Union[str,
|
||||
ba.Lstr] = ('B' if _ba.app.iircade_mode else
|
||||
self._press_to_bomb: str | ba.Lstr = ('B' if _ba.app.iircade_mode else
|
||||
_ba.charstr(
|
||||
SpecialChar.RIGHT_BUTTON))
|
||||
self._joinmsg = Lstr(resource='pressAnyButtonToJoinText')
|
||||
|
|
@ -150,12 +148,12 @@ class Chooser:
|
|||
self._sessionplayer = sessionplayer
|
||||
self._inited = False
|
||||
self._dead = False
|
||||
self._text_node: Optional[ba.Node] = None
|
||||
self._text_node: ba.Node | None = None
|
||||
self._profilename = ''
|
||||
self._profilenames: list[str] = []
|
||||
self._ready: bool = False
|
||||
self._character_names: list[str] = []
|
||||
self._last_change: Sequence[Union[float, int]] = (0, 0)
|
||||
self._last_change: Sequence[float | int] = (0, 0)
|
||||
self._profiles: dict[str, dict[str, Any]] = {}
|
||||
|
||||
app = _ba.app
|
||||
|
|
@ -318,7 +316,7 @@ class Chooser:
|
|||
raise NotFoundError('Lobby does not exist.')
|
||||
return lobby
|
||||
|
||||
def get_lobby(self) -> Optional[ba.Lobby]:
|
||||
def get_lobby(self) -> ba.Lobby | None:
|
||||
"""Return this chooser's lobby if it still exists; otherwise None."""
|
||||
return self._lobby()
|
||||
|
||||
|
|
|
|||
19
dist/ba_data/python/ba/_map.py
vendored
19
dist/ba_data/python/ba/_map.py
vendored
|
|
@ -11,7 +11,7 @@ from ba import _math
|
|||
from ba._actor import Actor
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Sequence, Any
|
||||
from typing import Sequence, Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ class Map(Actor):
|
|||
return []
|
||||
|
||||
@classmethod
|
||||
def get_preview_texture_name(cls) -> Optional[str]:
|
||||
def get_preview_texture_name(cls) -> str | None:
|
||||
"""Return the name of the preview texture for this map."""
|
||||
return None
|
||||
|
||||
|
|
@ -179,7 +179,7 @@ class Map(Actor):
|
|||
return cls.name
|
||||
|
||||
@classmethod
|
||||
def get_music_type(cls) -> Optional[ba.MusicType]:
|
||||
def get_music_type(cls) -> ba.MusicType | None:
|
||||
"""Return a music-type string that should be played on this map.
|
||||
|
||||
If None is returned, default music will be used.
|
||||
|
|
@ -187,13 +187,13 @@ class Map(Actor):
|
|||
return None
|
||||
|
||||
def __init__(self,
|
||||
vr_overlay_offset: Optional[Sequence[float]] = None) -> None:
|
||||
vr_overlay_offset: Sequence[float] | None = None) -> None:
|
||||
"""Instantiate a map."""
|
||||
super().__init__()
|
||||
|
||||
# This is expected to always be a ba.Node object (whether valid or not)
|
||||
# should be set to something meaningful by child classes.
|
||||
self.node: Optional[_ba.Node] = None
|
||||
self.node: _ba.Node | None = None
|
||||
|
||||
# Make our class' preload-data available to us
|
||||
# (and instruct the user if we weren't preloaded properly).
|
||||
|
|
@ -209,8 +209,9 @@ class Map(Actor):
|
|||
# Set various globals.
|
||||
gnode = _ba.getactivity().globalsnode
|
||||
import ba
|
||||
from features import text_on_map
|
||||
text_on_map.textonmap()
|
||||
import custom_hooks
|
||||
custom_hooks.on_map_init()
|
||||
|
||||
|
||||
# Set area-of-interest bounds.
|
||||
aoi_bounds = self.get_def_bound_box('area_of_interest_bounds')
|
||||
|
|
@ -298,7 +299,7 @@ class Map(Actor):
|
|||
|
||||
def get_def_bound_box(
|
||||
self, name: str
|
||||
) -> Optional[tuple[float, float, float, float, float, float]]:
|
||||
) -> tuple[float, float, float, float, float, float] | None:
|
||||
"""Return a 6 member bounds tuple or None if it is not defined."""
|
||||
try:
|
||||
box = self.defs.boxes[name]
|
||||
|
|
@ -308,7 +309,7 @@ class Map(Actor):
|
|||
except Exception:
|
||||
return None
|
||||
|
||||
def get_def_point(self, name: str) -> Optional[Sequence[float]]:
|
||||
def get_def_point(self, name: str) -> Sequence[float] | None:
|
||||
"""Return a single defined point or a default value in its absence."""
|
||||
val = self.defs.points.get(name)
|
||||
return (None if val is None else
|
||||
|
|
|
|||
10
dist/ba_data/python/ba/_messages.py
vendored
10
dist/ba_data/python/ba/_messages.py
vendored
|
|
@ -11,7 +11,7 @@ from enum import Enum
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional, Any
|
||||
from typing import Sequence, Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ class PlayerDiedMessage:
|
|||
"""The particular type of death."""
|
||||
|
||||
def __init__(self, player: ba.Player, was_killed: bool,
|
||||
killerplayer: Optional[ba.Player], how: ba.DeathType):
|
||||
killerplayer: ba.Player | None, how: ba.DeathType):
|
||||
"""Instantiate a message with the given values."""
|
||||
|
||||
# Invalid refs should never be passed as args.
|
||||
|
|
@ -98,7 +98,7 @@ class PlayerDiedMessage:
|
|||
self.how = how
|
||||
|
||||
def getkillerplayer(self,
|
||||
playertype: type[PlayerType]) -> Optional[PlayerType]:
|
||||
playertype: type[PlayerType]) -> PlayerType | None:
|
||||
"""Return the ba.Player responsible for the killing, if any.
|
||||
|
||||
Pass the Player type being used by the current game.
|
||||
|
|
@ -267,8 +267,8 @@ class HitMessage:
|
|||
self.force_direction = (force_direction
|
||||
if force_direction is not None else velocity)
|
||||
|
||||
def get_source_player(
|
||||
self, playertype: type[PlayerType]) -> Optional[PlayerType]:
|
||||
def get_source_player(self,
|
||||
playertype: type[PlayerType]) -> PlayerType | None:
|
||||
"""Return the source-player if one exists and is the provided type."""
|
||||
player: Any = self._source_player
|
||||
|
||||
|
|
|
|||
71
dist/ba_data/python/ba/_meta.py
vendored
71
dist/ba_data/python/ba/_meta.py
vendored
|
|
@ -6,22 +6,23 @@ from __future__ import annotations
|
|||
|
||||
import os
|
||||
import time
|
||||
import pathlib
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Union, Optional
|
||||
import ba
|
||||
|
||||
# The meta api version of this build of the game.
|
||||
# Only packages and modules requiring this exact api version
|
||||
# will be considered when scanning directories.
|
||||
# See: https://ballistica.net/wiki/Meta-Tags
|
||||
CURRENT_API_VERSION = 6
|
||||
CURRENT_API_VERSION = 6 #TODO update it to latest
|
||||
# current API version is 7 , im downgrading it to 6 to support mini games which i cant update to 7 bcoz of encryption
|
||||
# shouldn't be a issue , I manually updated all plugin on_app_launch to on_app_running and that was the only change btw API 6 and 7
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -43,10 +44,11 @@ class MetadataSubsystem:
|
|||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.metascan: Optional[ScanResults] = None
|
||||
self.metascan: ScanResults | None = None
|
||||
self.extra_scan_dirs: list[str] = []
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Should be called when the app is done bootstrapping."""
|
||||
def on_app_running(self) -> None:
|
||||
"""Should be called when the app enters the running state."""
|
||||
|
||||
# Start scanning for things exposed via ba_meta.
|
||||
self.start_scan()
|
||||
|
|
@ -58,7 +60,8 @@ class MetadataSubsystem:
|
|||
app = _ba.app
|
||||
if self.metascan is not None:
|
||||
print('WARNING: meta scan run more than once.')
|
||||
pythondirs = [app.python_directory_app, app.python_directory_user]
|
||||
pythondirs = ([app.python_directory_app, app.python_directory_user] +
|
||||
self.extra_scan_dirs)
|
||||
thread = ScanThread(pythondirs)
|
||||
thread.start()
|
||||
|
||||
|
|
@ -99,16 +102,10 @@ class MetadataSubsystem:
|
|||
class_path=class_path,
|
||||
available=True))
|
||||
if class_path not in plugstates:
|
||||
if _ba.app.headless_mode:
|
||||
# If we running in headless mode, enable plugin by default
|
||||
# to allow server admins to get their modified build
|
||||
# working 'out-of-the-box', without manually updating the
|
||||
# config.
|
||||
# Go ahead and enable new plugins by default, but we'll
|
||||
# inform the user that they need to restart to pick them up.
|
||||
# they can also disable them in settings so they never load.
|
||||
plugstates[class_path] = {'enabled': True}
|
||||
else:
|
||||
# If we running in normal mode, disable plugin by default
|
||||
# (user can enable it later).
|
||||
plugstates[class_path] = {'enabled': False}
|
||||
config_changed = True
|
||||
found_new = True
|
||||
|
||||
|
|
@ -223,18 +220,17 @@ class DirectoryScan:
|
|||
"""
|
||||
|
||||
# Skip non-existent paths completely.
|
||||
self.paths = [pathlib.Path(p) for p in paths if os.path.isdir(p)]
|
||||
self.paths = [Path(p) for p in paths if os.path.isdir(p)]
|
||||
self.results = ScanResults()
|
||||
|
||||
def _get_path_module_entries(
|
||||
self, path: pathlib.Path, subpath: Union[str, pathlib.Path],
|
||||
modules: list[tuple[pathlib.Path, pathlib.Path]]) -> None:
|
||||
def _get_path_module_entries(self, path: Path, subpath: str | Path,
|
||||
modules: list[tuple[Path, Path]]) -> None:
|
||||
"""Scan provided path and add module entries to provided list."""
|
||||
try:
|
||||
# Special case: let's save some time and skip the whole 'ba'
|
||||
# package since we know it doesn't contain any meta tags.
|
||||
fullpath = pathlib.Path(path, subpath)
|
||||
entries = [(path, pathlib.Path(subpath, name))
|
||||
fullpath = Path(path, subpath)
|
||||
entries = [(path, Path(subpath, name))
|
||||
for name in os.listdir(fullpath) if name != 'ba']
|
||||
except PermissionError:
|
||||
# Expected sometimes.
|
||||
|
|
@ -248,13 +244,13 @@ class DirectoryScan:
|
|||
for entry in entries:
|
||||
if entry[1].name.endswith('.py'):
|
||||
modules.append(entry)
|
||||
elif (pathlib.Path(entry[0], entry[1]).is_dir() and pathlib.Path(
|
||||
entry[0], entry[1], '__init__.py').is_file()):
|
||||
elif (Path(entry[0], entry[1]).is_dir()
|
||||
and Path(entry[0], entry[1], '__init__.py').is_file()):
|
||||
modules.append(entry)
|
||||
|
||||
def scan(self) -> None:
|
||||
"""Scan provided paths."""
|
||||
modules: list[tuple[pathlib.Path, pathlib.Path]] = []
|
||||
modules: list[tuple[Path, Path]] = []
|
||||
for path in self.paths:
|
||||
self._get_path_module_entries(path, '', modules)
|
||||
for moduledir, subpath in modules:
|
||||
|
|
@ -269,14 +265,13 @@ class DirectoryScan:
|
|||
self.results.games.sort()
|
||||
self.results.plugins.sort()
|
||||
|
||||
def scan_module(self, moduledir: pathlib.Path,
|
||||
subpath: pathlib.Path) -> None:
|
||||
def scan_module(self, moduledir: Path, subpath: Path) -> None:
|
||||
"""Scan an individual module and add the findings to results."""
|
||||
if subpath.name.endswith('.py'):
|
||||
fpath = pathlib.Path(moduledir, subpath)
|
||||
fpath = Path(moduledir, subpath)
|
||||
ispackage = False
|
||||
else:
|
||||
fpath = pathlib.Path(moduledir, subpath, '__init__.py')
|
||||
fpath = Path(moduledir, subpath, '__init__.py')
|
||||
ispackage = True
|
||||
with fpath.open(encoding='utf-8') as infile:
|
||||
flines = infile.readlines()
|
||||
|
|
@ -293,7 +288,7 @@ class DirectoryScan:
|
|||
|
||||
# If we find a module requiring a different api version, warn
|
||||
# and ignore.
|
||||
if required_api is not None and required_api != CURRENT_API_VERSION:
|
||||
if required_api is not None and required_api <= CURRENT_API_VERSION:
|
||||
self.results.warnings += (
|
||||
f'Warning: {subpath} requires api {required_api} but'
|
||||
f' we are running {CURRENT_API_VERSION}; ignoring module.\n')
|
||||
|
|
@ -305,7 +300,7 @@ class DirectoryScan:
|
|||
# If its a package, recurse into its subpackages.
|
||||
if ispackage:
|
||||
try:
|
||||
submodules: list[tuple[pathlib.Path, pathlib.Path]] = []
|
||||
submodules: list[tuple[Path, Path]] = []
|
||||
self._get_path_module_entries(moduledir, subpath, submodules)
|
||||
for submodule in submodules:
|
||||
if submodule[1].name != '__init__.py':
|
||||
|
|
@ -315,8 +310,7 @@ class DirectoryScan:
|
|||
self.results.warnings += (
|
||||
f"Error scanning '{subpath}': {traceback.format_exc()}\n")
|
||||
|
||||
def _process_module_meta_tags(self, subpath: pathlib.Path,
|
||||
flines: list[str],
|
||||
def _process_module_meta_tags(self, subpath: Path, flines: list[str],
|
||||
meta_lines: dict[int, list[str]]) -> None:
|
||||
"""Pull data from a module based on its ba_meta tags."""
|
||||
for lindex, mline in meta_lines.items():
|
||||
|
|
@ -360,8 +354,8 @@ class DirectoryScan:
|
|||
': unrecognized export type "' + exporttype +
|
||||
'" on line ' + str(lindex + 1) + '.\n')
|
||||
|
||||
def _get_export_class_name(self, subpath: pathlib.Path, lines: list[str],
|
||||
lindex: int) -> Optional[str]:
|
||||
def _get_export_class_name(self, subpath: Path, lines: list[str],
|
||||
lindex: int) -> str | None:
|
||||
"""Given line num of an export tag, returns its operand class name."""
|
||||
lindexorig = lindex
|
||||
classname = None
|
||||
|
|
@ -386,9 +380,12 @@ class DirectoryScan:
|
|||
str(lindexorig + 1) + '.\n')
|
||||
return classname
|
||||
|
||||
def get_api_requirement(self, subpath: pathlib.Path,
|
||||
def get_api_requirement(
|
||||
self,
|
||||
subpath: Path,
|
||||
meta_lines: dict[int, list[str]],
|
||||
toplevel: bool) -> Optional[int]:
|
||||
toplevel: bool,
|
||||
) -> int | None:
|
||||
"""Return an API requirement integer or None if none present.
|
||||
|
||||
Malformed api requirement strings will be logged as warnings.
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/_multiteamsession.py
vendored
8
dist/ba_data/python/ba/_multiteamsession.py
vendored
|
|
@ -12,7 +12,7 @@ from ba._session import Session
|
|||
from ba._error import NotFoundError, print_error
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Sequence
|
||||
from typing import Any, Sequence
|
||||
import ba
|
||||
|
||||
DEFAULT_TEAM_COLORS = ((0.1, 0.25, 1.0), (1.0, 0.25, 0.2))
|
||||
|
|
@ -62,7 +62,7 @@ class MultiTeamSession(Session):
|
|||
|
||||
show_tutorial = cfg.get('Show Tutorial', True)
|
||||
|
||||
self._tutorial_activity_instance: Optional[ba.Activity]
|
||||
self._tutorial_activity_instance: ba.Activity | None
|
||||
if show_tutorial:
|
||||
from bastd.tutorial import TutorialActivity
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ class MultiTeamSession(Session):
|
|||
shuffle=self._playlist_randomize)
|
||||
|
||||
# Get a game on deck ready to go.
|
||||
self._current_game_spec: Optional[dict[str, Any]] = None
|
||||
self._current_game_spec: dict[str, Any] | None = None
|
||||
self._next_game_spec: dict[str, Any] = self._playlist.pull_next()
|
||||
self._next_game: type[ba.GameActivity] = (
|
||||
self._next_game_spec['resolved_type'])
|
||||
|
|
@ -278,7 +278,7 @@ class ShuffleList:
|
|||
self.source_list = items
|
||||
self.shuffle = shuffle
|
||||
self.shuffle_list: list[dict[str, Any]] = []
|
||||
self.last_gotten: Optional[dict[str, Any]] = None
|
||||
self.last_gotten: dict[str, Any] | None = None
|
||||
|
||||
def pull_next(self) -> dict[str, Any]:
|
||||
"""Pull and return the next item on the shuffle-list."""
|
||||
|
|
|
|||
19
dist/ba_data/python/ba/_music.py
vendored
19
dist/ba_data/python/ba/_music.py
vendored
|
|
@ -11,7 +11,7 @@ from enum import Enum
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any, Optional, Union
|
||||
from typing import Callable, Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -127,11 +127,11 @@ class MusicSubsystem:
|
|||
|
||||
def __init__(self) -> None:
|
||||
# pylint: disable=cyclic-import
|
||||
self._music_node: Optional[_ba.Node] = None
|
||||
self._music_node: _ba.Node | None = None
|
||||
self._music_mode: MusicPlayMode = MusicPlayMode.REGULAR
|
||||
self._music_player: Optional[MusicPlayer] = None
|
||||
self._music_player_type: Optional[type[MusicPlayer]] = None
|
||||
self.music_types: dict[MusicPlayMode, Optional[MusicType]] = {
|
||||
self._music_player: MusicPlayer | None = None
|
||||
self._music_player_type: type[MusicPlayer] | None = None
|
||||
self.music_types: dict[MusicPlayMode, MusicType | None] = {
|
||||
MusicPlayMode.REGULAR: None,
|
||||
MusicPlayMode.TEST: None
|
||||
}
|
||||
|
|
@ -270,7 +270,7 @@ class MusicSubsystem:
|
|||
self.do_play_music(None)
|
||||
|
||||
def do_play_music(self,
|
||||
musictype: Union[MusicType, str, None],
|
||||
musictype: MusicType | str | None,
|
||||
continuous: bool = False,
|
||||
mode: MusicPlayMode = MusicPlayMode.REGULAR,
|
||||
testsoundtrack: dict[str, Any] = None) -> None:
|
||||
|
|
@ -352,7 +352,7 @@ class MusicSubsystem:
|
|||
# Do the thing.
|
||||
self.get_music_player().play(entry)
|
||||
|
||||
def _play_internal_music(self, musictype: Optional[MusicType]) -> None:
|
||||
def _play_internal_music(self, musictype: MusicType | None) -> None:
|
||||
|
||||
# Stop any existing music-player playback.
|
||||
if self._music_player is not None:
|
||||
|
|
@ -393,7 +393,7 @@ class MusicPlayer:
|
|||
|
||||
def __init__(self) -> None:
|
||||
self._have_set_initial_volume = False
|
||||
self._entry_to_play: Optional[Any] = None
|
||||
self._entry_to_play: Any = None
|
||||
self._volume = 1.0
|
||||
self._actually_playing = False
|
||||
|
||||
|
|
@ -470,8 +470,7 @@ class MusicPlayer:
|
|||
self._actually_playing = False
|
||||
|
||||
|
||||
def setmusic(musictype: Optional[ba.MusicType],
|
||||
continuous: bool = False) -> None:
|
||||
def setmusic(musictype: ba.MusicType | None, continuous: bool = False) -> None:
|
||||
"""Set the app to play (or stop playing) a certain type of music.
|
||||
|
||||
category: **Gameplay Functions**
|
||||
|
|
|
|||
16
dist/ba_data/python/ba/_net.py
vendored
16
dist/ba_data/python/ba/_net.py
vendored
|
|
@ -12,9 +12,9 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
import socket
|
||||
MasterServerCallback = Callable[[Union[None, dict[str, Any]]], None]
|
||||
MasterServerCallback = Callable[[None | dict[str, Any]], None]
|
||||
|
||||
# Timeout for standard functions talking to the master-server/etc.
|
||||
DEFAULT_REQUEST_TIMEOUT_SECONDS = 60
|
||||
|
|
@ -72,8 +72,8 @@ class MasterServerCallThread(threading.Thread):
|
|||
"""Thread to communicate with the master-server."""
|
||||
|
||||
def __init__(self, request: str, request_type: str,
|
||||
data: Optional[dict[str, Any]],
|
||||
callback: Optional[MasterServerCallback],
|
||||
data: dict[str, Any] | None,
|
||||
callback: MasterServerCallback | None,
|
||||
response_type: MasterServerResponseType):
|
||||
super().__init__()
|
||||
self._request = request
|
||||
|
|
@ -82,7 +82,7 @@ class MasterServerCallThread(threading.Thread):
|
|||
raise TypeError(f'Invalid response type: {response_type}')
|
||||
self._response_type = response_type
|
||||
self._data = {} if data is None else copy.deepcopy(data)
|
||||
self._callback: Optional[MasterServerCallback] = callback
|
||||
self._callback: MasterServerCallback | None = callback
|
||||
self._context = _ba.Context('current')
|
||||
|
||||
# Save and restore the context we were created from.
|
||||
|
|
@ -90,7 +90,7 @@ class MasterServerCallThread(threading.Thread):
|
|||
self._activity = weakref.ref(
|
||||
activity) if activity is not None else None
|
||||
|
||||
def _run_callback(self, arg: Union[None, dict[str, Any]]) -> None:
|
||||
def _run_callback(self, arg: None | dict[str, Any]) -> None:
|
||||
# If we were created in an activity context and that activity has
|
||||
# since died, do nothing.
|
||||
# FIXME: Should we just be using a ContextCall instead of doing
|
||||
|
|
@ -182,7 +182,7 @@ class MasterServerCallThread(threading.Thread):
|
|||
def master_server_get(
|
||||
request: str,
|
||||
data: dict[str, Any],
|
||||
callback: Optional[MasterServerCallback] = None,
|
||||
callback: MasterServerCallback | None = None,
|
||||
response_type: MasterServerResponseType = MasterServerResponseType.JSON
|
||||
) -> None:
|
||||
"""Make a call to the master server via a http GET."""
|
||||
|
|
@ -193,7 +193,7 @@ def master_server_get(
|
|||
def master_server_post(
|
||||
request: str,
|
||||
data: dict[str, Any],
|
||||
callback: Optional[MasterServerCallback] = None,
|
||||
callback: MasterServerCallback | None = None,
|
||||
response_type: MasterServerResponseType = MasterServerResponseType.JSON
|
||||
) -> None:
|
||||
"""Make a call to the master server via a http POST."""
|
||||
|
|
|
|||
15
dist/ba_data/python/ba/_player.py
vendored
15
dist/ba_data/python/ba/_player.py
vendored
|
|
@ -13,7 +13,7 @@ from ba._error import (SessionPlayerNotFoundError, print_exception,
|
|||
from ba._messages import DeathType, DieMessage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Sequence, Any, Union, Callable
|
||||
from typing import Sequence, Any, Callable
|
||||
import ba
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
|
|
@ -39,7 +39,7 @@ class StandLocation:
|
|||
Category: Gameplay Classes
|
||||
"""
|
||||
position: ba.Vec3
|
||||
angle: Optional[float] = None
|
||||
angle: float | None = None
|
||||
|
||||
|
||||
class Player(Generic[TeamType]):
|
||||
|
|
@ -56,7 +56,7 @@ class Player(Generic[TeamType]):
|
|||
# their type annotations are introspectable (for docs generation).
|
||||
character: str
|
||||
|
||||
actor: Optional[ba.Actor]
|
||||
actor: ba.Actor | None
|
||||
"""The ba.Actor associated with the player."""
|
||||
|
||||
color: Sequence[float]
|
||||
|
|
@ -64,7 +64,7 @@ class Player(Generic[TeamType]):
|
|||
|
||||
_team: TeamType
|
||||
_sessionplayer: ba.SessionPlayer
|
||||
_nodeactor: Optional[ba.NodeActor]
|
||||
_nodeactor: ba.NodeActor | None
|
||||
_expired: bool
|
||||
_postinited: bool
|
||||
_customdata: dict
|
||||
|
|
@ -94,7 +94,7 @@ class Player(Generic[TeamType]):
|
|||
|
||||
self.actor = None
|
||||
self.character = ''
|
||||
self._nodeactor: Optional[ba.NodeActor] = None
|
||||
self._nodeactor: ba.NodeActor | None = None
|
||||
self._sessionplayer = sessionplayer
|
||||
self.character = sessionplayer.character
|
||||
self.color = sessionplayer.color
|
||||
|
|
@ -249,8 +249,7 @@ class Player(Generic[TeamType]):
|
|||
assert not self._expired
|
||||
return self._sessionplayer.get_icon()
|
||||
|
||||
def assigninput(self, inputtype: Union[ba.InputType, tuple[ba.InputType,
|
||||
...]],
|
||||
def assigninput(self, inputtype: ba.InputType | tuple[ba.InputType, ...],
|
||||
call: Callable) -> None:
|
||||
"""
|
||||
Set the python callable to be run for one or more types of input.
|
||||
|
|
@ -313,7 +312,7 @@ def playercast(totype: type[PlayerType], player: ba.Player) -> PlayerType:
|
|||
# for the optional variety, but that currently seems to not be working.
|
||||
# See: https://github.com/python/mypy/issues/8800
|
||||
def playercast_o(totype: type[PlayerType],
|
||||
player: Optional[ba.Player]) -> Optional[PlayerType]:
|
||||
player: ba.Player | None) -> PlayerType | None:
|
||||
"""A variant of ba.playercast() for use with optional ba.Player values.
|
||||
|
||||
Category: Gameplay Functions
|
||||
|
|
|
|||
29
dist/ba_data/python/ba/_plugin.py
vendored
29
dist/ba_data/python/ba/_plugin.py
vendored
|
|
@ -25,16 +25,16 @@ class PluginSubsystem:
|
|||
self.potential_plugins: list[ba.PotentialPlugin] = []
|
||||
self.active_plugins: dict[str, ba.Plugin] = {}
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Should be called at app launch time."""
|
||||
# Load up our plugins and go ahead and call their on_app_launch calls.
|
||||
def on_app_running(self) -> None:
|
||||
"""Should be called when the app reaches the running state."""
|
||||
# Load up our plugins and go ahead and call their on_app_running calls.
|
||||
self.load_plugins()
|
||||
for plugin in self.active_plugins.values():
|
||||
try:
|
||||
plugin.on_app_launch()
|
||||
plugin.on_app_running()
|
||||
except Exception:
|
||||
from ba import _error
|
||||
_error.print_exception('Error in plugin on_app_launch()')
|
||||
_error.print_exception('Error in plugin on_app_running()')
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called when the app goes to a suspended state."""
|
||||
|
|
@ -80,16 +80,23 @@ class PluginSubsystem:
|
|||
try:
|
||||
cls = getclass(plugkey, Plugin)
|
||||
except Exception as exc:
|
||||
_ba.log(f"Error loading plugin class '{plugkey}': {exc}",
|
||||
to_server=False)
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
# TODO: Lstr.
|
||||
errstr = f"Error loading plugin class '{plugkey}': {exc}"
|
||||
_ba.screenmessage(errstr, color=(1, 0, 0))
|
||||
_ba.log(errstr, to_server=False)
|
||||
continue
|
||||
try:
|
||||
plugin = cls()
|
||||
assert plugkey not in self.active_plugins
|
||||
self.active_plugins[plugkey] = plugin
|
||||
except Exception:
|
||||
except Exception as exc:
|
||||
from ba import _error
|
||||
_error.print_exception(f'Error loading plugin: {plugkey}')
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
# TODO: Lstr.
|
||||
_ba.screenmessage(f"Error loading plugin: '{plugkey}': {exc}",
|
||||
color=(1, 0, 0))
|
||||
_error.print_exception(f"Error loading plugin: '{plugkey}'.")
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -119,8 +126,8 @@ class Plugin:
|
|||
app is running in order to modify its behavior in some way.
|
||||
"""
|
||||
|
||||
def on_app_launch(self) -> None:
|
||||
"""Called when the app is being launched."""
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when the app reaches the running state."""
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called after pausing game activity."""
|
||||
|
|
|
|||
4
dist/ba_data/python/ba/_powerup.py
vendored
4
dist/ba_data/python/ba/_powerup.py
vendored
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
|
|||
from dataclasses import dataclass
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Optional
|
||||
from typing import Sequence
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ class PowerupMessage:
|
|||
"""The type of powerup to be granted (a string).
|
||||
See ba.Powerup.poweruptype for available type values."""
|
||||
|
||||
sourcenode: Optional[ba.Node] = None
|
||||
sourcenode: ba.Node | None = None
|
||||
"""The node the powerup game from, or None otherwise.
|
||||
If a powerup is accepted, a ba.PowerupAcceptMessage should be sent
|
||||
back to the sourcenode to inform it of the fact. This will generally
|
||||
|
|
|
|||
4
dist/ba_data/python/ba/_profile.py
vendored
4
dist/ba_data/python/ba/_profile.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
# NOTE: player color options are enforced server-side for non-pro accounts
|
||||
# so don't change these or they won't stick...
|
||||
|
|
@ -49,7 +49,7 @@ def get_player_profile_icon(profilename: str) -> str:
|
|||
|
||||
|
||||
def get_player_profile_colors(
|
||||
profilename: Optional[str],
|
||||
profilename: str | None,
|
||||
profiles: dict[str, dict[str, Any]] = None
|
||||
) -> tuple[tuple[float, float, float], tuple[float, float, float]]:
|
||||
"""Given a profile, return colors for them."""
|
||||
|
|
|
|||
12
dist/ba_data/python/ba/_servermode.py
vendored
12
dist/ba_data/python/ba/_servermode.py
vendored
|
|
@ -19,7 +19,7 @@ from ba._dualteamsession import DualTeamSession
|
|||
from ba._coopsession import CoopSession
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any
|
||||
from typing import Any
|
||||
|
||||
import ba
|
||||
from bacommon.servermanager import ServerConfig
|
||||
|
|
@ -85,10 +85,10 @@ class ServerController:
|
|||
self._config = config
|
||||
self._playlist_name = '__default__'
|
||||
self._ran_access_check = False
|
||||
self._prep_timer: Optional[ba.Timer] = None
|
||||
self._prep_timer: ba.Timer | None = None
|
||||
self._next_stuck_login_warn_time = time.time() + 10.0
|
||||
self._first_run = True
|
||||
self._shutdown_reason: Optional[ShutdownReason] = None
|
||||
self._shutdown_reason: ShutdownReason | None = None
|
||||
self._executing_shutdown = False
|
||||
|
||||
# Make note if they want us to import a playlist;
|
||||
|
|
@ -129,7 +129,7 @@ class ServerController:
|
|||
out += f'\n{clientid:<{col1}} {name:<{col2}} {players}'
|
||||
print(out)
|
||||
|
||||
def kick(self, client_id: int, ban_time: Optional[int]) -> None:
|
||||
def kick(self, client_id: int, ban_time: int | None) -> None:
|
||||
"""Kick the provided client id.
|
||||
|
||||
ban_time is provided in seconds.
|
||||
|
|
@ -198,7 +198,7 @@ class ServerController:
|
|||
callback=self._access_check_response,
|
||||
)
|
||||
|
||||
def _access_check_response(self, data: Optional[dict[str, Any]]) -> None:
|
||||
def _access_check_response(self, data: dict[str, Any] | None) -> None:
|
||||
import os
|
||||
if data is None:
|
||||
print('error on UDP port access check (internet down?)')
|
||||
|
|
@ -267,7 +267,7 @@ class ServerController:
|
|||
|
||||
def _on_playlist_fetch_response(
|
||||
self,
|
||||
result: Optional[dict[str, Any]],
|
||||
result: dict[str, Any] | None,
|
||||
) -> None:
|
||||
if result is None:
|
||||
print('Error fetching playlist; aborting.')
|
||||
|
|
|
|||
20
dist/ba_data/python/ba/_session.py
vendored
20
dist/ba_data/python/ba/_session.py
vendored
|
|
@ -12,7 +12,7 @@ from ba._language import Lstr
|
|||
from ba._player import Player
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Any, Optional
|
||||
from typing import Sequence, Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ class Session:
|
|||
self._sessiondata = _ba.register_session(self)
|
||||
|
||||
# Should remove this if possible.
|
||||
self.tournament_id: Optional[str] = None
|
||||
self.tournament_id: str | None = None
|
||||
|
||||
self.sessionteams = []
|
||||
self.sessionplayers = []
|
||||
|
|
@ -144,16 +144,16 @@ class Session:
|
|||
self.customdata = {}
|
||||
self._in_set_activity = False
|
||||
self._next_team_id = 0
|
||||
self._activity_retained: Optional[ba.Activity] = None
|
||||
self._launch_end_session_activity_time: Optional[float] = None
|
||||
self._activity_end_timer: Optional[ba.Timer] = None
|
||||
self._activity_retained: ba.Activity | None = None
|
||||
self._launch_end_session_activity_time: float | None = None
|
||||
self._activity_end_timer: ba.Timer | None = None
|
||||
self._activity_weak = empty_weakref(Activity)
|
||||
self._next_activity: Optional[ba.Activity] = None
|
||||
self._next_activity: ba.Activity | None = None
|
||||
self._wants_to_end = False
|
||||
self._ending = False
|
||||
self._activity_should_end_immediately = False
|
||||
self._activity_should_end_immediately_results: (
|
||||
Optional[ba.GameResults]) = None
|
||||
self._activity_should_end_immediately_results: (ba.GameResults
|
||||
| None) = None
|
||||
self._activity_should_end_immediately_delay = 0.0
|
||||
|
||||
# Create static teams if we're using them.
|
||||
|
|
@ -285,7 +285,7 @@ class Session:
|
|||
self.sessionplayers.remove(sessionplayer)
|
||||
|
||||
def _remove_player_team(self, sessionteam: ba.SessionTeam,
|
||||
activity: Optional[ba.Activity]) -> None:
|
||||
activity: ba.Activity | None) -> None:
|
||||
"""Remove the player-specific team in non-teams mode."""
|
||||
|
||||
# They should have been the only one on their team.
|
||||
|
|
@ -481,7 +481,7 @@ class Session:
|
|||
timetype=TimeType.REAL)
|
||||
self._in_set_activity = False
|
||||
|
||||
def getactivity(self) -> Optional[ba.Activity]:
|
||||
def getactivity(self) -> ba.Activity | None:
|
||||
"""Return the current foreground activity for this session."""
|
||||
return self._activity_weak()
|
||||
|
||||
|
|
|
|||
32
dist/ba_data/python/ba/_stats.py
vendored
32
dist/ba_data/python/ba/_stats.py
vendored
|
|
@ -14,7 +14,7 @@ from ba._error import (print_exception, print_error, SessionTeamNotFoundError,
|
|||
|
||||
if TYPE_CHECKING:
|
||||
import ba
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -49,12 +49,12 @@ class PlayerRecord:
|
|||
self.accum_kill_count = 0
|
||||
self.killed_count = 0
|
||||
self.accum_killed_count = 0
|
||||
self._multi_kill_timer: Optional[ba.Timer] = None
|
||||
self._multi_kill_timer: ba.Timer | None = None
|
||||
self._multi_kill_count = 0
|
||||
self._stats = weakref.ref(stats)
|
||||
self._last_sessionplayer: Optional[ba.SessionPlayer] = None
|
||||
self._sessionplayer: Optional[ba.SessionPlayer] = None
|
||||
self._sessionteam: Optional[weakref.ref[ba.SessionTeam]] = None
|
||||
self._last_sessionplayer: ba.SessionPlayer | None = None
|
||||
self._sessionplayer: ba.SessionPlayer | None = None
|
||||
self._sessionteam: weakref.ref[ba.SessionTeam] | None = None
|
||||
self.streak = 0
|
||||
self.associate_with_sessionplayer(sessionplayer)
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ class PlayerRecord:
|
|||
"""Cancel any multi-kill timer for this player entry."""
|
||||
self._multi_kill_timer = None
|
||||
|
||||
def getactivity(self) -> Optional[ba.Activity]:
|
||||
def getactivity(self) -> ba.Activity | None:
|
||||
"""Return the ba.Activity this instance is currently associated with.
|
||||
|
||||
Returns None if the activity no longer exists."""
|
||||
|
|
@ -178,12 +178,12 @@ class PlayerRecord:
|
|||
|
||||
def _apply(name2: Lstr, score2: int, showpoints2: bool,
|
||||
color2: tuple[float, float, float, float], scale2: float,
|
||||
sound2: Optional[ba.Sound]) -> None:
|
||||
sound2: ba.Sound | None) -> None:
|
||||
from bastd.actor.popuptext import PopupText
|
||||
|
||||
# Only award this if they're still alive and we can get
|
||||
# a current position for them.
|
||||
our_pos: Optional[ba.Vec3] = None
|
||||
our_pos: ba.Vec3 | None = None
|
||||
if self._sessionplayer:
|
||||
if self._sessionplayer.activityplayer is not None:
|
||||
try:
|
||||
|
|
@ -233,14 +233,14 @@ class Stats:
|
|||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._activity: Optional[weakref.ref[ba.Activity]] = None
|
||||
self._activity: weakref.ref[ba.Activity] | None = None
|
||||
self._player_records: dict[str, PlayerRecord] = {}
|
||||
self.orchestrahitsound1: Optional[ba.Sound] = None
|
||||
self.orchestrahitsound2: Optional[ba.Sound] = None
|
||||
self.orchestrahitsound3: Optional[ba.Sound] = None
|
||||
self.orchestrahitsound4: Optional[ba.Sound] = None
|
||||
self.orchestrahitsound1: ba.Sound | None = None
|
||||
self.orchestrahitsound2: ba.Sound | None = None
|
||||
self.orchestrahitsound3: ba.Sound | None = None
|
||||
self.orchestrahitsound4: ba.Sound | None = None
|
||||
|
||||
def setactivity(self, activity: Optional[ba.Activity]) -> None:
|
||||
def setactivity(self, activity: ba.Activity | None) -> None:
|
||||
"""Set the current activity for this instance."""
|
||||
|
||||
self._activity = None if activity is None else weakref.ref(activity)
|
||||
|
|
@ -253,7 +253,7 @@ class Stats:
|
|||
with _ba.Context(activity):
|
||||
self._load_activity_media()
|
||||
|
||||
def getactivity(self) -> Optional[ba.Activity]:
|
||||
def getactivity(self) -> ba.Activity | None:
|
||||
"""Get the activity associated with this instance.
|
||||
|
||||
May return None.
|
||||
|
|
@ -319,7 +319,7 @@ class Stats:
|
|||
victim_player: ba.Player = None,
|
||||
scale: float = 1.0,
|
||||
color: Sequence[float] = None,
|
||||
title: Union[str, ba.Lstr] = None,
|
||||
title: str | ba.Lstr | None = None,
|
||||
screenmessage: bool = True,
|
||||
display: bool = True,
|
||||
importance: int = 1,
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/_store.py
vendored
8
dist/ba_data/python/ba/_store.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any
|
||||
from typing import Any
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -434,7 +434,7 @@ def _calc_count_for_tab(tabval: list[dict[str, Any]], our_tickets: int,
|
|||
return count
|
||||
|
||||
|
||||
def get_available_sale_time(tab: str) -> Optional[int]:
|
||||
def get_available_sale_time(tab: str) -> int | None:
|
||||
"""(internal)"""
|
||||
# pylint: disable=too-many-branches
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
|
|
@ -443,7 +443,7 @@ def get_available_sale_time(tab: str) -> Optional[int]:
|
|||
import datetime
|
||||
from ba._generated.enums import TimeType, TimeFormat
|
||||
app = _ba.app
|
||||
sale_times: list[Optional[int]] = []
|
||||
sale_times: list[int | None] = []
|
||||
|
||||
# Calc time for our pro sale (old special case).
|
||||
if tab == 'extras':
|
||||
|
|
@ -475,7 +475,7 @@ def get_available_sale_time(tab: str) -> Optional[int]:
|
|||
return None
|
||||
|
||||
assert app.pro_sale_start_val is not None
|
||||
val: Optional[int] = max(
|
||||
val: int | None = max(
|
||||
0, app.pro_sale_start_val -
|
||||
(_ba.time(TimeType.REAL, TimeFormat.MILLISECONDS) -
|
||||
app.pro_sale_start_time))
|
||||
|
|
|
|||
12
dist/ba_data/python/ba/_team.py
vendored
12
dist/ba_data/python/ba/_team.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, TypeVar, Generic
|
|||
from ba._error import print_exception
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Sequence, Union, Optional
|
||||
from typing import Sequence
|
||||
import ba
|
||||
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ class SessionTeam:
|
|||
|
||||
# Annotate our attr types at the class level so they're introspectable.
|
||||
|
||||
name: Union[ba.Lstr, str]
|
||||
name: ba.Lstr | str
|
||||
"""The team's name."""
|
||||
|
||||
color: tuple[float, ...] # FIXME: can't we make this fixed len?
|
||||
|
|
@ -46,7 +46,7 @@ class SessionTeam:
|
|||
|
||||
def __init__(self,
|
||||
team_id: int = 0,
|
||||
name: Union[ba.Lstr, str] = '',
|
||||
name: ba.Lstr | str = '',
|
||||
color: Sequence[float] = (1.0, 1.0, 1.0)):
|
||||
"""Instantiate a ba.SessionTeam.
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ class SessionTeam:
|
|||
self.color = tuple(color)
|
||||
self.players = []
|
||||
self.customdata = {}
|
||||
self.activityteam: Optional[Team] = None
|
||||
self.activityteam: Team | None = None
|
||||
|
||||
def leave(self) -> None:
|
||||
"""(internal)"""
|
||||
|
|
@ -84,7 +84,7 @@ class Team(Generic[PlayerType]):
|
|||
# that types are introspectable (these are still instance attrs).
|
||||
players: list[PlayerType]
|
||||
id: int
|
||||
name: Union[ba.Lstr, str]
|
||||
name: ba.Lstr | str
|
||||
color: tuple[float, ...] # FIXME: can't we make this fixed length?
|
||||
_sessionteam: weakref.ref[SessionTeam]
|
||||
_expired: bool
|
||||
|
|
@ -120,7 +120,7 @@ class Team(Generic[PlayerType]):
|
|||
self._expired = False
|
||||
self._postinited = True
|
||||
|
||||
def manual_init(self, team_id: int, name: Union[ba.Lstr, str],
|
||||
def manual_init(self, team_id: int, name: ba.Lstr | str,
|
||||
color: tuple[float, ...]) -> None:
|
||||
"""Manually init a team for uses such as bots."""
|
||||
self.id = team_id
|
||||
|
|
|
|||
17
dist/ba_data/python/ba/_ui.py
vendored
17
dist/ba_data/python/ba/_ui.py
vendored
|
|
@ -10,7 +10,7 @@ import _ba
|
|||
from ba._generated.enums import UIScale
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Callable
|
||||
from typing import Any, Callable
|
||||
from ba.ui import UICleanupCheck
|
||||
import ba
|
||||
|
||||
|
|
@ -26,10 +26,10 @@ class UISubsystem:
|
|||
def __init__(self) -> None:
|
||||
env = _ba.env()
|
||||
|
||||
self.controller: Optional[ba.UIController] = None
|
||||
self.controller: ba.UIController | None = None
|
||||
|
||||
self._main_menu_window: Optional[ba.Widget] = None
|
||||
self._main_menu_location: Optional[str] = None
|
||||
self._main_menu_window: ba.Widget | None = None
|
||||
self._main_menu_location: str | None = None
|
||||
|
||||
self._uiscale: ba.UIScale
|
||||
|
||||
|
|
@ -44,13 +44,12 @@ class UISubsystem:
|
|||
raise RuntimeError(f'Invalid UIScale value: {interfacetype}')
|
||||
|
||||
self.window_states: dict[type, Any] = {} # FIXME: Kill this.
|
||||
self.main_menu_selection: Optional[str] = None # FIXME: Kill this.
|
||||
self.main_menu_selection: str | None = None # FIXME: Kill this.
|
||||
self.have_party_queue_window = False
|
||||
self.quit_window: Any = None
|
||||
self.dismiss_wii_remotes_window_call: (Optional[Callable[[],
|
||||
Any]]) = None
|
||||
self.dismiss_wii_remotes_window_call: (Callable[[], Any] | None) = None
|
||||
self.cleanupchecks: list[UICleanupCheck] = []
|
||||
self.upkeeptimer: Optional[ba.Timer] = None
|
||||
self.upkeeptimer: ba.Timer | None = None
|
||||
self.use_toolbars = env.get('toolbar_test', True)
|
||||
self.party_window: Any = None # FIXME: Don't use Any.
|
||||
self.title_color = (0.72, 0.7, 0.75)
|
||||
|
|
@ -162,6 +161,6 @@ class UISubsystem:
|
|||
"""Set the location represented by the current main menu window."""
|
||||
self._main_menu_location = location
|
||||
|
||||
def get_main_menu_location(self) -> Optional[str]:
|
||||
def get_main_menu_location(self) -> str | None:
|
||||
"""Return the current named main menu location, if any."""
|
||||
return self._main_menu_location
|
||||
|
|
|
|||
196
dist/ba_data/python/ba/_workspace.py
vendored
Normal file
196
dist/ba_data/python/ba/_workspace.py
vendored
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Workspace related functionality."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from threading import Thread
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from efro.call import tpartial
|
||||
from efro.error import CleanError
|
||||
import _ba
|
||||
import bacommon.cloud
|
||||
from bacommon.transfer import DirectoryManifest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable
|
||||
|
||||
import ba
|
||||
|
||||
|
||||
class WorkspaceSubsystem:
|
||||
"""Subsystem for workspace handling in the app.
|
||||
|
||||
Category: **App Classes**
|
||||
|
||||
Access the single shared instance of this class at `ba.app.workspaces`.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def set_active_workspace(
|
||||
self,
|
||||
workspaceid: str,
|
||||
workspacename: str,
|
||||
on_completed: Callable[[], None],
|
||||
) -> None:
|
||||
"""(internal)"""
|
||||
|
||||
# Do our work in a background thread so we don't destroy
|
||||
# interactivity.
|
||||
Thread(
|
||||
target=lambda: self._set_active_workspace_bg(
|
||||
workspaceid=workspaceid,
|
||||
workspacename=workspacename,
|
||||
on_completed=on_completed),
|
||||
daemon=True,
|
||||
).start()
|
||||
|
||||
def _errmsg(self, msg: str | ba.Lstr) -> None:
|
||||
_ba.screenmessage(msg, color=(1, 0, 0))
|
||||
_ba.playsound(_ba.getsound('error'))
|
||||
|
||||
def _successmsg(self, msg: str | ba.Lstr) -> None:
|
||||
_ba.screenmessage(msg, color=(0, 1, 0))
|
||||
_ba.playsound(_ba.getsound('gunCocking'))
|
||||
|
||||
def _set_active_workspace_bg(self, workspaceid: str, workspacename: str,
|
||||
on_completed: Callable[[], None]) -> None:
|
||||
# pylint: disable=too-many-branches
|
||||
|
||||
class _SkipSyncError(RuntimeError):
|
||||
pass
|
||||
|
||||
set_path = True
|
||||
wspath = Path(_ba.get_volatile_data_directory(), 'workspaces',
|
||||
workspaceid)
|
||||
try:
|
||||
|
||||
# If it seems we're offline, don't even attempt a sync,
|
||||
# but allow using the previous synced state.
|
||||
# (is this a good idea?)
|
||||
if not _ba.app.cloud.is_connected():
|
||||
raise _SkipSyncError()
|
||||
|
||||
manifest = DirectoryManifest.create_from_disk(wspath)
|
||||
|
||||
# FIXME: Should implement a way to pass account credentials in
|
||||
# from the logic thread.
|
||||
state = bacommon.cloud.WorkspaceFetchState(manifest=manifest)
|
||||
|
||||
while True:
|
||||
response = _ba.app.cloud.send_message(
|
||||
bacommon.cloud.WorkspaceFetchMessage(
|
||||
workspaceid=workspaceid, state=state))
|
||||
state = response.state
|
||||
self._handle_deletes(workspace_dir=wspath,
|
||||
deletes=response.deletes)
|
||||
self._handle_downloads_inline(
|
||||
workspace_dir=wspath,
|
||||
downloads_inline=response.downloads_inline)
|
||||
if response.done:
|
||||
# Server only deals in files; let's clean up any
|
||||
# leftover empty dirs after the dust has cleared.
|
||||
self._handle_dir_prune_empty(str(wspath))
|
||||
break
|
||||
state.iteration += 1
|
||||
|
||||
extras: list[str] = []
|
||||
# Hmm; let's not show deletes for now since currently lots of
|
||||
# .pyc files get deleted.
|
||||
if bool(False):
|
||||
if state.total_deletes:
|
||||
extras.append(f'{state.total_deletes} files deleted')
|
||||
if state.total_downloads:
|
||||
extras.append(f'{state.total_downloads} files downloaded')
|
||||
if state.total_up_to_date:
|
||||
extras.append(f'{state.total_up_to_date} files up-to-date')
|
||||
# Actually let's try with none of this; seems a bit excessive.
|
||||
if bool(False) and extras:
|
||||
extras_s = '\n' + ', '.join(extras) + '.'
|
||||
else:
|
||||
extras_s = ''
|
||||
_ba.pushcall(tpartial(self._successmsg,
|
||||
f'{workspacename} activated.{extras_s}'),
|
||||
from_other_thread=True)
|
||||
|
||||
except _SkipSyncError:
|
||||
_ba.pushcall(tpartial(
|
||||
self._errmsg, f'Can\'t sync {workspacename}'
|
||||
f'. Reusing previous synced version.'),
|
||||
from_other_thread=True)
|
||||
|
||||
except CleanError as exc:
|
||||
# Avoid reusing existing if we fail in the middle; could
|
||||
# be in wonky state.
|
||||
set_path = False
|
||||
_ba.pushcall(tpartial(self._errmsg, str(exc)),
|
||||
from_other_thread=True)
|
||||
except Exception:
|
||||
# Ditto.
|
||||
set_path = False
|
||||
logging.exception('Error syncing workspace.')
|
||||
# TODO: Lstr.
|
||||
_ba.pushcall(tpartial(
|
||||
self._errmsg, 'Error syncing workspace. See log for details.'),
|
||||
from_other_thread=True)
|
||||
|
||||
if set_path and wspath.is_dir():
|
||||
# Add to Python paths and also to list of stuff to be scanned
|
||||
# for meta tags.
|
||||
sys.path.insert(0, str(wspath))
|
||||
_ba.app.meta.extra_scan_dirs.append(str(wspath))
|
||||
|
||||
# Job's done!
|
||||
_ba.pushcall(on_completed, from_other_thread=True)
|
||||
|
||||
def _handle_deletes(self, workspace_dir: Path, deletes: list[str]) -> None:
|
||||
"""Handle file deletes."""
|
||||
for fname in deletes:
|
||||
fname = os.path.join(workspace_dir, fname)
|
||||
# Server shouldn't be sending us dir paths here.
|
||||
assert not os.path.isdir(fname)
|
||||
os.unlink(fname)
|
||||
|
||||
def _handle_downloads_inline(
|
||||
self,
|
||||
workspace_dir: Path,
|
||||
downloads_inline: dict[str, bytes],
|
||||
) -> None:
|
||||
"""Handle inline file data to be saved to the client."""
|
||||
for fname, fdata in downloads_inline.items():
|
||||
fname = os.path.join(workspace_dir, fname)
|
||||
# If there's a directory where we want our file to go, clear it
|
||||
# out first. File deletes should have run before this so
|
||||
# everything under it should be empty and thus killable via rmdir.
|
||||
if os.path.isdir(fname):
|
||||
for basename, dirnames, _fn in os.walk(fname, topdown=False):
|
||||
for dirname in dirnames:
|
||||
os.rmdir(os.path.join(basename, dirname))
|
||||
os.rmdir(fname)
|
||||
|
||||
dirname = os.path.dirname(fname)
|
||||
if dirname:
|
||||
os.makedirs(dirname, exist_ok=True)
|
||||
with open(fname, 'wb') as outfile:
|
||||
outfile.write(fdata)
|
||||
|
||||
def _handle_dir_prune_empty(self, prunedir: str) -> None:
|
||||
"""Handle pruning empty directories."""
|
||||
# Walk the tree bottom-up so we can properly kill recursive empty dirs.
|
||||
for basename, dirnames, filenames in os.walk(prunedir, topdown=False):
|
||||
# It seems that child dirs we kill during the walk are still
|
||||
# listed when the parent dir is visited, so lets make sure
|
||||
# to only acknowledge still-existing ones.
|
||||
dirnames = [
|
||||
d for d in dirnames
|
||||
if os.path.exists(os.path.join(basename, d))
|
||||
]
|
||||
if not dirnames and not filenames and basename != prunedir:
|
||||
os.rmdir(basename)
|
||||
10
dist/ba_data/python/ba/macmusicapp.py
vendored
10
dist/ba_data/python/ba/macmusicapp.py
vendored
|
|
@ -10,7 +10,7 @@ import _ba
|
|||
from ba._music import MusicPlayer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Callable, Any
|
||||
from typing import Callable, Any
|
||||
|
||||
|
||||
class MacMusicAppMusicPlayer(MusicPlayer):
|
||||
|
|
@ -62,8 +62,8 @@ class _MacMusicAppThread(threading.Thread):
|
|||
self._commands_available = threading.Event()
|
||||
self._commands: list[list] = []
|
||||
self._volume = 1.0
|
||||
self._current_playlist: Optional[str] = None
|
||||
self._orig_volume: Optional[int] = None
|
||||
self._current_playlist: str | None = None
|
||||
self._orig_volume: int | None = None
|
||||
|
||||
def run(self) -> None:
|
||||
"""Run the Music.app thread."""
|
||||
|
|
@ -136,7 +136,7 @@ class _MacMusicAppThread(threading.Thread):
|
|||
if old_volume == 0.0:
|
||||
self._play_current_playlist()
|
||||
|
||||
def play_playlist(self, musictype: Optional[str]) -> None:
|
||||
def play_playlist(self, musictype: str | None) -> None:
|
||||
"""Play the given playlist."""
|
||||
self._commands.append(['PLAY', musictype])
|
||||
self._commands_available.set()
|
||||
|
|
@ -170,7 +170,7 @@ class _MacMusicAppThread(threading.Thread):
|
|||
playlists = []
|
||||
_ba.pushcall(Call(target, playlists), from_other_thread=True)
|
||||
|
||||
def _handle_play_command(self, target: Optional[str]) -> None:
|
||||
def _handle_play_command(self, target: str | None) -> None:
|
||||
if target is None:
|
||||
if self._current_playlist is not None and self._volume > 0:
|
||||
try:
|
||||
|
|
|
|||
8
dist/ba_data/python/ba/modutils.py
vendored
8
dist/ba_data/python/ba/modutils.py
vendored
|
|
@ -9,7 +9,7 @@ import os
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Sequence
|
||||
from typing import Sequence
|
||||
|
||||
|
||||
def get_human_readable_user_scripts_path() -> str:
|
||||
|
|
@ -19,7 +19,7 @@ def get_human_readable_user_scripts_path() -> str:
|
|||
"""
|
||||
from ba import _language
|
||||
app = _ba.app
|
||||
path: Optional[str] = app.python_directory_user
|
||||
path: str | None = app.python_directory_user
|
||||
if path is None:
|
||||
return '<Not Available>'
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ def get_human_readable_user_scripts_path() -> str:
|
|||
# only visible to the user's processes and thus not really useful printed
|
||||
# in its entirety; lets print it as <External Storage>/myfilepath.
|
||||
if app.platform == 'android':
|
||||
ext_storage_path: Optional[str] = (
|
||||
ext_storage_path: str | None = (
|
||||
_ba.android_get_external_storage_path())
|
||||
if (ext_storage_path is not None
|
||||
and app.python_directory_user.startswith(ext_storage_path)):
|
||||
|
|
@ -70,7 +70,7 @@ def show_user_scripts() -> None:
|
|||
# they can see it.
|
||||
if app.platform == 'android':
|
||||
try:
|
||||
usd: Optional[str] = app.python_directory_user
|
||||
usd: str | None = app.python_directory_user
|
||||
if usd is not None and os.path.isdir(usd):
|
||||
file_name = usd + '/about_this_folder.txt'
|
||||
with open(file_name, 'w', encoding='utf-8') as outfile:
|
||||
|
|
|
|||
9
dist/ba_data/python/ba/osmusic.py
vendored
9
dist/ba_data/python/ba/osmusic.py
vendored
|
|
@ -12,7 +12,7 @@ import _ba
|
|||
from ba._music import MusicPlayer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any, Union, Optional
|
||||
from typing import Callable, Any
|
||||
|
||||
|
||||
class OSMusicPlayer(MusicPlayer):
|
||||
|
|
@ -60,8 +60,8 @@ class OSMusicPlayer(MusicPlayer):
|
|||
self._on_play_folder_cb).start()
|
||||
|
||||
def _on_play_folder_cb(self,
|
||||
result: Union[str, list[str]],
|
||||
error: Optional[str] = None) -> None:
|
||||
result: str | list[str],
|
||||
error: str | None = None) -> None:
|
||||
from ba import _language
|
||||
if error is not None:
|
||||
rstr = (_language.Lstr(
|
||||
|
|
@ -95,8 +95,7 @@ class OSMusicPlayer(MusicPlayer):
|
|||
class _PickFolderSongThread(threading.Thread):
|
||||
|
||||
def __init__(self, path: str, valid_extensions: list[str],
|
||||
callback: Callable[[Union[str, list[str]], Optional[str]],
|
||||
None]):
|
||||
callback: Callable[[str | list[str], str | None], None]):
|
||||
super().__init__()
|
||||
self._valid_extensions = valid_extensions
|
||||
self._callback = callback
|
||||
|
|
|
|||
10
dist/ba_data/python/ba/ui/__init__.py
vendored
10
dist/ba_data/python/ba/ui/__init__.py
vendored
|
|
@ -14,7 +14,7 @@ from ba._generated.enums import TimeType
|
|||
from ba._general import print_active_refs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any
|
||||
from typing import Any
|
||||
|
||||
import ba
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ class UICleanupCheck:
|
|||
"""Holds info about a uicleanupcheck target."""
|
||||
obj: weakref.ref
|
||||
widget: ba.Widget
|
||||
widget_death_time: Optional[float]
|
||||
widget_death_time: float | None
|
||||
|
||||
|
||||
class UILocation:
|
||||
|
|
@ -76,7 +76,7 @@ class UILocationWindow(UILocation):
|
|||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._root_widget: Optional[ba.Widget] = None
|
||||
self._root_widget: ba.Widget | None = None
|
||||
|
||||
def get_root_widget(self) -> ba.Widget:
|
||||
"""Return the root widget for this window."""
|
||||
|
|
@ -91,7 +91,7 @@ class UIEntry:
|
|||
self._name = name
|
||||
self._state = None
|
||||
self._args = None
|
||||
self._instance: Optional[UILocation] = None
|
||||
self._instance: UILocation | None = None
|
||||
self._controller = weakref.ref(controller)
|
||||
|
||||
def create(self) -> None:
|
||||
|
|
@ -129,7 +129,7 @@ class UIController:
|
|||
self._main_stack_menu: list[UIEntry] = []
|
||||
|
||||
# This points at either the game or menu stack.
|
||||
self._main_stack: Optional[list[UIEntry]] = None
|
||||
self._main_stack: list[UIEntry] | None = None
|
||||
|
||||
# There's only one of these since we don't need to preserve its state
|
||||
# between sessions.
|
||||
|
|
|
|||
4
dist/ba_data/python/bacommon/assets.py
vendored
4
dist/ba_data/python/bacommon/assets.py
vendored
|
|
@ -5,7 +5,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING, Optional, Annotated
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
from enum import Enum
|
||||
|
||||
from efro.dataclassio import ioprepped, IOAttrs
|
||||
|
|
@ -57,4 +57,4 @@ class AssetPackageBuildState:
|
|||
# Build error string. If this is present, it should be presented
|
||||
# to the user and they should required to explicitly restart the build
|
||||
# in some way if desired.
|
||||
error: Annotated[Optional[str], IOAttrs('e')] = None
|
||||
error: Annotated[str | None, IOAttrs('e')] = None
|
||||
|
|
|
|||
69
dist/ba_data/python/bacommon/bacloud.py
vendored
69
dist/ba_data/python/bacommon/bacloud.py
vendored
|
|
@ -3,18 +3,34 @@
|
|||
"""Functionality related to the bacloud tool."""
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
from efro.dataclassio import ioprepped
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
|
||||
from efro.dataclassio import ioprepped, IOAttrs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
# Version is sent to the master-server with all commands. Can be incremented
|
||||
# if we need to change behavior server-side to go along with client changes.
|
||||
BACLOUD_VERSION = 6
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class Response:
|
||||
class RequestData:
|
||||
"""Request sent to bacloud server."""
|
||||
command: Annotated[str, IOAttrs('c')]
|
||||
token: Annotated[str | None, IOAttrs('t')]
|
||||
payload: Annotated[dict, IOAttrs('p')]
|
||||
tzoffset: Annotated[float, IOAttrs('z')]
|
||||
isatty: Annotated[bool, IOAttrs('y')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class ResponseData:
|
||||
# noinspection PyUnresolvedReferences
|
||||
"""Response sent from the bacloud server to the client.
|
||||
|
||||
|
|
@ -35,10 +51,10 @@ class Response:
|
|||
uploads_inline: If present, a list of pathnames that should be base64
|
||||
gzipped and uploaded to an 'uploads_inline' dict in end_command args.
|
||||
This should be limited to relatively small files.
|
||||
deletes: If present, file paths that should be deleted on the client.
|
||||
downloads_inline: If present, pathnames mapped to base64 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.
|
||||
deletes: If present, file paths that should be deleted on the client.
|
||||
dir_prune_empty: If present, all empty dirs under this one should be
|
||||
removed.
|
||||
open_url: If present, url to display to the user.
|
||||
|
|
@ -52,20 +68,29 @@ class Response:
|
|||
end_command: If present, this command is run with these args at the end
|
||||
of response processing.
|
||||
"""
|
||||
message: Optional[str] = None
|
||||
message_end: str = '\n'
|
||||
error: Optional[str] = None
|
||||
delay_seconds: float = 0.0
|
||||
login: Optional[str] = None
|
||||
logout: bool = False
|
||||
dir_manifest: Optional[str] = None
|
||||
uploads: Optional[tuple[list[str], str, dict]] = None
|
||||
uploads_inline: Optional[list[str]] = None
|
||||
downloads_inline: Optional[dict[str, str]] = None
|
||||
deletes: Optional[list[str]] = None
|
||||
dir_prune_empty: Optional[str] = None
|
||||
open_url: Optional[str] = None
|
||||
input_prompt: Optional[tuple[str, bool]] = None
|
||||
end_message: Optional[str] = None
|
||||
end_message_end: str = '\n'
|
||||
end_command: Optional[tuple[str, dict]] = None
|
||||
message: Annotated[str | None, IOAttrs('m', store_default=False)] = None
|
||||
message_end: Annotated[str, IOAttrs('m_end', store_default=False)] = '\n'
|
||||
error: Annotated[str | None, IOAttrs('e', store_default=False)] = None
|
||||
delay_seconds: Annotated[float, IOAttrs('d', store_default=False)] = 0.0
|
||||
login: Annotated[str | None, IOAttrs('l', store_default=False)] = None
|
||||
logout: Annotated[bool, IOAttrs('lo', store_default=False)] = False
|
||||
dir_manifest: Annotated[str | None,
|
||||
IOAttrs('man', store_default=False)] = None
|
||||
uploads: Annotated[tuple[list[str], str, dict] | None,
|
||||
IOAttrs('u', store_default=False)] = None
|
||||
uploads_inline: Annotated[list[str] | None,
|
||||
IOAttrs('uinl', store_default=False)] = None
|
||||
deletes: Annotated[list[str] | None,
|
||||
IOAttrs('dlt', store_default=False)] = None
|
||||
downloads_inline: Annotated[dict[str, str] | None,
|
||||
IOAttrs('dinl', store_default=False)] = None
|
||||
dir_prune_empty: Annotated[str | None,
|
||||
IOAttrs('dpe', store_default=False)] = None
|
||||
open_url: Annotated[str | None, IOAttrs('url', store_default=False)] = None
|
||||
input_prompt: Annotated[tuple[str, bool] | None,
|
||||
IOAttrs('inp', store_default=False)] = None
|
||||
end_message: Annotated[str | None,
|
||||
IOAttrs('em', store_default=False)] = None
|
||||
end_message_end: Annotated[str, IOAttrs('eme', store_default=False)] = '\n'
|
||||
end_command: Annotated[tuple[str, dict] | None,
|
||||
IOAttrs('ec', store_default=False)] = None
|
||||
|
|
|
|||
67
dist/ba_data/python/bacommon/cloud.py
vendored
67
dist/ba_data/python/bacommon/cloud.py
vendored
|
|
@ -3,12 +3,13 @@
|
|||
"""Functionality related to cloud functionality."""
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Annotated, Optional
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
from enum import Enum
|
||||
|
||||
from efro.message import Message, Response
|
||||
from efro.dataclassio import ioprepped, IOAttrs
|
||||
from bacommon.transfer import DirectoryManifest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
|
@ -65,7 +66,7 @@ class LoginProxyStateQueryResponse(Response):
|
|||
state: Annotated[State, IOAttrs('s')]
|
||||
|
||||
# On success, these will be filled out.
|
||||
credentials: Annotated[Optional[str], IOAttrs('tk')]
|
||||
credentials: Annotated[str | None, IOAttrs('tk')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
|
|
@ -77,27 +78,57 @@ class LoginProxyCompleteMessage(Message):
|
|||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class AccountSessionReleaseMessage(Message):
|
||||
"""We're done using this particular session."""
|
||||
token: Annotated[str, IOAttrs('tk')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class CredentialsCheckMessage(Message):
|
||||
"""Are our current credentials valid?"""
|
||||
class TestMessage(Message):
|
||||
"""Can I get some of that workspace action?"""
|
||||
testfoo: Annotated[int, IOAttrs('f')]
|
||||
|
||||
@classmethod
|
||||
def get_response_types(cls) -> list[type[Response]]:
|
||||
return [CredentialsCheckResponse]
|
||||
return [TestResponse]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class CredentialsCheckResponse(Response):
|
||||
"""Info returned when checking credentials."""
|
||||
class TestResponse(Response):
|
||||
"""Here's that workspace you asked for, boss."""
|
||||
|
||||
verified: Annotated[bool, IOAttrs('v')]
|
||||
testfoo: Annotated[int, IOAttrs('f')]
|
||||
|
||||
# Current account tag (good time to check if it has changed).
|
||||
tag: Annotated[str, IOAttrs('t')]
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class WorkspaceFetchState:
|
||||
"""Common state data for a workspace fetch."""
|
||||
manifest: Annotated[DirectoryManifest, IOAttrs('m')]
|
||||
iteration: Annotated[int, IOAttrs('i')] = 0
|
||||
total_deletes: Annotated[int, IOAttrs('tdels')] = 0
|
||||
total_downloads: Annotated[int, IOAttrs('tdlds')] = 0
|
||||
total_up_to_date: Annotated[int | None, IOAttrs('tunmd')] = None
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class WorkspaceFetchMessage(Message):
|
||||
"""Can I get some of that workspace action?"""
|
||||
workspaceid: Annotated[str, IOAttrs('w')]
|
||||
state: Annotated[WorkspaceFetchState, IOAttrs('s')]
|
||||
|
||||
@classmethod
|
||||
def get_response_types(cls) -> list[type[Response]]:
|
||||
return [WorkspaceFetchResponse]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class WorkspaceFetchResponse(Response):
|
||||
"""Here's that workspace you asked for, boss."""
|
||||
|
||||
state: Annotated[WorkspaceFetchState, IOAttrs('s')]
|
||||
deletes: Annotated[list[str],
|
||||
IOAttrs('dlt', store_default=False)] = field(
|
||||
default_factory=list)
|
||||
downloads_inline: Annotated[dict[str, bytes],
|
||||
IOAttrs('dinl', store_default=False)] = field(
|
||||
default_factory=dict)
|
||||
|
||||
done: Annotated[bool, IOAttrs('d')] = False
|
||||
|
|
|
|||
28
dist/ba_data/python/bacommon/net.py
vendored
28
dist/ba_data/python/bacommon/net.py
vendored
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Optional, Any, Annotated
|
||||
from typing import TYPE_CHECKING, Any, Annotated
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from efro.dataclassio import ioprepped, IOAttrs
|
||||
|
|
@ -28,7 +28,7 @@ class ServerNodeQueryResponse:
|
|||
"""A response to a query about server-nodes."""
|
||||
|
||||
# If present, something went wrong, and this describes it.
|
||||
error: Annotated[Optional[str], IOAttrs('e', store_default=False)] = None
|
||||
error: Annotated[str | None, IOAttrs('e', store_default=False)] = None
|
||||
|
||||
# The set of servernodes.
|
||||
servers: Annotated[list[ServerNodeEntry],
|
||||
|
|
@ -40,11 +40,11 @@ class ServerNodeQueryResponse:
|
|||
@dataclass
|
||||
class PrivateHostingState:
|
||||
"""Combined state of whether we're hosting, whether we can, etc."""
|
||||
unavailable_error: Optional[str] = None
|
||||
party_code: Optional[str] = None
|
||||
unavailable_error: str | None = None
|
||||
party_code: str | None = None
|
||||
tickets_to_host_now: int = 0
|
||||
minutes_until_free_host: Optional[float] = None
|
||||
free_host_minutes_remaining: Optional[float] = None
|
||||
minutes_until_free_host: float | None = None
|
||||
free_host_minutes_remaining: float | None = None
|
||||
|
||||
|
||||
@ioprepped
|
||||
|
|
@ -55,10 +55,10 @@ class PrivateHostingConfig:
|
|||
playlist_name: str = 'Unknown'
|
||||
randomize: bool = False
|
||||
tutorial: bool = False
|
||||
custom_team_names: Optional[tuple[str, str]] = None
|
||||
custom_team_colors: Optional[tuple[tuple[float, float, float],
|
||||
tuple[float, float, float]]] = None
|
||||
playlist: Optional[list[dict[str, Any]]] = None
|
||||
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
|
||||
|
|
@ -68,7 +68,7 @@ class PrivateHostingConfig:
|
|||
@dataclass
|
||||
class PrivatePartyConnectResult:
|
||||
"""Info about a server we get back when connecting."""
|
||||
error: Optional[str] = None
|
||||
addr: Optional[str] = None
|
||||
port: Optional[int] = None
|
||||
password: Optional[str] = None
|
||||
error: str | None = None
|
||||
addr: str | None = None
|
||||
port: int | None = None
|
||||
password: str | None = None
|
||||
|
|
|
|||
30
dist/ba_data/python/bacommon/servermanager.py
vendored
30
dist/ba_data/python/bacommon/servermanager.py
vendored
|
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
|||
|
||||
from enum import Enum
|
||||
from dataclasses import field, dataclass
|
||||
from typing import TYPE_CHECKING, Optional, Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from efro.dataclassio import ioprepped
|
||||
|
||||
|
|
@ -60,11 +60,11 @@ class ServerConfig:
|
|||
# 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: Optional[int] = None
|
||||
playlist_code: int | None = None
|
||||
|
||||
# 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: Optional[list[dict[str, Any]]] = None
|
||||
playlist_inline: list[dict[str, Any]] | None = None
|
||||
|
||||
# Whether to shuffle the playlist or play its games in designated order.
|
||||
playlist_shuffle: bool = True
|
||||
|
|
@ -105,7 +105,7 @@ class ServerConfig:
|
|||
# currently-signed-in account's id. To fetch info about an account,
|
||||
# your back-end server can use the following url:
|
||||
# https://legacy.ballistica.net/accountquery?id=ACCOUNT_ID_HERE
|
||||
stats_url: Optional[str] = None
|
||||
stats_url: str | None = None
|
||||
|
||||
# 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
|
||||
|
|
@ -113,32 +113,32 @@ class ServerConfig:
|
|||
# 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: Optional[float] = None
|
||||
clean_exit_minutes: float | None = None
|
||||
|
||||
# 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: Optional[float] = None
|
||||
unclean_exit_minutes: float | None = None
|
||||
|
||||
# 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: Optional[float] = None
|
||||
idle_exit_minutes: float | None = None
|
||||
|
||||
# Should the tutorial be shown at the beginning of games?
|
||||
show_tutorial: bool = False
|
||||
|
||||
# Team names (teams mode only).
|
||||
team_names: Optional[tuple[str, str]] = None
|
||||
team_names: tuple[str, str] | None = None
|
||||
|
||||
# Team colors (teams mode only).
|
||||
team_colors: Optional[tuple[tuple[float, float, float],
|
||||
tuple[float, float, float]]] = None
|
||||
team_colors: tuple[tuple[float, float, float], tuple[float, float,
|
||||
float]] | None = None
|
||||
|
||||
# (internal) stress-testing mode.
|
||||
stress_test_players: Optional[int] = None
|
||||
stress_test_players: int | None = None
|
||||
|
||||
|
||||
# NOTE: as much as possible, communication from the server-manager to the
|
||||
|
|
@ -171,15 +171,15 @@ class ShutdownCommand(ServerCommand):
|
|||
class ChatMessageCommand(ServerCommand):
|
||||
"""Chat message from the server."""
|
||||
message: str
|
||||
clients: Optional[list[int]]
|
||||
clients: list[int] | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ScreenMessageCommand(ServerCommand):
|
||||
"""Screen-message from the server."""
|
||||
message: str
|
||||
color: Optional[tuple[float, float, float]]
|
||||
clients: Optional[list[int]]
|
||||
color: tuple[float, float, float] | None
|
||||
clients: list[int] | None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -191,4 +191,4 @@ class ClientListCommand(ServerCommand):
|
|||
class KickCommand(ServerCommand):
|
||||
"""Kick a client."""
|
||||
client_id: int
|
||||
ban_time: Optional[int]
|
||||
ban_time: int | None
|
||||
|
|
|
|||
80
dist/ba_data/python/bacommon/transfer.py
vendored
Normal file
80
dist/ba_data/python/bacommon/transfer.py
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Functionality related to transferring files/data."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
|
||||
from efro.dataclassio import ioprepped, IOAttrs
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class DirectoryManifestFile:
|
||||
"""Describes metadata and hashes for a file in a manifest."""
|
||||
filehash: Annotated[str, IOAttrs('h')]
|
||||
filesize: Annotated[int, IOAttrs('s')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class DirectoryManifest:
|
||||
"""Contains a summary of files in a directory."""
|
||||
files: Annotated[dict[str, DirectoryManifestFile], IOAttrs('f')]
|
||||
|
||||
_empty_hash: str | None = None
|
||||
|
||||
@classmethod
|
||||
def create_from_disk(cls, path: Path) -> DirectoryManifest:
|
||||
"""Create a manifest from a directory on disk."""
|
||||
import hashlib
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
pathstr = str(path)
|
||||
paths: list[str] = []
|
||||
|
||||
if path.is_dir():
|
||||
# Build the full list of package-relative paths.
|
||||
for basename, _dirnames, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
fullname = os.path.join(basename, filename)
|
||||
assert fullname.startswith(pathstr)
|
||||
paths.append(fullname[len(pathstr) + 1:])
|
||||
elif path.exists():
|
||||
# Just return a single file entry if path is not a dir.
|
||||
paths.append(pathstr)
|
||||
|
||||
def _get_file_info(filepath: str) -> tuple[str, DirectoryManifestFile]:
|
||||
sha = hashlib.sha256()
|
||||
fullfilepath = os.path.join(pathstr, filepath)
|
||||
if not os.path.isfile(fullfilepath):
|
||||
raise Exception(f'File not found: "{fullfilepath}"')
|
||||
with open(fullfilepath, 'rb') as infile:
|
||||
filebytes = infile.read()
|
||||
filesize = len(filebytes)
|
||||
sha.update(filebytes)
|
||||
return (filepath,
|
||||
DirectoryManifestFile(filehash=sha.hexdigest(),
|
||||
filesize=filesize))
|
||||
|
||||
# Now use all procs to hash the files efficiently.
|
||||
cpus = os.cpu_count()
|
||||
if cpus is None:
|
||||
cpus = 4
|
||||
with ThreadPoolExecutor(max_workers=cpus) as executor:
|
||||
return cls(files=dict(executor.map(_get_file_info, paths)))
|
||||
|
||||
@classmethod
|
||||
def get_empty_hash(cls) -> str:
|
||||
"""Return the hash for an empty file."""
|
||||
if cls._empty_hash is None:
|
||||
import hashlib
|
||||
sha = hashlib.sha256()
|
||||
cls._empty_hash = sha.hexdigest()
|
||||
return cls._empty_hash
|
||||
2
dist/ba_data/python/bastd/__init__.py
vendored
2
dist/ba_data/python/bastd/__init__.py
vendored
|
|
@ -2,4 +2,4 @@
|
|||
#
|
||||
"""Ballistica standard library: games, UI, etc."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import ba
|
|||
from ba.internal import JoinActivity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class CoopJoinActivity(JoinActivity):
|
||||
|
|
@ -54,7 +54,7 @@ class CoopJoinActivity(JoinActivity):
|
|||
ControlsGuide(delay=1.0).autoretain()
|
||||
|
||||
def _on_got_scores_to_beat(self,
|
||||
scores: Optional[list[dict[str, Any]]]) -> None:
|
||||
scores: list[dict[str, Any]] | None) -> None:
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-statements
|
||||
from efro.util import asserttype
|
||||
|
|
@ -87,7 +87,7 @@ class CoopJoinActivity(JoinActivity):
|
|||
delay_inc = 0.1
|
||||
|
||||
def _add_t(
|
||||
text: Union[str, ba.Lstr],
|
||||
text: str | ba.Lstr,
|
||||
h_offs: float = 0.0,
|
||||
scale: float = 1.0,
|
||||
color: Sequence[float] = (1.0, 1.0, 1.0, 0.46)
|
||||
|
|
|
|||
72
dist/ba_data/python/bastd/activity/coopscore.py
vendored
72
dist/ba_data/python/bastd/activity/coopscore.py
vendored
|
|
@ -14,7 +14,7 @@ from bastd.actor.text import Text
|
|||
from bastd.actor.zoomtext import ZoomText
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Any, Sequence
|
||||
from typing import Any, Sequence
|
||||
from bastd.ui.store.button import StoreButton
|
||||
from bastd.ui.league.rankbutton import LeagueRankButton
|
||||
|
||||
|
|
@ -56,9 +56,9 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
if _ba.get_v1_account_state() == 'signed_in' else
|
||||
None)
|
||||
|
||||
self._game_service_icon_color: Optional[Sequence[float]]
|
||||
self._game_service_achievements_texture: Optional[ba.Texture]
|
||||
self._game_service_leaderboards_texture: Optional[ba.Texture]
|
||||
self._game_service_icon_color: Sequence[float] | None
|
||||
self._game_service_achievements_texture: ba.Texture | None
|
||||
self._game_service_leaderboards_texture: ba.Texture | None
|
||||
|
||||
with ba.Context('ui'):
|
||||
if self._account_type == 'Game Center':
|
||||
|
|
@ -89,53 +89,53 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
self._cashregistersound = ba.getsound('cashRegister')
|
||||
self._gun_cocking_sound = ba.getsound('gunCocking')
|
||||
self._dingsound = ba.getsound('ding')
|
||||
self._score_link: Optional[str] = None
|
||||
self._root_ui: Optional[ba.Widget] = None
|
||||
self._background: Optional[ba.Actor] = None
|
||||
self._score_link: str | None = None
|
||||
self._root_ui: ba.Widget | None = None
|
||||
self._background: ba.Actor | None = None
|
||||
self._old_best_rank = 0.0
|
||||
self._game_name_str: Optional[str] = None
|
||||
self._game_config_str: Optional[str] = None
|
||||
self._game_name_str: str | None = None
|
||||
self._game_config_str: str | None = None
|
||||
|
||||
# Ui bits.
|
||||
self._corner_button_offs: Optional[tuple[float, float]] = None
|
||||
self._league_rank_button: Optional[LeagueRankButton] = None
|
||||
self._store_button_instance: Optional[StoreButton] = None
|
||||
self._restart_button: Optional[ba.Widget] = None
|
||||
self._update_corner_button_positions_timer: Optional[ba.Timer] = None
|
||||
self._next_level_error: Optional[ba.Actor] = None
|
||||
self._corner_button_offs: tuple[float, float] | None = None
|
||||
self._league_rank_button: LeagueRankButton | None = None
|
||||
self._store_button_instance: StoreButton | None = None
|
||||
self._restart_button: ba.Widget | None = None
|
||||
self._update_corner_button_positions_timer: ba.Timer | None = None
|
||||
self._next_level_error: ba.Actor | None = None
|
||||
|
||||
# Score/gameplay bits.
|
||||
self._was_complete: Optional[bool] = None
|
||||
self._is_complete: Optional[bool] = None
|
||||
self._newly_complete: Optional[bool] = None
|
||||
self._is_more_levels: Optional[bool] = None
|
||||
self._next_level_name: Optional[str] = None
|
||||
self._show_friend_scores: Optional[bool] = None
|
||||
self._show_info: Optional[dict[str, Any]] = None
|
||||
self._name_str: Optional[str] = None
|
||||
self._friends_loading_status: Optional[ba.Actor] = None
|
||||
self._score_loading_status: Optional[ba.Actor] = None
|
||||
self._tournament_time_remaining: Optional[float] = None
|
||||
self._tournament_time_remaining_text: Optional[Text] = None
|
||||
self._tournament_time_remaining_text_timer: Optional[ba.Timer] = None
|
||||
self._was_complete: bool | None = None
|
||||
self._is_complete: bool | None = None
|
||||
self._newly_complete: bool | None = None
|
||||
self._is_more_levels: bool | None = None
|
||||
self._next_level_name: str | None = None
|
||||
self._show_friend_scores: bool | None = None
|
||||
self._show_info: dict[str, Any] | None = None
|
||||
self._name_str: str | None = None
|
||||
self._friends_loading_status: ba.Actor | None = None
|
||||
self._score_loading_status: ba.Actor | None = None
|
||||
self._tournament_time_remaining: float | None = None
|
||||
self._tournament_time_remaining_text: Text | None = None
|
||||
self._tournament_time_remaining_text_timer: ba.Timer | None = None
|
||||
|
||||
# Stuff for activity skip by pressing button
|
||||
self._birth_time = ba.time()
|
||||
self._min_view_time = 5.0
|
||||
self._allow_server_transition = False
|
||||
self._server_transitioning: Optional[bool] = None
|
||||
self._server_transitioning: bool | None = None
|
||||
|
||||
self._playerinfos: list[ba.PlayerInfo] = settings['playerinfos']
|
||||
assert isinstance(self._playerinfos, list)
|
||||
assert (isinstance(i, ba.PlayerInfo) for i in self._playerinfos)
|
||||
|
||||
self._score: Optional[int] = settings['score']
|
||||
self._score: int | None = settings['score']
|
||||
assert isinstance(self._score, (int, type(None)))
|
||||
|
||||
self._fail_message: Optional[ba.Lstr] = settings['fail_message']
|
||||
self._fail_message: ba.Lstr | None = settings['fail_message']
|
||||
assert isinstance(self._fail_message, (ba.Lstr, type(None)))
|
||||
|
||||
self._begin_time: Optional[float] = None
|
||||
self._begin_time: float | None = None
|
||||
|
||||
self._score_order: str
|
||||
if 'score_order' in settings:
|
||||
|
|
@ -410,7 +410,7 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
texture=self._replay_icon_texture,
|
||||
opacity=0.8)
|
||||
|
||||
next_button: Optional[ba.Widget] = None
|
||||
next_button: ba.Widget | None = None
|
||||
|
||||
# Our 'next' button is disabled if we haven't unlocked the next
|
||||
# level yet and invisible if there is none.
|
||||
|
|
@ -702,7 +702,7 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
str(len(self._playerinfos)) + ' Player', [])
|
||||
|
||||
if self._score is not None:
|
||||
our_score: Optional[list] = [
|
||||
our_score: list | None = [
|
||||
self._score, {
|
||||
'players': [{
|
||||
'name': p.name,
|
||||
|
|
@ -931,7 +931,7 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
'loop': False
|
||||
})).autoretain()
|
||||
|
||||
def _got_friend_score_results(self, results: Optional[list[Any]]) -> None:
|
||||
def _got_friend_score_results(self, results: list[Any] | None) -> None:
|
||||
|
||||
# FIXME: tidy this up
|
||||
# pylint: disable=too-many-locals
|
||||
|
|
@ -1046,7 +1046,7 @@ class CoopScoreScreen(ba.Activity[ba.Player, ba.Team]):
|
|||
transition=Text.Transition.IN_RIGHT,
|
||||
transition_delay=tdelay2).autoretain()
|
||||
|
||||
def _got_score_results(self, results: Optional[dict[str, Any]]) -> None:
|
||||
def _got_score_results(self, results: dict[str, Any] | None) -> None:
|
||||
|
||||
# FIXME: tidy this up
|
||||
# pylint: disable=too-many-locals
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import ba
|
|||
from bastd.activity.multiteamscore import MultiTeamScoreScreenActivity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
||||
|
|
@ -236,7 +236,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
|||
transtime2: ts_h_offs + (xval - slide_amt) * scale
|
||||
}))
|
||||
|
||||
def _safesetattr(node: Optional[ba.Node], attr: str,
|
||||
def _safesetattr(node: ba.Node | None, attr: str,
|
||||
value: Any) -> None:
|
||||
if node:
|
||||
setattr(node, attr, value)
|
||||
|
|
@ -259,7 +259,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
|||
self._score_display_sound_small))
|
||||
v_offs -= spacing
|
||||
|
||||
def _safe_animate(self, node: Optional[ba.Node], attr: str,
|
||||
def _safe_animate(self, node: ba.Node | None, attr: str,
|
||||
keys: dict[float, float]) -> None:
|
||||
"""Run an animation on a node if the node still exists."""
|
||||
if node:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from ba.internal import JoinActivity
|
|||
from bastd.actor.text import Text
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
class MultiTeamJoinActivity(JoinActivity):
|
||||
|
|
@ -19,7 +19,7 @@ class MultiTeamJoinActivity(JoinActivity):
|
|||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._next_up_text: Optional[Text] = None
|
||||
self._next_up_text: Text | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
from bastd.actor.controlsguide import ControlsGuide
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from bastd.actor.text import Text
|
|||
from bastd.actor.image import Image
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Union
|
||||
pass
|
||||
|
||||
|
||||
class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
||||
|
|
@ -52,7 +52,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
|
||||
def show_player_scores(self,
|
||||
delay: float = 2.5,
|
||||
results: Optional[ba.GameResults] = None,
|
||||
results: ba.GameResults | None = None,
|
||||
scale: float = 1.0,
|
||||
x_offset: float = 0.0,
|
||||
y_offset: float = 0.0) -> None:
|
||||
|
|
@ -67,7 +67,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
|
||||
is_free_for_all = isinstance(self.session, ba.FreeForAllSession)
|
||||
|
||||
def _get_prec_score(p_rec: ba.PlayerRecord) -> Optional[int]:
|
||||
def _get_prec_score(p_rec: ba.PlayerRecord) -> int | None:
|
||||
if is_free_for_all and results is not None:
|
||||
assert isinstance(results, ba.GameResults)
|
||||
assert p_rec.team.activityteam is not None
|
||||
|
|
@ -75,7 +75,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
return val
|
||||
return p_rec.accumscore
|
||||
|
||||
def _get_prec_score_str(p_rec: ba.PlayerRecord) -> Union[str, ba.Lstr]:
|
||||
def _get_prec_score_str(p_rec: ba.PlayerRecord) -> str | ba.Lstr:
|
||||
if is_free_for_all and results is not None:
|
||||
assert isinstance(results, ba.GameResults)
|
||||
assert p_rec.team.activityteam is not None
|
||||
|
|
@ -96,7 +96,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def _get_player_score_set_entry(
|
||||
player: ba.SessionPlayer) -> Optional[ba.PlayerRecord]:
|
||||
player: ba.SessionPlayer) -> ba.PlayerRecord | None:
|
||||
for p_rec in valid_players:
|
||||
if p_rec[1].player is player:
|
||||
return p_rec[1]
|
||||
|
|
@ -129,7 +129,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
text: ba.Lstr,
|
||||
h_align: Text.HAlign = Text.HAlign.RIGHT,
|
||||
extrascale: float = 1.0,
|
||||
maxwidth: Optional[float] = 120.0) -> None:
|
||||
maxwidth: float | None = 120.0) -> None:
|
||||
Text(text,
|
||||
color=(0.5, 0.5, 0.6, 0.5),
|
||||
position=(ts_h_offs + xoffs * scale,
|
||||
|
|
@ -169,7 +169,7 @@ class MultiTeamScoreScreenActivity(ScoreScreenActivity):
|
|||
topkillcount = max(topkillcount, prec.accum_kill_count)
|
||||
topkilledcount = min(topkilledcount, prec.accum_killed_count)
|
||||
|
||||
def _scoretxt(text: Union[str, ba.Lstr],
|
||||
def _scoretxt(text: str | ba.Lstr,
|
||||
x_offs: float,
|
||||
highlight: bool,
|
||||
delay2: float,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import ba
|
|||
from bastd.activity.multiteamscore import MultiTeamScoreScreenActivity
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
||||
|
|
@ -146,8 +146,8 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity):
|
|||
else:
|
||||
v_extra = 0
|
||||
|
||||
mvp: Optional[ba.PlayerRecord] = None
|
||||
mvp_name: Optional[str] = None
|
||||
mvp: ba.PlayerRecord | None = None
|
||||
mvp_name: str | None = None
|
||||
|
||||
# Show game MVP.
|
||||
if not self._is_ffa:
|
||||
|
|
|
|||
10
dist/ba_data/python/bastd/actor/bomb.py
vendored
10
dist/ba_data/python/bastd/actor/bomb.py
vendored
|
|
@ -14,7 +14,7 @@ import ba
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Callable
|
||||
from typing import Any, Sequence, Callable
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
PlayerType = TypeVar('PlayerType', bound='ba.Player')
|
||||
|
|
@ -678,7 +678,7 @@ class Bomb(ba.Actor):
|
|||
self._exploded = False
|
||||
self.scale = bomb_scale
|
||||
|
||||
self.texture_sequence: Optional[ba.Node] = None
|
||||
self.texture_sequence: ba.Node | None = None
|
||||
|
||||
if self.bomb_type == 'sticky':
|
||||
self._last_sticky_sound_time = 0.0
|
||||
|
|
@ -846,8 +846,8 @@ class Bomb(ba.Actor):
|
|||
0.26: self.scale
|
||||
})
|
||||
|
||||
def get_source_player(
|
||||
self, playertype: type[PlayerType]) -> Optional[PlayerType]:
|
||||
def get_source_player(self,
|
||||
playertype: type[PlayerType]) -> PlayerType | None:
|
||||
"""Return the source-player if one exists and is the provided type."""
|
||||
player: Any = self._source_player
|
||||
return (player if isinstance(player, playertype) and player.exists()
|
||||
|
|
@ -1071,7 +1071,7 @@ class TNTSpawner:
|
|||
def __init__(self, position: Sequence[float], respawn_time: float = 20.0):
|
||||
"""Instantiate with given position and respawn_time (in seconds)."""
|
||||
self._position = position
|
||||
self._tnt: Optional[Bomb] = None
|
||||
self._tnt: Bomb | None = None
|
||||
self._respawn_time = random.uniform(0.8, 1.2) * respawn_time
|
||||
self._wait_time = 0.0
|
||||
self._update()
|
||||
|
|
|
|||
25
dist/ba_data/python/bastd/actor/controlsguide.py
vendored
25
dist/ba_data/python/bastd/actor/controlsguide.py
vendored
|
|
@ -10,7 +10,7 @@ import _ba
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class ControlsGuide(ba.Actor):
|
||||
|
|
@ -52,13 +52,13 @@ class ControlsGuide(ba.Actor):
|
|||
self._lifespan = lifespan
|
||||
self._dead = False
|
||||
self._bright = bright
|
||||
self._cancel_timer: Optional[ba.Timer] = None
|
||||
self._fade_in_timer: Optional[ba.Timer] = None
|
||||
self._update_timer: Optional[ba.Timer] = None
|
||||
self._title_text: Optional[ba.Node]
|
||||
self._cancel_timer: ba.Timer | None = None
|
||||
self._fade_in_timer: ba.Timer | None = None
|
||||
self._update_timer: ba.Timer | None = None
|
||||
self._title_text: ba.Node | None
|
||||
clr: Sequence[float]
|
||||
extra_pos_1: Optional[tuple[float, float]]
|
||||
extra_pos_2: Optional[tuple[float, float]]
|
||||
extra_pos_1: tuple[float, float] | None
|
||||
extra_pos_2: tuple[float, float] | None
|
||||
if ba.app.iircade_mode:
|
||||
xtweak = 0.2
|
||||
ytweak = 0.2
|
||||
|
|
@ -238,7 +238,7 @@ class ControlsGuide(ba.Actor):
|
|||
})
|
||||
|
||||
if extra_pos_1 is not None:
|
||||
self._extra_image_1: Optional[ba.Node] = ba.newnode(
|
||||
self._extra_image_1: ba.Node | None = ba.newnode(
|
||||
'image',
|
||||
attrs={
|
||||
'texture': ba.gettexture('nub'),
|
||||
|
|
@ -252,7 +252,7 @@ class ControlsGuide(ba.Actor):
|
|||
else:
|
||||
self._extra_image_1 = None
|
||||
if extra_pos_2 is not None:
|
||||
self._extra_image_2: Optional[ba.Node] = ba.newnode(
|
||||
self._extra_image_2: ba.Node | None = ba.newnode(
|
||||
'image',
|
||||
attrs={
|
||||
'texture': ba.gettexture('nub'),
|
||||
|
|
@ -317,8 +317,9 @@ class ControlsGuide(ba.Actor):
|
|||
# an input device that is *not* the touchscreen.
|
||||
# (otherwise it is confusing to see the touchscreen buttons right
|
||||
# next to our display buttons)
|
||||
touchscreen: Optional[ba.InputDevice] = _ba.getinputdevice(
|
||||
'TouchScreen', '#1', doraise=False)
|
||||
touchscreen: ba.InputDevice | None = _ba.getinputdevice('TouchScreen',
|
||||
'#1',
|
||||
doraise=False)
|
||||
|
||||
if touchscreen is not None:
|
||||
# We look at the session's players; not the activity's.
|
||||
|
|
@ -477,7 +478,7 @@ class ControlsGuide(ba.Actor):
|
|||
pickup_button_names.clear()
|
||||
|
||||
self._run_text.text = run_text
|
||||
w_text: Union[ba.Lstr, str]
|
||||
w_text: ba.Lstr | str
|
||||
if only_remote and self._lifespan is None:
|
||||
w_text = ba.Lstr(resource='fireTVRemoteWarningText',
|
||||
subs=[('${REMOTE_APP_NAME}',
|
||||
|
|
|
|||
10
dist/ba_data/python/bastd/actor/flag.py
vendored
10
dist/ba_data/python/bastd/actor/flag.py
vendored
|
|
@ -11,7 +11,7 @@ import ba
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class FlagFactory:
|
||||
|
|
@ -185,7 +185,7 @@ class Flag(ba.Actor):
|
|||
|
||||
super().__init__()
|
||||
|
||||
self._initial_position: Optional[Sequence[float]] = None
|
||||
self._initial_position: Sequence[float] | None = None
|
||||
self._has_moved = False
|
||||
shared = SharedObjects.get()
|
||||
factory = FlagFactory.get()
|
||||
|
|
@ -214,7 +214,7 @@ class Flag(ba.Actor):
|
|||
if dropped_timeout is not None:
|
||||
dropped_timeout = int(dropped_timeout)
|
||||
self._dropped_timeout = dropped_timeout
|
||||
self._counter: Optional[ba.Node]
|
||||
self._counter: ba.Node | None
|
||||
if self._dropped_timeout is not None:
|
||||
self._count = self._dropped_timeout
|
||||
self._tick_timer = ba.Timer(1.0,
|
||||
|
|
@ -234,8 +234,8 @@ class Flag(ba.Actor):
|
|||
self._counter = None
|
||||
|
||||
self._held_count = 0
|
||||
self._score_text: Optional[ba.Node] = None
|
||||
self._score_text_hide_timer: Optional[ba.Timer] = None
|
||||
self._score_text: ba.Node | None = None
|
||||
self._score_text_hide_timer: ba.Timer | None = None
|
||||
|
||||
def _tick(self) -> None:
|
||||
if self.node:
|
||||
|
|
|
|||
8
dist/ba_data/python/bastd/actor/image.py
vendored
8
dist/ba_data/python/bastd/actor/image.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Union, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Image(ba.Actor):
|
||||
|
|
@ -33,9 +33,9 @@ class Image(ba.Actor):
|
|||
BOTTOM_CENTER = 'bottomCenter'
|
||||
|
||||
def __init__(self,
|
||||
texture: Union[ba.Texture, dict[str, Any]],
|
||||
texture: ba.Texture | dict[str, Any],
|
||||
position: tuple[float, float] = (0, 0),
|
||||
transition: Optional[Transition] = None,
|
||||
transition: Transition | None = None,
|
||||
transition_delay: float = 0.0,
|
||||
attach: Attach = Attach.CENTER,
|
||||
color: Sequence[float] = (1.0, 1.0, 1.0, 1.0),
|
||||
|
|
@ -53,7 +53,7 @@ class Image(ba.Actor):
|
|||
|
||||
# If they provided a dict as texture, assume its an icon.
|
||||
# otherwise its just a texture value itself.
|
||||
mask_texture: Optional[ba.Texture]
|
||||
mask_texture: ba.Texture | None
|
||||
if isinstance(texture, dict):
|
||||
tint_color = texture['tint_color']
|
||||
tint2_color = texture['tint2_color']
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
|
||||
|
||||
class OnScreenCountdown(ba.Actor):
|
||||
|
|
@ -57,7 +57,7 @@ class OnScreenCountdown(ba.Actor):
|
|||
2: ba.getsound('announceTwo'),
|
||||
1: ba.getsound('announceOne')
|
||||
}
|
||||
self._timer: Optional[ba.Timer] = None
|
||||
self._timer: ba.Timer | None = None
|
||||
|
||||
def start(self) -> None:
|
||||
"""Start the timer."""
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, overload
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Union, Any, Literal
|
||||
from typing import Any, Literal
|
||||
|
||||
|
||||
class OnScreenTimer(ba.Actor):
|
||||
|
|
@ -21,7 +21,7 @@ class OnScreenTimer(ba.Actor):
|
|||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._starttime_ms: Optional[int] = None
|
||||
self._starttime_ms: int | None = None
|
||||
self.node = ba.newnode('text',
|
||||
attrs={
|
||||
'v_attach': 'top',
|
||||
|
|
@ -55,7 +55,7 @@ class OnScreenTimer(ba.Actor):
|
|||
return self._starttime_ms is not None
|
||||
|
||||
def stop(self,
|
||||
endtime: Union[int, float] = None,
|
||||
endtime: int | float | None = None,
|
||||
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> None:
|
||||
"""End the timer.
|
||||
|
||||
|
|
@ -97,8 +97,7 @@ class OnScreenTimer(ba.Actor):
|
|||
|
||||
def getstarttime(
|
||||
self,
|
||||
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
|
||||
) -> Union[int, float]:
|
||||
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS) -> int | float:
|
||||
"""Return the sim-time when start() was called.
|
||||
|
||||
Time will be returned in seconds if timeformat is SECONDS or
|
||||
|
|
|
|||
13
dist/ba_data/python/bastd/actor/playerspaz.py
vendored
13
dist/ba_data/python/bastd/actor/playerspaz.py
vendored
|
|
@ -10,7 +10,7 @@ import ba
|
|||
from bastd.actor.spaz import Spaz
|
||||
from spazmod import modifyspaz
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Literal
|
||||
from typing import Any, Sequence, Literal
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
PlayerType = TypeVar('PlayerType', bound=ba.Player)
|
||||
|
|
@ -64,14 +64,13 @@ class PlayerSpaz(Spaz):
|
|||
source_player=player,
|
||||
start_invincible=True,
|
||||
powerups_expire=powerups_expire)
|
||||
self.last_player_attacked_by: Optional[ba.Player] = None
|
||||
self.last_player_attacked_by: ba.Player | None = None
|
||||
self.last_attacked_time = 0.0
|
||||
self.last_attacked_type: Optional[tuple[str, str]] = None
|
||||
self.last_attacked_type: tuple[str, str] | None = None
|
||||
self.held_count = 0
|
||||
self.last_player_held_by: Optional[ba.Player] = None
|
||||
self.last_player_held_by: ba.Player | None = None
|
||||
self._player = player
|
||||
self._drive_player_position()
|
||||
|
||||
import custom_hooks
|
||||
custom_hooks.playerspaz_init(self, self.node, self._player)
|
||||
|
||||
|
|
@ -80,7 +79,7 @@ class PlayerSpaz(Spaz):
|
|||
@overload
|
||||
def getplayer(self,
|
||||
playertype: type[PlayerType],
|
||||
doraise: Literal[False] = False) -> Optional[PlayerType]:
|
||||
doraise: Literal[False] = False) -> PlayerType | None:
|
||||
...
|
||||
|
||||
@overload
|
||||
|
|
@ -90,7 +89,7 @@ class PlayerSpaz(Spaz):
|
|||
|
||||
def getplayer(self,
|
||||
playertype: type[PlayerType],
|
||||
doraise: bool = False) -> Optional[PlayerType]:
|
||||
doraise: bool = False) -> PlayerType | None:
|
||||
"""Get the ba.Player associated with this Spaz.
|
||||
|
||||
By default this will return None if the Player no longer exists.
|
||||
|
|
|
|||
4
dist/ba_data/python/bastd/actor/popuptext.py
vendored
4
dist/ba_data/python/bastd/actor/popuptext.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class PopupText(ba.Actor):
|
||||
|
|
@ -20,7 +20,7 @@ class PopupText(ba.Actor):
|
|||
"""
|
||||
|
||||
def __init__(self,
|
||||
text: Union[str, ba.Lstr],
|
||||
text: str | ba.Lstr,
|
||||
position: Sequence[float] = (0.0, 0.0, 0.0),
|
||||
color: Sequence[float] = (1.0, 1.0, 1.0, 1.0),
|
||||
random_offset: float = 0.5,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import ba
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence
|
||||
from typing import Any, Sequence
|
||||
|
||||
DEFAULT_POWERUP_INTERVAL = 8.0
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ class PowerupBoxFactory:
|
|||
"""
|
||||
from ba.internal import get_default_powerup_distribution
|
||||
shared = SharedObjects.get()
|
||||
self._lastpoweruptype: Optional[str] = None
|
||||
self._lastpoweruptype: str | None = None
|
||||
self.model = ba.getmodel('powerup')
|
||||
self.model_simple = ba.getmodel('powerupSimple')
|
||||
self.tex_bomb = ba.gettexture('powerupBomb')
|
||||
|
|
|
|||
10
dist/ba_data/python/bastd/actor/respawnicon.py
vendored
10
dist/ba_data/python/bastd/actor/respawnicon.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
class RespawnIcon:
|
||||
|
|
@ -49,7 +49,7 @@ class RespawnIcon:
|
|||
texture = icon['texture']
|
||||
h_offs = -10
|
||||
ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs)
|
||||
self._image: Optional[ba.NodeActor] = ba.NodeActor(
|
||||
self._image: ba.NodeActor | None = ba.NodeActor(
|
||||
ba.newnode('image',
|
||||
attrs={
|
||||
'texture': texture,
|
||||
|
|
@ -68,7 +68,7 @@ class RespawnIcon:
|
|||
ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7})
|
||||
|
||||
npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs)
|
||||
self._name: Optional[ba.NodeActor] = ba.NodeActor(
|
||||
self._name: ba.NodeActor | None = ba.NodeActor(
|
||||
ba.newnode('text',
|
||||
attrs={
|
||||
'v_attach': 'top',
|
||||
|
|
@ -88,7 +88,7 @@ class RespawnIcon:
|
|||
ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5})
|
||||
|
||||
tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs)
|
||||
self._text: Optional[ba.NodeActor] = ba.NodeActor(
|
||||
self._text: ba.NodeActor | None = ba.NodeActor(
|
||||
ba.newnode('text',
|
||||
attrs={
|
||||
'position': tpos,
|
||||
|
|
@ -107,7 +107,7 @@ class RespawnIcon:
|
|||
|
||||
self._respawn_time = ba.time() + respawn_time
|
||||
self._update()
|
||||
self._timer: Optional[ba.Timer] = ba.Timer(1.0,
|
||||
self._timer: ba.Timer | None = ba.Timer(1.0,
|
||||
ba.WeakCall(self._update),
|
||||
repeat=True)
|
||||
|
||||
|
|
|
|||
18
dist/ba_data/python/bastd/actor/scoreboard.py
vendored
18
dist/ba_data/python/bastd/actor/scoreboard.py
vendored
|
|
@ -10,13 +10,13 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class _Entry:
|
||||
|
||||
def __init__(self, scoreboard: Scoreboard, team: ba.Team, do_cover: bool,
|
||||
scale: float, label: Optional[ba.Lstr], flash_length: float):
|
||||
scale: float, label: ba.Lstr | None, flash_length: float):
|
||||
# pylint: disable=too-many-statements
|
||||
self._scoreboard = weakref.ref(scoreboard)
|
||||
self._do_cover = do_cover
|
||||
|
|
@ -29,11 +29,11 @@ class _Entry:
|
|||
self._bar_tex = self._backing_tex = ba.gettexture('bar')
|
||||
self._cover_tex = ba.gettexture('uiAtlas')
|
||||
self._model = ba.getmodel('meterTransparent')
|
||||
self._pos: Optional[Sequence[float]] = None
|
||||
self._flash_timer: Optional[ba.Timer] = None
|
||||
self._flash_counter: Optional[int] = None
|
||||
self._flash_colors: Optional[bool] = None
|
||||
self._score: Optional[float] = None
|
||||
self._pos: Sequence[float] | None = None
|
||||
self._flash_timer: ba.Timer | None = None
|
||||
self._flash_counter: int | None = None
|
||||
self._flash_colors: bool | None = None
|
||||
self._score: float | None = None
|
||||
|
||||
safe_team_color = ba.safecolor(team.color, target_intensity=1.0)
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ class _Entry:
|
|||
|
||||
clr = safe_team_color
|
||||
|
||||
team_name_label: Union[str, ba.Lstr]
|
||||
team_name_label: str | ba.Lstr
|
||||
if label is not None:
|
||||
team_name_label = label
|
||||
else:
|
||||
|
|
@ -207,7 +207,7 @@ class _Entry:
|
|||
def _set_flash_colors(self, flash: bool) -> None:
|
||||
self._flash_colors = flash
|
||||
|
||||
def _safesetcolor(node: Optional[ba.Node], val: Any) -> None:
|
||||
def _safesetcolor(node: ba.Node | None, val: Any) -> None:
|
||||
if node:
|
||||
node.color = val
|
||||
|
||||
|
|
|
|||
40
dist/ba_data/python/bastd/actor/spaz.py
vendored
40
dist/ba_data/python/bastd/actor/spaz.py
vendored
|
|
@ -15,7 +15,7 @@ from bastd.actor.spazfactory import SpazFactory
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union, Callable
|
||||
from typing import Any, Sequence, Callable
|
||||
|
||||
POWERUP_WEAR_OFF_TIME = 20000
|
||||
BASE_PUNCH_COOLDOWN = 400
|
||||
|
|
@ -57,7 +57,7 @@ class Spaz(ba.Actor):
|
|||
"""The 'spaz' ba.Node."""
|
||||
|
||||
points_mult = 1
|
||||
curse_time: Optional[float] = 5.0
|
||||
curse_time: float | None = 5.0
|
||||
default_bomb_count = 1
|
||||
default_bomb_type = 'normal'
|
||||
default_boxing_gloves = False
|
||||
|
|
@ -102,7 +102,7 @@ class Spaz(ba.Actor):
|
|||
self._hockey = False
|
||||
self._punched_nodes: set[ba.Node] = set()
|
||||
self._cursed = False
|
||||
self._connected_to_player: Optional[ba.Player] = None
|
||||
self._connected_to_player: ba.Player | None = None
|
||||
materials = [
|
||||
factory.spaz_material, shared.object_material,
|
||||
shared.player_material
|
||||
|
|
@ -155,11 +155,11 @@ class Spaz(ba.Actor):
|
|||
'invincible': start_invincible,
|
||||
'source_player': source_player
|
||||
})
|
||||
self.shield: Optional[ba.Node] = None
|
||||
self.shield: ba.Node | None = None
|
||||
|
||||
if start_invincible:
|
||||
|
||||
def _safesetattr(node: Optional[ba.Node], attr: str,
|
||||
def _safesetattr(node: ba.Node | None, attr: str,
|
||||
val: Any) -> None:
|
||||
if node:
|
||||
setattr(node, attr, val)
|
||||
|
|
@ -168,15 +168,15 @@ class Spaz(ba.Actor):
|
|||
False))
|
||||
self.hitpoints = 1000
|
||||
self.hitpoints_max = 1000
|
||||
self.shield_hitpoints: Optional[int] = None
|
||||
self.shield_hitpoints: int | None = None
|
||||
self.shield_hitpoints_max = 650
|
||||
self.shield_decay_rate = 0
|
||||
self.shield_decay_timer: Optional[ba.Timer] = None
|
||||
self._boxing_gloves_wear_off_timer: Optional[ba.Timer] = None
|
||||
self._boxing_gloves_wear_off_flash_timer: Optional[ba.Timer] = None
|
||||
self._bomb_wear_off_timer: Optional[ba.Timer] = None
|
||||
self._bomb_wear_off_flash_timer: Optional[ba.Timer] = None
|
||||
self._multi_bomb_wear_off_timer: Optional[ba.Timer] = None
|
||||
self.shield_decay_timer: ba.Timer | None = None
|
||||
self._boxing_gloves_wear_off_timer: ba.Timer | None = None
|
||||
self._boxing_gloves_wear_off_flash_timer: ba.Timer | None = None
|
||||
self._bomb_wear_off_timer: ba.Timer | None = None
|
||||
self._bomb_wear_off_flash_timer: ba.Timer | None = None
|
||||
self._multi_bomb_wear_off_timer: ba.Timer | None = None
|
||||
self.bomb_count = self.default_bomb_count
|
||||
self._max_bomb_count = self.default_bomb_count
|
||||
self.bomb_type_default = self.default_bomb_type
|
||||
|
|
@ -205,7 +205,7 @@ class Spaz(ba.Actor):
|
|||
self._turbo_filter_counts: dict[str, int] = {}
|
||||
self.frozen = False
|
||||
self.shattered = False
|
||||
self._last_hit_time: Optional[int] = None
|
||||
self._last_hit_time: int | None = None
|
||||
self._num_times_hit = 0
|
||||
self._bomb_held = False
|
||||
if self.default_shields:
|
||||
|
|
@ -213,13 +213,13 @@ class Spaz(ba.Actor):
|
|||
self._dropped_bomb_callbacks: list[Callable[[Spaz, ba.Actor],
|
||||
Any]] = []
|
||||
|
||||
self._score_text: Optional[ba.Node] = None
|
||||
self._score_text_hide_timer: Optional[ba.Timer] = None
|
||||
self._last_stand_pos: Optional[Sequence[float]] = None
|
||||
self._score_text: ba.Node | None = None
|
||||
self._score_text_hide_timer: ba.Timer | None = None
|
||||
self._last_stand_pos: Sequence[float] | None = None
|
||||
|
||||
# Deprecated stuff.. should make these into lists.
|
||||
self.punch_callback: Optional[Callable[[Spaz], Any]] = None
|
||||
self.pick_up_powerup_callback: Optional[Callable[[Spaz], Any]] = None
|
||||
self.punch_callback: Callable[[Spaz], Any] | None = None
|
||||
self.pick_up_powerup_callback: Callable[[Spaz], Any] | None = None
|
||||
|
||||
def exists(self) -> bool:
|
||||
return bool(self.node)
|
||||
|
|
@ -297,7 +297,7 @@ class Spaz(ba.Actor):
|
|||
self._turbo_filter_counts = {source: 1}
|
||||
|
||||
def set_score_text(self,
|
||||
text: Union[str, ba.Lstr],
|
||||
text: str | ba.Lstr,
|
||||
color: Sequence[float] = (1.0, 1.0, 0.4),
|
||||
flash: bool = False) -> None:
|
||||
"""
|
||||
|
|
@ -1208,7 +1208,7 @@ class Spaz(ba.Actor):
|
|||
return super().handlemessage(msg)
|
||||
return None
|
||||
|
||||
def drop_bomb(self) -> Optional[stdbomb.Bomb]:
|
||||
def drop_bomb(self) -> stdbomb.Bomb | None:
|
||||
"""
|
||||
Tell the spaz to drop one of his bombs, and returns
|
||||
the resulting bomb object.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import _ba
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
def get_appearances(include_locked: bool = False) -> list[str]:
|
||||
|
|
@ -111,8 +111,8 @@ class Appearance:
|
|||
self.pickup_sounds: list[str] = []
|
||||
self.fall_sounds: list[str] = []
|
||||
self.style = 'spaz'
|
||||
self.default_color: Optional[tuple[float, float, float]] = None
|
||||
self.default_highlight: Optional[tuple[float, float, float]] = None
|
||||
self.default_color: tuple[float, float, float] | None = None
|
||||
self.default_highlight: tuple[float, float, float] | None = None
|
||||
|
||||
|
||||
def register_appearances() -> None:
|
||||
|
|
|
|||
43
dist/ba_data/python/bastd/actor/spazbot.py
vendored
43
dist/ba_data/python/bastd/actor/spazbot.py
vendored
|
|
@ -13,7 +13,7 @@ import ba
|
|||
from bastd.actor.spaz import Spaz
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Callable
|
||||
from typing import Any, Sequence, Callable
|
||||
from bastd.actor.flag import Flag
|
||||
|
||||
LITE_BOT_COLOR = (1.2, 0.9, 0.2)
|
||||
|
|
@ -51,13 +51,13 @@ class SpazBotDiedMessage:
|
|||
spazbot: SpazBot
|
||||
"""The SpazBot that was killed."""
|
||||
|
||||
killerplayer: Optional[ba.Player]
|
||||
killerplayer: ba.Player | None
|
||||
"""The ba.Player that killed it (or None)."""
|
||||
|
||||
how: ba.DeathType
|
||||
"""The particular type of death."""
|
||||
|
||||
def __init__(self, spazbot: SpazBot, killerplayer: Optional[ba.Player],
|
||||
def __init__(self, spazbot: SpazBot, killerplayer: ba.Player | None,
|
||||
how: ba.DeathType):
|
||||
"""Instantiate with given values."""
|
||||
self.spazbot = spazbot
|
||||
|
|
@ -115,17 +115,17 @@ class SpazBot(Spaz):
|
|||
# If you need to add custom behavior to a bot, set this to a callable
|
||||
# which takes one arg (the bot) and returns False if the bot's normal
|
||||
# update should be run and True if not.
|
||||
self.update_callback: Optional[Callable[[SpazBot], Any]] = None
|
||||
self.update_callback: Callable[[SpazBot], Any] | None = None
|
||||
activity = self.activity
|
||||
assert isinstance(activity, ba.GameActivity)
|
||||
self._map = weakref.ref(activity.map)
|
||||
self.last_player_attacked_by: Optional[ba.Player] = None
|
||||
self.last_player_attacked_by: ba.Player | None = None
|
||||
self.last_attacked_time = 0.0
|
||||
self.last_attacked_type: Optional[tuple[str, str]] = None
|
||||
self.target_point_default: Optional[ba.Vec3] = None
|
||||
self.last_attacked_type: tuple[str, str] | None = None
|
||||
self.target_point_default: ba.Vec3 | None = None
|
||||
self.held_count = 0
|
||||
self.last_player_held_by: Optional[ba.Player] = None
|
||||
self.target_flag: Optional[Flag] = None
|
||||
self.last_player_held_by: ba.Player | None = None
|
||||
self.target_flag: Flag | None = None
|
||||
self._charge_speed = 0.5 * (self.charge_speed_min +
|
||||
self.charge_speed_max)
|
||||
self._lead_amount = 0.5
|
||||
|
|
@ -135,9 +135,9 @@ class SpazBot(Spaz):
|
|||
self._running = False
|
||||
self._last_jump_time = 0.0
|
||||
|
||||
self._throw_release_time: Optional[float] = None
|
||||
self._have_dropped_throw_bomb: Optional[bool] = None
|
||||
self._player_pts: Optional[list[tuple[ba.Vec3, ba.Vec3]]] = None
|
||||
self._throw_release_time: float | None = None
|
||||
self._have_dropped_throw_bomb: bool | None = None
|
||||
self._player_pts: list[tuple[ba.Vec3, ba.Vec3]] | None = None
|
||||
|
||||
# These cooldowns didn't exist when these bots were calibrated,
|
||||
# so take them out of the equation.
|
||||
|
|
@ -156,17 +156,16 @@ class SpazBot(Spaz):
|
|||
assert mval is not None
|
||||
return mval
|
||||
|
||||
def _get_target_player_pt(
|
||||
self) -> tuple[Optional[ba.Vec3], Optional[ba.Vec3]]:
|
||||
def _get_target_player_pt(self) -> tuple[ba.Vec3 | None, ba.Vec3 | None]:
|
||||
"""Returns the position and velocity of our target.
|
||||
|
||||
Both values will be None in the case of no target.
|
||||
"""
|
||||
assert self.node
|
||||
botpt = ba.Vec3(self.node.position)
|
||||
closest_dist: Optional[float] = None
|
||||
closest_vel: Optional[ba.Vec3] = None
|
||||
closest: Optional[ba.Vec3] = None
|
||||
closest_dist: float | None = None
|
||||
closest_vel: ba.Vec3 | None = None
|
||||
closest: ba.Vec3 | None = None
|
||||
assert self._player_pts is not None
|
||||
for plpt, plvel in self._player_pts:
|
||||
dist = (plpt - botpt).length()
|
||||
|
|
@ -206,8 +205,8 @@ class SpazBot(Spaz):
|
|||
our_pos = ba.Vec3(pos[0], 0, pos[2])
|
||||
can_attack = True
|
||||
|
||||
target_pt_raw: Optional[ba.Vec3]
|
||||
target_vel: Optional[ba.Vec3]
|
||||
target_pt_raw: ba.Vec3 | None
|
||||
target_vel: ba.Vec3 | None
|
||||
|
||||
# If we're a flag-bearer, we're pretty simple-minded - just walk
|
||||
# towards the flag and try to pick it up.
|
||||
|
|
@ -517,7 +516,7 @@ class SpazBot(Spaz):
|
|||
# Report normal deaths for scoring purposes.
|
||||
if not self._dead and not msg.immediate:
|
||||
|
||||
killerplayer: Optional[ba.Player]
|
||||
killerplayer: ba.Player | None
|
||||
|
||||
# If this guy was being held at the time of death, the
|
||||
# holder is the killer.
|
||||
|
|
@ -883,7 +882,7 @@ class SpazBotSet:
|
|||
]
|
||||
self._spawn_sound = ba.getsound('spawn')
|
||||
self._spawning_count = 0
|
||||
self._bot_update_timer: Optional[ba.Timer] = None
|
||||
self._bot_update_timer: ba.Timer | None = None
|
||||
self.start_moving()
|
||||
|
||||
def __del__(self) -> None:
|
||||
|
|
@ -904,7 +903,7 @@ class SpazBotSet:
|
|||
self._spawning_count += 1
|
||||
|
||||
def _spawn_bot(self, bot_type: type[SpazBot], pos: Sequence[float],
|
||||
on_spawn_call: Optional[Callable[[SpazBot], Any]]) -> None:
|
||||
on_spawn_call: Callable[[SpazBot], Any] | None) -> None:
|
||||
spaz = bot_type()
|
||||
ba.playsound(self._spawn_sound, position=pos)
|
||||
assert spaz.node
|
||||
|
|
|
|||
6
dist/ba_data/python/bastd/actor/text.py
vendored
6
dist/ba_data/python/bastd/actor/text.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Text(ba.Actor):
|
||||
|
|
@ -49,12 +49,12 @@ class Text(ba.Actor):
|
|||
TOP = 'top'
|
||||
|
||||
def __init__(self,
|
||||
text: Union[str, ba.Lstr],
|
||||
text: str | ba.Lstr,
|
||||
position: tuple[float, float] = (0.0, 0.0),
|
||||
h_align: HAlign = HAlign.LEFT,
|
||||
v_align: VAlign = VAlign.NONE,
|
||||
color: Sequence[float] = (1.0, 1.0, 1.0, 1.0),
|
||||
transition: Optional[Transition] = None,
|
||||
transition: Transition | None = None,
|
||||
transition_delay: float = 0.0,
|
||||
flash: bool = False,
|
||||
v_attach: VAttach = VAttach.CENTER,
|
||||
|
|
|
|||
4
dist/ba_data/python/bastd/actor/zoomtext.py
vendored
4
dist/ba_data/python/bastd/actor/zoomtext.py
vendored
|
|
@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class ZoomText(ba.Actor):
|
||||
|
|
@ -22,7 +22,7 @@ class ZoomText(ba.Actor):
|
|||
"""
|
||||
|
||||
def __init__(self,
|
||||
text: Union[str, ba.Lstr],
|
||||
text: str | ba.Lstr,
|
||||
position: tuple[float, float] = (0.0, 0.0),
|
||||
shiftposition: tuple[float, float] = None,
|
||||
shiftdelay: float = None,
|
||||
|
|
|
|||
6
dist/ba_data/python/bastd/appdelegate.py
vendored
6
dist/ba_data/python/bastd/appdelegate.py
vendored
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Callable, Optional
|
||||
from typing import Any, Callable
|
||||
|
||||
|
||||
class AppDelegate(ba.AppDelegate):
|
||||
|
|
@ -16,8 +16,8 @@ class AppDelegate(ba.AppDelegate):
|
|||
|
||||
def create_default_game_settings_ui(
|
||||
self, gameclass: type[ba.GameActivity],
|
||||
sessiontype: type[ba.Session], settings: Optional[dict],
|
||||
completion_call: Callable[[Optional[dict]], Any]) -> None:
|
||||
sessiontype: type[ba.Session], settings: dict | None,
|
||||
completion_call: Callable[[dict | None], Any]) -> None:
|
||||
"""(internal)"""
|
||||
|
||||
# Replace the main window once we come up successfully.
|
||||
|
|
|
|||
8
dist/ba_data/python/bastd/game/assault.py
vendored
8
dist/ba_data/python/bastd/game/assault.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines assault minigame."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -17,7 +17,7 @@ from bastd.actor.scoreboard import Scoreboard
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
|
|
@ -94,12 +94,12 @@ class AssaultGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.FORWARD_MARCH)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'Touch the enemy flag.'
|
||||
return 'Touch the enemy flag ${ARG1} times.', self._score_to_win
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'touch 1 flag'
|
||||
return 'touch ${ARG1} flags', self._score_to_win
|
||||
|
|
|
|||
24
dist/ba_data/python/bastd/game/capturetheflag.py
vendored
24
dist/ba_data/python/bastd/game/capturetheflag.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines a capture-the-flag game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -16,7 +16,7 @@ from bastd.actor.flag import (FlagFactory, Flag, FlagPickedUpMessage,
|
|||
FlagDroppedMessage, FlagDiedMessage)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Union, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class CTFFlag(Flag):
|
||||
|
|
@ -39,9 +39,9 @@ class CTFFlag(Flag):
|
|||
'h_align': 'center'
|
||||
})
|
||||
self.reset_return_times()
|
||||
self.last_player_to_hold: Optional[Player] = None
|
||||
self.time_out_respawn_time: Optional[int] = None
|
||||
self.touch_return_time: Optional[float] = None
|
||||
self.last_player_to_hold: Player | None = None
|
||||
self.time_out_respawn_time: int | None = None
|
||||
self.touch_return_time: float | None = None
|
||||
|
||||
def reset_return_times(self) -> None:
|
||||
"""Clear flag related times in the activity."""
|
||||
|
|
@ -78,11 +78,11 @@ class Team(ba.Team[Player]):
|
|||
self.score = 0
|
||||
self.flag_return_touches = 0
|
||||
self.home_flag_at_base = True
|
||||
self.touch_return_timer: Optional[ba.Timer] = None
|
||||
self.touch_return_timer: ba.Timer | None = None
|
||||
self.enemy_flag_at_base = False
|
||||
self.flag: Optional[CTFFlag] = None
|
||||
self.last_flag_leave_time: Optional[float] = None
|
||||
self.touch_return_timer_ticking: Optional[ba.NodeActor] = None
|
||||
self.flag: CTFFlag | None = None
|
||||
self.last_flag_leave_time: float | None = None
|
||||
self.touch_return_timer_ticking: ba.NodeActor | None = None
|
||||
|
||||
|
||||
# ba_meta export game
|
||||
|
|
@ -161,12 +161,12 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.FLAG_CATCHER)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'Steal the enemy flag.'
|
||||
return 'Steal the enemy flag ${ARG1} times.', self._score_to_win
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'return 1 flag'
|
||||
return 'return ${ARG1} flags', self._score_to_win
|
||||
|
|
@ -438,7 +438,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity[Player, Team]):
|
|||
We keep track of when each player is touching their own flag so we
|
||||
can award points when returned.
|
||||
"""
|
||||
player: Optional[Player]
|
||||
player: Player | None
|
||||
try:
|
||||
spaz = ba.getcollision().sourcenode.getdelegate(PlayerSpaz, True)
|
||||
except ba.NotFoundError:
|
||||
|
|
|
|||
22
dist/ba_data/python/bastd/game/chosenone.py
vendored
22
dist/ba_data/python/bastd/game/chosenone.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Provides the chosen-one mini-game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -16,14 +16,14 @@ from bastd.actor.scoreboard import Scoreboard
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.chosen_light: Optional[ba.NodeActor] = None
|
||||
self.chosen_light: ba.NodeActor | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
|
|
@ -87,7 +87,7 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]):
|
|||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._chosen_one_player: Optional[Player] = None
|
||||
self._chosen_one_player: Player | None = None
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._countdownsounds: dict[int, ba.Sound] = {
|
||||
10: ba.getsound('announceTen'),
|
||||
|
|
@ -101,10 +101,10 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]):
|
|||
2: ba.getsound('announceTwo'),
|
||||
1: ba.getsound('announceOne')
|
||||
}
|
||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._reset_region_material: Optional[ba.Material] = None
|
||||
self._flag: Optional[Flag] = None
|
||||
self._reset_region: Optional[ba.Node] = None
|
||||
self._flag_spawn_pos: Sequence[float] | None = None
|
||||
self._reset_region_material: ba.Material | None = None
|
||||
self._flag: Flag | None = None
|
||||
self._reset_region: ba.Node | None = None
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._chosen_one_time = int(settings['Chosen One Time'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
|
@ -116,7 +116,7 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC
|
||||
if self._epic_mode else ba.MusicType.CHOSEN_ONE)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'There can be only one.'
|
||||
|
||||
def create_team(self, sessionteam: ba.SessionTeam) -> Team:
|
||||
|
|
@ -165,7 +165,7 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]):
|
|||
'materials': [mat]
|
||||
})
|
||||
|
||||
def _get_chosen_one_player(self) -> Optional[Player]:
|
||||
def _get_chosen_one_player(self) -> Player | None:
|
||||
# Should never return invalid references; return None in that case.
|
||||
if self._chosen_one_player:
|
||||
return self._chosen_one_player
|
||||
|
|
@ -251,7 +251,7 @@ class ChosenOneGame(ba.TeamGameActivity[Player, Team]):
|
|||
self._chosen_one_time - team.time_remaining)
|
||||
self.end(results=results, announce_delay=0)
|
||||
|
||||
def _set_chosen_one_player(self, player: Optional[Player]) -> None:
|
||||
def _set_chosen_one_player(self, player: Player | None) -> None:
|
||||
existing = self._get_chosen_one_player()
|
||||
if existing:
|
||||
existing.chosen_light = None
|
||||
|
|
|
|||
22
dist/ba_data/python/bastd/game/conquest.py
vendored
22
dist/ba_data/python/bastd/game/conquest.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Provides the Conquest game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -17,7 +17,7 @@ from bastd.actor.playerspaz import PlayerSpaz
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.respawnicon import RespawnIcon
|
||||
|
||||
|
||||
|
|
@ -26,11 +26,11 @@ class ConquestFlag(Flag):
|
|||
|
||||
def __init__(self, *args: Any, **keywds: Any):
|
||||
super().__init__(*args, **keywds)
|
||||
self._team: Optional[Team] = None
|
||||
self.light: Optional[ba.Node] = None
|
||||
self._team: Team | None = None
|
||||
self.light: ba.Node | None = None
|
||||
|
||||
@property
|
||||
def team(self) -> Optional[Team]:
|
||||
def team(self) -> Team | None:
|
||||
"""The team that owns this flag."""
|
||||
return self._team
|
||||
|
||||
|
|
@ -46,21 +46,21 @@ class Player(ba.Player['Team']):
|
|||
# FIXME: We shouldn't be using customdata here
|
||||
# (but need to update respawn funcs accordingly first).
|
||||
@property
|
||||
def respawn_timer(self) -> Optional[ba.Timer]:
|
||||
def respawn_timer(self) -> ba.Timer | None:
|
||||
"""Type safe access to standard respawn timer."""
|
||||
return self.customdata.get('respawn_timer', None)
|
||||
|
||||
@respawn_timer.setter
|
||||
def respawn_timer(self, value: Optional[ba.Timer]) -> None:
|
||||
def respawn_timer(self, value: ba.Timer | None) -> None:
|
||||
self.customdata['respawn_timer'] = value
|
||||
|
||||
@property
|
||||
def respawn_icon(self) -> Optional[RespawnIcon]:
|
||||
def respawn_icon(self) -> RespawnIcon | None:
|
||||
"""Type safe access to standard respawn icon."""
|
||||
return self.customdata.get('respawn_icon', None)
|
||||
|
||||
@respawn_icon.setter
|
||||
def respawn_icon(self, value: Optional[RespawnIcon]) -> None:
|
||||
def respawn_icon(self, value: RespawnIcon | None) -> None:
|
||||
self.customdata['respawn_icon'] = value
|
||||
|
||||
|
||||
|
|
@ -136,10 +136,10 @@ class ConquestGame(ba.TeamGameActivity[Player, Team]):
|
|||
('call', 'at_connect', self._handle_flag_player_collide),
|
||||
))
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'Secure all ${ARG1} flags.', len(self.map.flag_points)
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
return 'secure all ${ARG1} flags', len(self.map.flag_points)
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
|
|
|
|||
10
dist/ba_data/python/bastd/game/deathmatch.py
vendored
10
dist/ba_data/python/bastd/game/deathmatch.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""DeathMatch game and support classes."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -14,7 +14,7 @@ from bastd.actor.playerspaz import PlayerSpaz
|
|||
from bastd.actor.scoreboard import Scoreboard
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Union, Sequence, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
|
|
@ -97,7 +97,7 @@ class DeathMatchGame(ba.TeamGameActivity[Player, Team]):
|
|||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._score_to_win: Optional[int] = None
|
||||
self._score_to_win: int | None = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._kills_to_win_per_player = int(
|
||||
|
|
@ -111,10 +111,10 @@ class DeathMatchGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC if self._epic_mode else
|
||||
ba.MusicType.TO_THE_DEATH)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'Crush ${ARG1} of your enemies.', self._score_to_win
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
return 'kill ${ARG1} enemies', self._score_to_win
|
||||
|
||||
def on_team_join(self, team: Team) -> None:
|
||||
|
|
|
|||
14
dist/ba_data/python/bastd/game/easteregghunt.py
vendored
14
dist/ba_data/python/bastd/game/easteregghunt.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Provides an easter egg hunt game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -20,15 +20,15 @@ from bastd.actor.respawnicon import RespawnIcon
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.respawn_timer: Optional[ba.Timer] = None
|
||||
self.respawn_icon: Optional[RespawnIcon] = None
|
||||
self.respawn_timer: ba.Timer | None = None
|
||||
self.respawn_icon: RespawnIcon | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
|
|
@ -76,9 +76,9 @@ class EasterEggHuntGame(ba.TeamGameActivity[Player, Team]):
|
|||
conditions=('they_have_material', shared.player_material),
|
||||
actions=(('call', 'at_connect', self._on_egg_player_collide), ))
|
||||
self._eggs: list[Egg] = []
|
||||
self._update_timer: Optional[ba.Timer] = None
|
||||
self._countdown: Optional[OnScreenCountdown] = None
|
||||
self._bots: Optional[SpazBotSet] = None
|
||||
self._update_timer: ba.Timer | None = None
|
||||
self._countdown: OnScreenCountdown | None = None
|
||||
self._bots: SpazBotSet | None = None
|
||||
|
||||
# Base class overrides
|
||||
self.default_music = ba.MusicType.FORWARD_MARCH
|
||||
|
|
|
|||
18
dist/ba_data/python/bastd/game/elimination.py
vendored
18
dist/ba_data/python/bastd/game/elimination.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Elimination mini-game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -14,7 +14,7 @@ from bastd.actor.spazfactory import SpazFactory
|
|||
from bastd.actor.scoreboard import Scoreboard
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Icon(ba.Actor):
|
||||
|
|
@ -162,7 +162,7 @@ class Team(ba.Team[Player]):
|
|||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.survival_seconds: Optional[int] = None
|
||||
self.survival_seconds: int | None = None
|
||||
self.spawn_order: list[Player] = []
|
||||
|
||||
|
||||
|
|
@ -234,9 +234,9 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]):
|
|||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._start_time: Optional[float] = None
|
||||
self._vs_text: Optional[ba.Actor] = None
|
||||
self._round_end_timer: Optional[ba.Timer] = None
|
||||
self._start_time: float | None = None
|
||||
self._vs_text: ba.Actor | None = None
|
||||
self._round_end_timer: ba.Timer | None = None
|
||||
self._epic_mode = bool(settings['Epic Mode'])
|
||||
self._lives_per_player = int(settings['Lives Per Player'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
|
@ -249,11 +249,11 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC
|
||||
if self._epic_mode else ba.MusicType.SURVIVAL)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'Last team standing wins.' if isinstance(
|
||||
self.session, ba.DualTeamSession) else 'Last one standing wins.'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
return 'last team standing wins' if isinstance(
|
||||
self.session, ba.DualTeamSession) else 'last one standing wins'
|
||||
|
||||
|
|
@ -401,7 +401,7 @@ class EliminationGame(ba.TeamGameActivity[Player, Team]):
|
|||
icon.update_for_lives()
|
||||
xval += x_offs
|
||||
|
||||
def _get_spawn_point(self, player: Player) -> Optional[ba.Vec3]:
|
||||
def _get_spawn_point(self, player: Player) -> ba.Vec3 | None:
|
||||
del player # Unused.
|
||||
|
||||
# In solo-mode, if there's an existing live player on the map, spawn at
|
||||
|
|
|
|||
66
dist/ba_data/python/bastd/game/football.py
vendored
66
dist/ba_data/python/bastd/game/football.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Implements football games (both co-op and teams varieties)."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -26,7 +26,7 @@ from bastd.actor.spazbot import (SpazBotDiedMessage, SpazBotPunchedMessage,
|
|||
StickyBot, ExplodeyBot)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.spaz import Spaz
|
||||
from bastd.actor.spazbot import SpazBot
|
||||
|
||||
|
|
@ -39,9 +39,9 @@ class FootballFlag(Flag):
|
|||
dropped_timeout=20,
|
||||
color=(1.0, 1.0, 0.3))
|
||||
assert self.node
|
||||
self.last_holding_player: Optional[ba.Player] = None
|
||||
self.last_holding_player: ba.Player | None = None
|
||||
self.node.is_area_of_interest = True
|
||||
self.respawn_timer: Optional[ba.Timer] = None
|
||||
self.respawn_timer: ba.Timer | None = None
|
||||
self.scored = False
|
||||
self.held_count = 0
|
||||
self.light = ba.newnode('light',
|
||||
|
|
@ -59,8 +59,8 @@ class Player(ba.Player['Team']):
|
|||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.respawn_timer: Optional[ba.Timer] = None
|
||||
self.respawn_icon: Optional[RespawnIcon] = None
|
||||
self.respawn_timer: ba.Timer | None = None
|
||||
self.respawn_icon: RespawnIcon | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
|
|
@ -120,7 +120,7 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]):
|
|||
|
||||
def __init__(self, settings: dict):
|
||||
super().__init__(settings)
|
||||
self._scoreboard: Optional[Scoreboard] = Scoreboard()
|
||||
self._scoreboard: Scoreboard | None = Scoreboard()
|
||||
|
||||
# Load some media we need.
|
||||
self._cheer_sound = ba.getsound('cheer')
|
||||
|
|
@ -136,15 +136,15 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]):
|
|||
('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', self._handle_score),
|
||||
))
|
||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._flag_spawn_pos: Sequence[float] | None = None
|
||||
self._score_regions: list[ba.NodeActor] = []
|
||||
self._flag: Optional[FootballFlag] = None
|
||||
self._flag_respawn_timer: Optional[ba.Timer] = None
|
||||
self._flag_respawn_light: Optional[ba.NodeActor] = None
|
||||
self._flag: FootballFlag | None = None
|
||||
self._flag_respawn_timer: ba.Timer | None = None
|
||||
self._flag_respawn_light: ba.NodeActor | None = None
|
||||
self._score_to_win = int(settings['Score to Win'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
touchdowns = self._score_to_win / 7
|
||||
|
||||
# NOTE: if use just touchdowns = self._score_to_win // 7
|
||||
|
|
@ -155,7 +155,7 @@ class FootballTeamGame(ba.TeamGameActivity[Player, Team]):
|
|||
return 'Score ${ARG1} touchdowns.', touchdowns
|
||||
return 'Score a touchdown.'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
touchdowns = self._score_to_win / 7
|
||||
touchdowns = math.ceil(touchdowns)
|
||||
if touchdowns > 1:
|
||||
|
|
@ -336,14 +336,14 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]):
|
|||
def get_score_type(self) -> str:
|
||||
return 'time'
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
touchdowns = self._score_to_win / 7
|
||||
touchdowns = math.ceil(touchdowns)
|
||||
if touchdowns > 1:
|
||||
return 'Score ${ARG1} touchdowns.', touchdowns
|
||||
return 'Score a touchdown.'
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
touchdowns = self._score_to_win / 7
|
||||
touchdowns = math.ceil(touchdowns)
|
||||
if touchdowns > 1:
|
||||
|
|
@ -375,27 +375,27 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]):
|
|||
self._powerup_spread = (10, 5.5)
|
||||
self._player_has_dropped_bomb = False
|
||||
self._player_has_punched = False
|
||||
self._scoreboard: Optional[Scoreboard] = None
|
||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._scoreboard: Scoreboard | None = None
|
||||
self._flag_spawn_pos: Sequence[float] | None = None
|
||||
self._score_regions: list[ba.NodeActor] = []
|
||||
self._exclude_powerups: list[str] = []
|
||||
self._have_tnt = False
|
||||
self._bot_types_initial: Optional[list[type[SpazBot]]] = None
|
||||
self._bot_types_7: Optional[list[type[SpazBot]]] = None
|
||||
self._bot_types_14: Optional[list[type[SpazBot]]] = None
|
||||
self._bot_team: Optional[Team] = None
|
||||
self._starttime_ms: Optional[int] = None
|
||||
self._time_text: Optional[ba.NodeActor] = None
|
||||
self._time_text_input: Optional[ba.NodeActor] = None
|
||||
self._tntspawner: Optional[TNTSpawner] = None
|
||||
self._bot_types_initial: list[type[SpazBot]] | None = None
|
||||
self._bot_types_7: list[type[SpazBot]] | None = None
|
||||
self._bot_types_14: list[type[SpazBot]] | None = None
|
||||
self._bot_team: Team | None = None
|
||||
self._starttime_ms: int | None = None
|
||||
self._time_text: ba.NodeActor | None = None
|
||||
self._time_text_input: ba.NodeActor | None = None
|
||||
self._tntspawner: TNTSpawner | None = None
|
||||
self._bots = SpazBotSet()
|
||||
self._bot_spawn_timer: Optional[ba.Timer] = None
|
||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||
self._scoring_team: Optional[Team] = None
|
||||
self._final_time_ms: Optional[int] = None
|
||||
self._time_text_timer: Optional[ba.Timer] = None
|
||||
self._flag_respawn_light: Optional[ba.Actor] = None
|
||||
self._flag: Optional[FootballFlag] = None
|
||||
self._bot_spawn_timer: ba.Timer | None = None
|
||||
self._powerup_drop_timer: ba.Timer | None = None
|
||||
self._scoring_team: Team | None = None
|
||||
self._final_time_ms: int | None = None
|
||||
self._time_text_timer: ba.Timer | None = None
|
||||
self._flag_respawn_light: ba.Actor | None = None
|
||||
self._flag: FootballFlag | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
|
|
@ -581,7 +581,7 @@ class FootballCoopGame(ba.CoopGameActivity[Player, Team]):
|
|||
return
|
||||
|
||||
flagpos = ba.Vec3(self._flag.node.position)
|
||||
closest_bot: Optional[SpazBot] = None
|
||||
closest_bot: SpazBot | None = None
|
||||
closest_dist = 0.0 # Always gets assigned first time through.
|
||||
for bot in bots:
|
||||
# If a bot is picked up, he should forget about the flag.
|
||||
|
|
|
|||
14
dist/ba_data/python/bastd/game/hockey.py
vendored
14
dist/ba_data/python/bastd/game/hockey.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Hockey game and support classes."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -16,7 +16,7 @@ from bastd.actor.powerupbox import PowerupBoxFactory
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class PuckDiedMessage:
|
||||
|
|
@ -198,18 +198,18 @@ class HockeyGame(ba.TeamGameActivity[Player, Team]):
|
|||
actions=(('modify_part_collision', 'collide',
|
||||
True), ('modify_part_collision', 'physical', False),
|
||||
('call', 'at_connect', self._handle_score)))
|
||||
self._puck_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._score_regions: Optional[list[ba.NodeActor]] = None
|
||||
self._puck: Optional[Puck] = None
|
||||
self._puck_spawn_pos: Sequence[float] | None = None
|
||||
self._score_regions: list[ba.NodeActor] | None = None
|
||||
self._puck: Puck | None = None
|
||||
self._score_to_win = int(settings['Score to Win'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'Score a goal.'
|
||||
return 'Score ${ARG1} goals.', self._score_to_win
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
if self._score_to_win == 1:
|
||||
return 'score a goal'
|
||||
return 'score ${ARG1} goals', self._score_to_win
|
||||
|
|
|
|||
20
dist/ba_data/python/bastd/game/keepaway.py
vendored
20
dist/ba_data/python/bastd/game/keepaway.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines a keep-away game type."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -17,7 +17,7 @@ from bastd.actor.flag import (Flag, FlagDroppedMessage, FlagDiedMessage,
|
|||
FlagPickedUpMessage)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class FlagState(Enum):
|
||||
|
|
@ -106,20 +106,20 @@ class KeepAwayGame(ba.TeamGameActivity[Player, Team]):
|
|||
2: ba.getsound('announceTwo'),
|
||||
1: ba.getsound('announceOne')
|
||||
}
|
||||
self._flag_spawn_pos: Optional[Sequence[float]] = None
|
||||
self._update_timer: Optional[ba.Timer] = None
|
||||
self._flag_spawn_pos: Sequence[float] | None = None
|
||||
self._update_timer: ba.Timer | None = None
|
||||
self._holding_players: list[Player] = []
|
||||
self._flag_state: Optional[FlagState] = None
|
||||
self._flag_light: Optional[ba.Node] = None
|
||||
self._scoring_team: Optional[Team] = None
|
||||
self._flag: Optional[Flag] = None
|
||||
self._flag_state: FlagState | None = None
|
||||
self._flag_light: ba.Node | None = None
|
||||
self._scoring_team: Team | None = None
|
||||
self._flag: Flag | None = None
|
||||
self._hold_time = int(settings['Hold Time'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'Carry the flag for ${ARG1} seconds.', self._hold_time
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
return 'carry the flag for ${ARG1} seconds', self._hold_time
|
||||
|
||||
def create_team(self, sessionteam: ba.SessionTeam) -> Team:
|
||||
|
|
|
|||
20
dist/ba_data/python/bastd/game/kingofthehill.py
vendored
20
dist/ba_data/python/bastd/game/kingofthehill.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines the King of the Hill game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -18,7 +18,7 @@ from bastd.actor.scoreboard import Scoreboard
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class FlagState(Enum):
|
||||
|
|
@ -108,11 +108,11 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]):
|
|||
2: ba.getsound('announceTwo'),
|
||||
1: ba.getsound('announceOne')
|
||||
}
|
||||
self._flag_pos: Optional[Sequence[float]] = None
|
||||
self._flag_state: Optional[FlagState] = None
|
||||
self._flag: Optional[Flag] = None
|
||||
self._flag_light: Optional[ba.Node] = None
|
||||
self._scoring_team: Optional[weakref.ref[Team]] = None
|
||||
self._flag_pos: Sequence[float] | None = None
|
||||
self._flag_state: FlagState | None = None
|
||||
self._flag: Flag | None = None
|
||||
self._flag_light: ba.Node | None = None
|
||||
self._scoring_team: weakref.ref[Team] | None = None
|
||||
self._hold_time = int(settings['Hold Time'])
|
||||
self._time_limit = float(settings['Time Limit'])
|
||||
self._flag_region_material = ba.Material()
|
||||
|
|
@ -130,10 +130,10 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]):
|
|||
# Base class overrides.
|
||||
self.default_music = ba.MusicType.SCARY
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
return 'Secure the flag for ${ARG1} seconds.', self._hold_time
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
return 'secure the flag for ${ARG1} seconds', self._hold_time
|
||||
|
||||
def create_team(self, sessionteam: ba.SessionTeam) -> Team:
|
||||
|
|
@ -239,7 +239,7 @@ class KingOfTheHillGame(ba.TeamGameActivity[Player, Team]):
|
|||
|
||||
def _handle_player_flag_region_collide(self, colliding: bool) -> None:
|
||||
try:
|
||||
spaz = ba.getcollision().sourcenode.getdelegate(PlayerSpaz, True)
|
||||
spaz = ba.getcollision().opposingnode.getdelegate(PlayerSpaz, True)
|
||||
except ba.NotFoundError:
|
||||
return
|
||||
|
||||
|
|
|
|||
15
dist/ba_data/python/bastd/game/meteorshower.py
vendored
15
dist/ba_data/python/bastd/game/meteorshower.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines a bomb-dodging mini-game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -15,7 +15,7 @@ from bastd.actor.bomb import Bomb
|
|||
from bastd.actor.onscreentimer import OnScreenTimer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
|
|
@ -23,7 +23,7 @@ class Player(ba.Player['Team']):
|
|||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.death_time: Optional[float] = None
|
||||
self.death_time: float | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
|
|
@ -64,9 +64,9 @@ class MeteorShowerGame(ba.TeamGameActivity[Player, Team]):
|
|||
super().__init__(settings)
|
||||
|
||||
self._epic_mode = settings.get('Epic Mode', False)
|
||||
self._last_player_death_time: Optional[float] = None
|
||||
self._last_player_death_time: float | None = None
|
||||
self._meteor_time = 2.0
|
||||
self._timer: Optional[OnScreenTimer] = None
|
||||
self._timer: OnScreenTimer | None = None
|
||||
|
||||
# Some base class overrides:
|
||||
self.default_music = (ba.MusicType.EPIC
|
||||
|
|
@ -188,9 +188,10 @@ class MeteorShowerGame(ba.TeamGameActivity[Player, Team]):
|
|||
# Drop them somewhere within our bounds with velocity pointing
|
||||
# toward the opposite side.
|
||||
pos = (-7.3 + 15.3 * random.random(), 11,
|
||||
-5.5 + 2.1 * random.random())
|
||||
-5.57 + 2.1 * random.random())
|
||||
dropdir = (-1.0 if pos[0] > 0 else 1.0)
|
||||
vel = ((-5.0 + random.random() * 30.0) * dropdir, -4.0, 0)
|
||||
vel = ((-5.0 + random.random() * 30.0) * dropdir,
|
||||
random.uniform(-3.066, -4.12), 0)
|
||||
ba.timer(delay, ba.Call(self._drop_bomb, pos, vel))
|
||||
delay += 0.1
|
||||
self._set_meteor_timer()
|
||||
|
|
|
|||
6
dist/ba_data/python/bastd/game/ninjafight.py
vendored
6
dist/ba_data/python/bastd/game/ninjafight.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Provides Ninja Fight mini-game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -15,7 +15,7 @@ from bastd.actor.spazbot import SpazBotSet, ChargerBot, SpazBotDiedMessage
|
|||
from bastd.actor.onscreentimer import OnScreenTimer
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
|
|
@ -58,7 +58,7 @@ class NinjaFightGame(ba.TeamGameActivity[Player, Team]):
|
|||
super().__init__(settings)
|
||||
self._winsound = ba.getsound('score')
|
||||
self._won = False
|
||||
self._timer: Optional[OnScreenTimer] = None
|
||||
self._timer: OnScreenTimer | None = None
|
||||
self._bots = SpazBotSet()
|
||||
self._preset = str(settings['preset'])
|
||||
|
||||
|
|
|
|||
44
dist/ba_data/python/bastd/game/onslaught.py
vendored
44
dist/ba_data/python/bastd/game/onslaught.py
vendored
|
|
@ -28,22 +28,22 @@ from bastd.actor.spazbot import (
|
|||
TriggerBotProShielded, BrawlerBotPro, BomberBotProShielded)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Union, Sequence
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.spazbot import SpazBot
|
||||
|
||||
|
||||
@dataclass
|
||||
class Wave:
|
||||
"""A wave of enemies."""
|
||||
entries: list[Union[Spawn, Spacing, Delay, None]]
|
||||
entries: list[Spawn | Spacing | Delay | None]
|
||||
base_angle: float = 0.0
|
||||
|
||||
|
||||
@dataclass
|
||||
class Spawn:
|
||||
"""A bot spawn event in a wave."""
|
||||
bottype: Union[type[SpazBot], str]
|
||||
point: Optional[Point] = None
|
||||
bottype: type[SpazBot] | str
|
||||
point: Point | None = None
|
||||
spacing: float = 5.0
|
||||
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
name = 'Onslaught'
|
||||
description = 'Defeat all enemies.'
|
||||
|
||||
tips: list[Union[str, ba.GameTip]] = [
|
||||
tips: list[str | ba.GameTip] = [
|
||||
'Hold any button to run.'
|
||||
' (Trigger buttons work well if you have them)',
|
||||
'Try tricking enemies into killing eachother or running off cliffs.',
|
||||
|
|
@ -169,26 +169,26 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
self._powerup_spread = (4.6, 2.7)
|
||||
else:
|
||||
raise Exception('Unsupported map: ' + str(settings['map']))
|
||||
self._scoreboard: Optional[Scoreboard] = None
|
||||
self._scoreboard: Scoreboard | None = None
|
||||
self._game_over = False
|
||||
self._wavenum = 0
|
||||
self._can_end_wave = True
|
||||
self._score = 0
|
||||
self._time_bonus = 0
|
||||
self._spawn_info_text: Optional[ba.NodeActor] = None
|
||||
self._spawn_info_text: ba.NodeActor | None = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._dingsoundhigh = ba.getsound('dingSmallHigh')
|
||||
self._have_tnt = False
|
||||
self._excluded_powerups: Optional[list[str]] = None
|
||||
self._excluded_powerups: list[str] | None = None
|
||||
self._waves: list[Wave] = []
|
||||
self._tntspawner: Optional[TNTSpawner] = None
|
||||
self._bots: Optional[SpazBotSet] = None
|
||||
self._powerup_drop_timer: Optional[ba.Timer] = None
|
||||
self._time_bonus_timer: Optional[ba.Timer] = None
|
||||
self._time_bonus_text: Optional[ba.NodeActor] = None
|
||||
self._flawless_bonus: Optional[int] = None
|
||||
self._wave_text: Optional[ba.NodeActor] = None
|
||||
self._wave_update_timer: Optional[ba.Timer] = None
|
||||
self._tntspawner: TNTSpawner | None = None
|
||||
self._bots: SpazBotSet | None = None
|
||||
self._powerup_drop_timer: ba.Timer | None = None
|
||||
self._time_bonus_timer: ba.Timer | None = None
|
||||
self._time_bonus_text: ba.NodeActor | None = None
|
||||
self._flawless_bonus: int | None = None
|
||||
self._wave_text: ba.NodeActor | None = None
|
||||
self._wave_update_timer: ba.Timer | None = None
|
||||
self._throw_off_kills = 0
|
||||
self._land_mine_kills = 0
|
||||
self._tnt_kills = 0
|
||||
|
|
@ -729,7 +729,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
"""End the game with the specified outcome."""
|
||||
if outcome == 'defeat':
|
||||
self.fade_to_red()
|
||||
score: Optional[int]
|
||||
score: int | None
|
||||
if self._wavenum >= 2:
|
||||
score = self._score
|
||||
fail_message = None
|
||||
|
|
@ -878,7 +878,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
if not any(player.is_alive() for player in self.teams[0].players):
|
||||
self._spawn_info_text.node.text = ''
|
||||
else:
|
||||
text: Union[str, ba.Lstr] = ''
|
||||
text: str | ba.Lstr = ''
|
||||
for player in self.players:
|
||||
if (not player.is_alive()
|
||||
and (self._preset
|
||||
|
|
@ -1070,8 +1070,8 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
def _add_entries_for_distribution_group(
|
||||
self, group: list[tuple[int, int]],
|
||||
bot_levels: list[list[type[SpazBot]]],
|
||||
all_entries: list[Union[Spawn, Spacing, Delay, None]]) -> None:
|
||||
entries: list[Union[Spawn, Spacing, Delay, None]] = []
|
||||
all_entries: list[Spawn | Spacing | Delay | None]) -> None:
|
||||
entries: list[Spawn | Spacing | Delay | None] = []
|
||||
for entry in group:
|
||||
bot_level = bot_levels[entry[0] - 1]
|
||||
bot_type = bot_level[random.randrange(len(bot_level))]
|
||||
|
|
@ -1106,7 +1106,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
distribution = self._get_distribution(target_points, min_dudes,
|
||||
max_dudes, group_count,
|
||||
max_level)
|
||||
all_entries: list[Union[Spawn, Spacing, Delay, None]] = []
|
||||
all_entries: list[Spawn | Spacing | Delay | None] = []
|
||||
for group in distribution:
|
||||
self._add_entries_for_distribution_group(group, bot_levels,
|
||||
all_entries)
|
||||
|
|
@ -1206,7 +1206,7 @@ class OnslaughtGame(ba.CoopGameActivity[Player, Team]):
|
|||
pts, importance = msg.spazbot.get_death_points(msg.how)
|
||||
if msg.killerplayer is not None:
|
||||
self._handle_kill_achievements(msg)
|
||||
target: Optional[Sequence[float]]
|
||||
target: Sequence[float] | None
|
||||
if msg.spazbot.node:
|
||||
target = msg.spazbot.node.position
|
||||
else:
|
||||
|
|
|
|||
42
dist/ba_data/python/bastd/game/race.py
vendored
42
dist/ba_data/python/bastd/game/race.py
vendored
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines Race mini-game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -18,7 +18,7 @@ from bastd.actor.scoreboard import Scoreboard
|
|||
from bastd.gameutils import SharedObjects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.onscreentimer import OnScreenTimer
|
||||
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ if TYPE_CHECKING:
|
|||
class RaceMine:
|
||||
"""Holds info about a mine on the track."""
|
||||
point: Sequence[float]
|
||||
mine: Optional[Bomb]
|
||||
mine: Bomb | None
|
||||
|
||||
|
||||
class RaceRegion(ba.Actor):
|
||||
|
|
@ -53,19 +53,19 @@ class Player(ba.Player['Team']):
|
|||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.distance_txt: Optional[ba.Node] = None
|
||||
self.distance_txt: ba.Node | None = None
|
||||
self.last_region = 0
|
||||
self.lap = 0
|
||||
self.distance = 0.0
|
||||
self.finished = False
|
||||
self.rank: Optional[int] = None
|
||||
self.rank: int | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
"""Our team type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.time: Optional[float] = None
|
||||
self.time: float | None = None
|
||||
self.lap = 0
|
||||
self.finished = False
|
||||
|
||||
|
|
@ -141,22 +141,22 @@ class RaceGame(ba.TeamGameActivity[Player, Team]):
|
|||
self._scoreboard = Scoreboard()
|
||||
self._score_sound = ba.getsound('score')
|
||||
self._swipsound = ba.getsound('swip')
|
||||
self._last_team_time: Optional[float] = None
|
||||
self._front_race_region: Optional[int] = None
|
||||
self._last_team_time: float | None = None
|
||||
self._front_race_region: int | None = None
|
||||
self._nub_tex = ba.gettexture('nub')
|
||||
self._beep_1_sound = ba.getsound('raceBeep1')
|
||||
self._beep_2_sound = ba.getsound('raceBeep2')
|
||||
self.race_region_material: Optional[ba.Material] = None
|
||||
self.race_region_material: ba.Material | None = None
|
||||
self._regions: list[RaceRegion] = []
|
||||
self._team_finish_pts: Optional[int] = None
|
||||
self._time_text: Optional[ba.Actor] = None
|
||||
self._timer: Optional[OnScreenTimer] = None
|
||||
self._race_mines: Optional[list[RaceMine]] = None
|
||||
self._race_mine_timer: Optional[ba.Timer] = None
|
||||
self._scoreboard_timer: Optional[ba.Timer] = None
|
||||
self._player_order_update_timer: Optional[ba.Timer] = None
|
||||
self._start_lights: Optional[list[ba.Node]] = None
|
||||
self._bomb_spawn_timer: Optional[ba.Timer] = None
|
||||
self._team_finish_pts: int | None = None
|
||||
self._time_text: ba.Actor | None = None
|
||||
self._timer: OnScreenTimer | None = None
|
||||
self._race_mines: list[RaceMine] | None = None
|
||||
self._race_mine_timer: ba.Timer | None = None
|
||||
self._scoreboard_timer: ba.Timer | None = None
|
||||
self._player_order_update_timer: ba.Timer | None = None
|
||||
self._start_lights: list[ba.Node] | None = None
|
||||
self._bomb_spawn_timer: ba.Timer | None = None
|
||||
self._laps = int(settings['Laps'])
|
||||
self._entire_team_must_finish = bool(
|
||||
settings.get('Entire Team Must Finish', False))
|
||||
|
|
@ -170,7 +170,7 @@ class RaceGame(ba.TeamGameActivity[Player, Team]):
|
|||
self.default_music = (ba.MusicType.EPIC_RACE
|
||||
if self._epic_mode else ba.MusicType.RACE)
|
||||
|
||||
def get_instance_description(self) -> Union[str, Sequence]:
|
||||
def get_instance_description(self) -> str | Sequence:
|
||||
if (isinstance(self.session, ba.DualTeamSession)
|
||||
and self._entire_team_must_finish):
|
||||
t_str = ' Your entire team has to finish.'
|
||||
|
|
@ -181,7 +181,7 @@ class RaceGame(ba.TeamGameActivity[Player, Team]):
|
|||
return 'Run ${ARG1} laps.' + t_str, self._laps
|
||||
return 'Run 1 lap.' + t_str
|
||||
|
||||
def get_instance_description_short(self) -> Union[str, Sequence]:
|
||||
def get_instance_description_short(self) -> str | Sequence:
|
||||
if self._laps > 1:
|
||||
return 'run ${ARG1} laps', self._laps
|
||||
return 'run 1 lap'
|
||||
|
|
@ -522,7 +522,7 @@ class RaceGame(ba.TeamGameActivity[Player, Team]):
|
|||
|
||||
# Calc all player distances.
|
||||
for player in self.players:
|
||||
pos: Optional[ba.Vec3]
|
||||
pos: ba.Vec3 | None
|
||||
try:
|
||||
pos = player.position
|
||||
except ba.NotFoundError:
|
||||
|
|
|
|||
46
dist/ba_data/python/bastd/game/runaround.py
vendored
46
dist/ba_data/python/bastd/game/runaround.py
vendored
|
|
@ -26,7 +26,7 @@ from bastd.actor.spazbot import (
|
|||
BomberBotPro, BrawlerBotPro)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Sequence, Optional, Union
|
||||
from typing import Any, Sequence
|
||||
|
||||
|
||||
class Preset(Enum):
|
||||
|
|
@ -54,7 +54,7 @@ class Spawn:
|
|||
# noinspection PyUnresolvedReferences
|
||||
type: type[SpazBot]
|
||||
path: int = 0
|
||||
point: Optional[Point] = None
|
||||
point: Point | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -66,15 +66,15 @@ class Spacing:
|
|||
@dataclass
|
||||
class Wave:
|
||||
"""Defines a wave of enemies."""
|
||||
entries: list[Union[Spawn, Spacing, None]]
|
||||
entries: list[Spawn | Spacing | None]
|
||||
|
||||
|
||||
class Player(ba.Player['Team']):
|
||||
"""Our player type for this game."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.respawn_timer: Optional[ba.Timer] = None
|
||||
self.respawn_icon: Optional[RespawnIcon] = None
|
||||
self.respawn_timer: ba.Timer | None = None
|
||||
self.respawn_icon: RespawnIcon | None = None
|
||||
|
||||
|
||||
class Team(ba.Team[Player]):
|
||||
|
|
@ -144,31 +144,31 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]):
|
|||
|
||||
self._last_wave_end_time = ba.time()
|
||||
self._player_has_picked_up_powerup = False
|
||||
self._scoreboard: Optional[Scoreboard] = None
|
||||
self._scoreboard: Scoreboard | None = None
|
||||
self._game_over = False
|
||||
self._wavenum = 0
|
||||
self._can_end_wave = True
|
||||
self._score = 0
|
||||
self._time_bonus = 0
|
||||
self._score_region: Optional[ba.Actor] = None
|
||||
self._score_region: ba.Actor | None = None
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._dingsoundhigh = ba.getsound('dingSmallHigh')
|
||||
self._exclude_powerups: Optional[list[str]] = None
|
||||
self._have_tnt: Optional[bool] = None
|
||||
self._waves: Optional[list[Wave]] = None
|
||||
self._exclude_powerups: list[str] | None = None
|
||||
self._have_tnt: bool | None = None
|
||||
self._waves: list[Wave] | None = None
|
||||
self._bots = SpazBotSet()
|
||||
self._tntspawner: Optional[TNTSpawner] = None
|
||||
self._lives_bg: Optional[ba.NodeActor] = None
|
||||
self._tntspawner: TNTSpawner | None = None
|
||||
self._lives_bg: ba.NodeActor | None = None
|
||||
self._start_lives = 10
|
||||
self._lives = self._start_lives
|
||||
self._lives_text: Optional[ba.NodeActor] = None
|
||||
self._lives_text: ba.NodeActor | None = None
|
||||
self._flawless = True
|
||||
self._time_bonus_timer: Optional[ba.Timer] = None
|
||||
self._time_bonus_text: Optional[ba.NodeActor] = None
|
||||
self._time_bonus_mult: Optional[float] = None
|
||||
self._wave_text: Optional[ba.NodeActor] = None
|
||||
self._flawless_bonus: Optional[int] = None
|
||||
self._wave_update_timer: Optional[ba.Timer] = None
|
||||
self._time_bonus_timer: ba.Timer | None = None
|
||||
self._time_bonus_text: ba.NodeActor | None = None
|
||||
self._time_bonus_mult: float | None = None
|
||||
self._wave_text: ba.NodeActor | None = None
|
||||
self._flawless_bonus: int | None = None
|
||||
self._wave_update_timer: ba.Timer | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
|
|
@ -556,7 +556,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]):
|
|||
else:
|
||||
delay = 0
|
||||
|
||||
score: Optional[int]
|
||||
score: int | None
|
||||
if self._wavenum >= 2:
|
||||
score = self._score
|
||||
fail_message = None
|
||||
|
|
@ -723,13 +723,13 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]):
|
|||
t_sec = 0.0
|
||||
base_delay = 0.5
|
||||
delay = 0.0
|
||||
bot_types: list[Union[Spawn, Spacing, None]] = []
|
||||
bot_types: list[Spawn | Spacing | None] = []
|
||||
|
||||
if self._preset in {Preset.ENDLESS, Preset.ENDLESS_TOURNAMENT}:
|
||||
level = self._wavenum
|
||||
target_points = (level + 1) * 8.0
|
||||
group_count = random.randint(1, 3)
|
||||
entries: list[Union[Spawn, Spacing, None]] = []
|
||||
entries: list[Spawn | Spacing | None] = []
|
||||
spaz_types: list[tuple[type[SpazBot], float]] = []
|
||||
if level < 6:
|
||||
spaz_types += [(BomberBot, 5.0)]
|
||||
|
|
@ -1121,7 +1121,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]):
|
|||
return None
|
||||
pts, importance = msg.spazbot.get_death_points(msg.how)
|
||||
if msg.killerplayer is not None:
|
||||
target: Optional[Sequence[float]]
|
||||
target: Sequence[float] | None
|
||||
try:
|
||||
assert msg.spazbot is not None
|
||||
assert msg.spazbot.node
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Implements Target Practice game."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -17,7 +17,7 @@ from bastd.actor.bomb import Bomb
|
|||
from bastd.actor.popuptext import PopupText
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.bomb import Blast
|
||||
|
||||
|
||||
|
|
@ -62,8 +62,8 @@ class TargetPracticeGame(ba.TeamGameActivity[Player, Team]):
|
|||
super().__init__(settings)
|
||||
self._scoreboard = Scoreboard()
|
||||
self._targets: list[Target] = []
|
||||
self._update_timer: Optional[ba.Timer] = None
|
||||
self._countdown: Optional[OnScreenCountdown] = None
|
||||
self._update_timer: ba.Timer | None = None
|
||||
self._countdown: OnScreenCountdown | None = None
|
||||
self._target_count = int(settings['Target Count'])
|
||||
self._enable_impact_bombs = bool(settings['Enable Impact Bombs'])
|
||||
self._enable_triple_bombs = bool(settings['Enable Triple Bombs'])
|
||||
|
|
|
|||
14
dist/ba_data/python/bastd/game/thelaststand.py
vendored
14
dist/ba_data/python/bastd/game/thelaststand.py
vendored
|
|
@ -21,7 +21,7 @@ from bastd.actor.spazbot import (SpazBotSet, SpazBotDiedMessage, BomberBot,
|
|||
ChargerBot, StickyBot, ExplodeyBot)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Sequence
|
||||
from typing import Any, Sequence
|
||||
from bastd.actor.spazbot import SpazBot
|
||||
|
||||
|
||||
|
|
@ -71,14 +71,14 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]):
|
|||
self._powerup_spread = (7, 2)
|
||||
self._preset = str(settings.get('preset', 'default'))
|
||||
self._excludepowerups: list[str] = []
|
||||
self._scoreboard: Optional[Scoreboard] = None
|
||||
self._scoreboard: Scoreboard | None = None
|
||||
self._score = 0
|
||||
self._bots = SpazBotSet()
|
||||
self._dingsound = ba.getsound('dingSmall')
|
||||
self._dingsoundhigh = ba.getsound('dingSmallHigh')
|
||||
self._tntspawner: Optional[TNTSpawner] = None
|
||||
self._bot_update_interval: Optional[float] = None
|
||||
self._bot_update_timer: Optional[ba.Timer] = None
|
||||
self._tntspawner: TNTSpawner | None = None
|
||||
self._bot_update_interval: float | None = None
|
||||
self._bot_update_timer: ba.Timer | None = None
|
||||
self._powerup_drop_timer = None
|
||||
|
||||
# For each bot type: [spawnrate, increase, d_increase]
|
||||
|
|
@ -220,7 +220,7 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]):
|
|||
|
||||
# Now go back through and see where this value falls.
|
||||
total = 0
|
||||
bottype: Optional[type[SpazBot]] = None
|
||||
bottype: type[SpazBot] | None = None
|
||||
for spawntype, spawninfo in self._bot_spawn_types.items():
|
||||
total += spawninfo.spawnrate
|
||||
if randval <= total:
|
||||
|
|
@ -262,7 +262,7 @@ class TheLastStandGame(ba.CoopGameActivity[Player, Team]):
|
|||
|
||||
elif isinstance(msg, SpazBotDiedMessage):
|
||||
pts, importance = msg.spazbot.get_death_points(msg.how)
|
||||
target: Optional[Sequence[float]]
|
||||
target: Sequence[float] | None
|
||||
if msg.killerplayer:
|
||||
assert msg.spazbot.node
|
||||
target = msg.spazbot.node.position
|
||||
|
|
|
|||
18
dist/ba_data/python/bastd/gameutils.py
vendored
18
dist/ba_data/python/bastd/gameutils.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional
|
||||
pass
|
||||
|
||||
|
||||
class SharedObjects:
|
||||
|
|
@ -29,14 +29,14 @@ class SharedObjects:
|
|||
if self._STORENAME in activity.customdata:
|
||||
raise RuntimeError('Use SharedObjects.get() to fetch the'
|
||||
' shared instance for this activity.')
|
||||
self._object_material: Optional[ba.Material] = None
|
||||
self._player_material: Optional[ba.Material] = None
|
||||
self._pickup_material: Optional[ba.Material] = None
|
||||
self._footing_material: Optional[ba.Material] = None
|
||||
self._attack_material: Optional[ba.Material] = None
|
||||
self._death_material: Optional[ba.Material] = None
|
||||
self._region_material: Optional[ba.Material] = None
|
||||
self._railing_material: Optional[ba.Material] = None
|
||||
self._object_material: ba.Material | None = None
|
||||
self._player_material: ba.Material | None = None
|
||||
self._pickup_material: ba.Material | None = None
|
||||
self._footing_material: ba.Material | None = None
|
||||
self._attack_material: ba.Material | None = None
|
||||
self._death_material: ba.Material | None = None
|
||||
self._region_material: ba.Material | None = None
|
||||
self._railing_material: ba.Material | None = None
|
||||
|
||||
@classmethod
|
||||
def get(cls) -> SharedObjects:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
"""Defines a default keyboards."""
|
||||
|
||||
# ba_meta require api 6
|
||||
# ba_meta require api 7
|
||||
# (see https://ballistica.net/wiki/meta-tag-system)
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
|
|||
18
dist/ba_data/python/bastd/mainmenu.py
vendored
18
dist/ba_data/python/bastd/mainmenu.py
vendored
|
|
@ -13,7 +13,7 @@ import ba
|
|||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
# FIXME: Clean this up if I ever revisit it.
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
|
|
@ -32,8 +32,8 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
|||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
random.seed(123)
|
||||
self._logo_node: Optional[ba.Node] = None
|
||||
self._custom_logo_tex_name: Optional[str] = None
|
||||
self._logo_node: ba.Node | None = None
|
||||
self._custom_logo_tex_name: str | None = None
|
||||
self._word_actors: list[ba.Actor] = []
|
||||
app = ba.app
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
|||
|
||||
self._ts = 0.86
|
||||
|
||||
self._language: Optional[str] = None
|
||||
self._language: str | None = None
|
||||
self._update_timer = ba.Timer(1.0, self._update, repeat=True)
|
||||
self._update()
|
||||
|
||||
|
|
@ -263,12 +263,12 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
|||
self._valid = True
|
||||
self._message_duration = 10.0
|
||||
self._message_spacing = 2.0
|
||||
self._text: Optional[ba.NodeActor] = None
|
||||
self._text: ba.NodeActor | None = None
|
||||
self._activity = weakref.ref(activity)
|
||||
|
||||
# If we're signed in, fetch news immediately.
|
||||
# Otherwise wait until we are signed in.
|
||||
self._fetch_timer: Optional[ba.Timer] = ba.Timer(
|
||||
self._fetch_timer: ba.Timer | None = ba.Timer(
|
||||
1.0, ba.WeakCall(self._try_fetching_news), repeat=True)
|
||||
self._try_fetching_news()
|
||||
|
||||
|
|
@ -694,8 +694,8 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
|||
# (unless we're in VR mode in which case its best to
|
||||
# leave things still).
|
||||
if not ba.app.vr_mode:
|
||||
cmb: Optional[ba.Node]
|
||||
cmb2: Optional[ba.Node]
|
||||
cmb: ba.Node | None
|
||||
cmb2: ba.Node | None
|
||||
if not shadow:
|
||||
cmb = ba.newnode('combine',
|
||||
owner=word_obj.node,
|
||||
|
|
@ -756,7 +756,7 @@ class MainMenuActivity(ba.Activity[ba.Player, ba.Team]):
|
|||
delay + 0.2: scale
|
||||
})
|
||||
|
||||
def _get_custom_logo_tex_name(self) -> Optional[str]:
|
||||
def _get_custom_logo_tex_name(self) -> str | None:
|
||||
if _ba.get_v1_account_misc_read_val('easter', False):
|
||||
return 'logoEaster'
|
||||
return None
|
||||
|
|
|
|||
4
dist/ba_data/python/bastd/stdmap.py
vendored
4
dist/ba_data/python/bastd/stdmap.py
vendored
|
|
@ -9,7 +9,7 @@ from typing import TYPE_CHECKING
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
def _get_map_data(name: str) -> dict[str, Any]:
|
||||
|
|
@ -26,7 +26,7 @@ class StdMap(ba.Map):
|
|||
"""A map completely defined by asset data.
|
||||
|
||||
"""
|
||||
_data: Optional[dict[str, Any]] = None
|
||||
_data: dict[str, Any] | None = None
|
||||
|
||||
@classmethod
|
||||
def _getdata(cls) -> dict[str, Any]:
|
||||
|
|
|
|||
50
dist/ba_data/python/bastd/tutorial.py
vendored
50
dist/ba_data/python/bastd/tutorial.py
vendored
|
|
@ -23,10 +23,10 @@ import ba
|
|||
from bastd.actor import spaz as basespaz
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional, Callable, Sequence, Union
|
||||
from typing import Any, Callable, Sequence
|
||||
|
||||
|
||||
def _safesetattr(node: Optional[ba.Node], attr: str, value: Any) -> None:
|
||||
def _safesetattr(node: ba.Node | None, attr: str, value: Any) -> None:
|
||||
if node:
|
||||
setattr(node, attr, value)
|
||||
|
||||
|
|
@ -46,9 +46,9 @@ class ButtonPress:
|
|||
def run(self, a: TutorialActivity) -> None:
|
||||
s = a.current_spaz
|
||||
assert s is not None
|
||||
img: Optional[ba.Node]
|
||||
release_call: Optional[Callable]
|
||||
color: Optional[Sequence[float]]
|
||||
img: ba.Node | None
|
||||
release_call: Callable[[], None] | None
|
||||
color: Sequence[float] | None
|
||||
if self._button == 'punch':
|
||||
call = s.on_punch_press
|
||||
release_call = s.on_punch_release
|
||||
|
|
@ -124,9 +124,9 @@ class ButtonRelease:
|
|||
def run(self, a: TutorialActivity) -> None:
|
||||
s = a.current_spaz
|
||||
assert s is not None
|
||||
call: Optional[Callable]
|
||||
img: Optional[ba.Node]
|
||||
color: Optional[Sequence[float]]
|
||||
call: Callable[[], None] | None
|
||||
img: ba.Node | None
|
||||
color: Sequence[float] | None
|
||||
if self._button == 'punch':
|
||||
call = s.on_punch_release
|
||||
img = a.punch_image
|
||||
|
|
@ -183,9 +183,9 @@ class TutorialActivity(ba.Activity[Player, Team]):
|
|||
if settings is None:
|
||||
settings = {}
|
||||
super().__init__(settings)
|
||||
self.current_spaz: Optional[basespaz.Spaz] = None
|
||||
self.current_spaz: basespaz.Spaz | None = None
|
||||
self._benchmark_type = getattr(ba.getsession(), 'benchmark_type', None)
|
||||
self.last_start_time: Optional[int] = None
|
||||
self.last_start_time: int | None = None
|
||||
self.cycle_times: list[int] = []
|
||||
self.allow_pausing = True
|
||||
self.allow_kick_idle_players = False
|
||||
|
|
@ -200,31 +200,31 @@ class TutorialActivity(ba.Activity[Player, Team]):
|
|||
self._have_skipped = False
|
||||
self.stick_image_position_x = self.stick_image_position_y = 0.0
|
||||
self.spawn_sound = ba.getsound('spawn')
|
||||
self.map: Optional[ba.Map] = None
|
||||
self.text: Optional[ba.Node] = None
|
||||
self._skip_text: Optional[ba.Node] = None
|
||||
self._skip_count_text: Optional[ba.Node] = None
|
||||
self._scale: Optional[float] = None
|
||||
self.map: ba.Map | None = None
|
||||
self.text: ba.Node | None = None
|
||||
self._skip_text: ba.Node | None = None
|
||||
self._skip_count_text: ba.Node | None = None
|
||||
self._scale: float | None = None
|
||||
self._stick_base_position: tuple[float, float] = (0.0, 0.0)
|
||||
self._stick_nub_position: tuple[float, float] = (0.0, 0.0)
|
||||
self._stick_base_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0)
|
||||
self._stick_nub_image_color: Sequence[float] = (1.0, 1.0, 1.0, 1.0)
|
||||
self._time: int = -1
|
||||
self.punch_image_color = (1.0, 1.0, 1.0)
|
||||
self.punch_image: Optional[ba.Node] = None
|
||||
self.bomb_image: Optional[ba.Node] = None
|
||||
self.jump_image: Optional[ba.Node] = None
|
||||
self.pickup_image: Optional[ba.Node] = None
|
||||
self._stick_base_image: Optional[ba.Node] = None
|
||||
self._stick_nub_image: Optional[ba.Node] = None
|
||||
self.punch_image: ba.Node | None = None
|
||||
self.bomb_image: ba.Node | None = None
|
||||
self.jump_image: ba.Node | None = None
|
||||
self.pickup_image: ba.Node | None = None
|
||||
self._stick_base_image: ba.Node | None = None
|
||||
self._stick_nub_image: ba.Node | None = None
|
||||
self.bomb_image_color = (1.0, 1.0, 1.0)
|
||||
self.pickup_image_color = (1.0, 1.0, 1.0)
|
||||
self.control_ui_nodes: list[ba.Node] = []
|
||||
self.spazzes: dict[int, basespaz.Spaz] = {}
|
||||
self.jump_image_color = (1.0, 1.0, 1.0)
|
||||
self._entries: list[Any] = []
|
||||
self._read_entries_timer: Optional[ba.Timer] = None
|
||||
self._entry_timer: Optional[ba.Timer] = None
|
||||
self._read_entries_timer: ba.Timer | None = None
|
||||
self._entry_timer: ba.Timer | None = None
|
||||
|
||||
def on_transition_in(self) -> None:
|
||||
super().on_transition_in()
|
||||
|
|
@ -493,7 +493,7 @@ class TutorialActivity(ba.Activity[Player, Team]):
|
|||
color: Sequence[float] = (1.0, 1.0, 1.0),
|
||||
make_current: bool = False,
|
||||
relative_to: int = None,
|
||||
name: Union[str, ba.Lstr] = '',
|
||||
name: str | ba.Lstr = '',
|
||||
flash: bool = True,
|
||||
angle: float = 0.0):
|
||||
self._num = num
|
||||
|
|
@ -752,7 +752,7 @@ class TutorialActivity(ba.Activity[Player, Team]):
|
|||
|
||||
class Text:
|
||||
|
||||
def __init__(self, text: Union[str, ba.Lstr]):
|
||||
def __init__(self, text: str | ba.Lstr):
|
||||
self.text = text
|
||||
|
||||
def run(self, a: TutorialActivity) -> None:
|
||||
|
|
|
|||
4
dist/ba_data/python/bastd/ui/account/link.py
vendored
4
dist/ba_data/python/bastd/ui/account/link.py
vendored
|
|
@ -12,14 +12,14 @@ import _ba
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class AccountLinkWindow(ba.Window):
|
||||
"""Window for linking accounts."""
|
||||
|
||||
def __init__(self, origin_widget: ba.Widget = None):
|
||||
scale_origin: Optional[tuple[float, float]]
|
||||
scale_origin: tuple[float, float] | None
|
||||
if origin_widget is not None:
|
||||
self._transition_out = 'out_scale'
|
||||
scale_origin = origin_widget.get_screen_space_center()
|
||||
|
|
|
|||
34
dist/ba_data/python/bastd/ui/account/settings.py
vendored
34
dist/ba_data/python/bastd/ui/account/settings.py
vendored
|
|
@ -12,7 +12,7 @@ import _ba
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Optional, Union
|
||||
pass
|
||||
|
||||
|
||||
class AccountSettingsWindow(ba.Window):
|
||||
|
|
@ -25,15 +25,15 @@ class AccountSettingsWindow(ba.Window):
|
|||
close_once_signed_in: bool = False):
|
||||
# pylint: disable=too-many-statements
|
||||
|
||||
self._sign_in_game_circle_button: Optional[ba.Widget] = None
|
||||
self._sign_in_v2_button: Optional[ba.Widget] = None
|
||||
self._sign_in_device_button: Optional[ba.Widget] = None
|
||||
self._sign_in_game_circle_button: ba.Widget | None = None
|
||||
self._sign_in_v2_button: ba.Widget | None = None
|
||||
self._sign_in_device_button: ba.Widget | None = None
|
||||
|
||||
self._close_once_signed_in = close_once_signed_in
|
||||
ba.set_analytics_screen('Account Window')
|
||||
|
||||
# If they provided an origin-widget, scale up from that.
|
||||
scale_origin: Optional[tuple[float, float]]
|
||||
scale_origin: tuple[float, float] | None
|
||||
if origin_widget is not None:
|
||||
self._transition_out = 'out_scale'
|
||||
scale_origin = origin_widget.get_screen_space_center()
|
||||
|
|
@ -56,7 +56,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
repeat=True)
|
||||
|
||||
# Currently we can only reset achievements on game-center.
|
||||
account_type: Optional[str]
|
||||
account_type: str | None
|
||||
if self._signed_in:
|
||||
account_type = _ba.get_v1_account_type()
|
||||
else:
|
||||
|
|
@ -145,7 +145,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
claims_left_right=True,
|
||||
claims_tab=True,
|
||||
selection_loops_to_parent=True)
|
||||
self._subcontainer: Optional[ba.Widget] = None
|
||||
self._subcontainer: ba.Widget | None = None
|
||||
self._refresh()
|
||||
self._restore_state()
|
||||
|
||||
|
|
@ -344,7 +344,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
v_align='center')
|
||||
v -= local_signed_in_as_space * 0.4
|
||||
|
||||
self._account_name_text: Optional[ba.Widget]
|
||||
self._account_name_text: ba.Widget | None
|
||||
if show_signed_in_as:
|
||||
v -= signed_in_as_space * 0.2
|
||||
txt = ba.Lstr(
|
||||
|
|
@ -383,7 +383,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
if show_sign_in_benefits:
|
||||
v -= sign_in_benefits_space
|
||||
app = ba.app
|
||||
extra: Optional[Union[str, ba.Lstr]]
|
||||
extra: str | ba.Lstr | None
|
||||
if (app.platform in ['mac', 'ios']
|
||||
and app.subplatform == 'appstore'):
|
||||
extra = ba.Lstr(
|
||||
|
|
@ -616,7 +616,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
else:
|
||||
self.game_service_button = None
|
||||
|
||||
self._achievements_text: Optional[ba.Widget]
|
||||
self._achievements_text: ba.Widget | None
|
||||
if show_achievements_text:
|
||||
v -= achievements_text_space * 0.5
|
||||
self._achievements_text = ba.textwidget(
|
||||
|
|
@ -632,7 +632,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
else:
|
||||
self._achievements_text = None
|
||||
|
||||
self._achievements_button: Optional[ba.Widget]
|
||||
self._achievements_button: ba.Widget | None
|
||||
if show_achievements_button:
|
||||
button_width = 300
|
||||
v -= achievements_button_space * 0.85
|
||||
|
|
@ -661,7 +661,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
if show_achievements_text or show_achievements_button:
|
||||
self._refresh_achievements()
|
||||
|
||||
self._leaderboards_button: Optional[ba.Widget]
|
||||
self._leaderboards_button: ba.Widget | None
|
||||
if show_leaderboards_button:
|
||||
button_width = 300
|
||||
v -= leaderboards_button_space * 0.85
|
||||
|
|
@ -686,7 +686,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
else:
|
||||
self._leaderboards_button = None
|
||||
|
||||
self._campaign_progress_text: Optional[ba.Widget]
|
||||
self._campaign_progress_text: ba.Widget | None
|
||||
if show_campaign_progress:
|
||||
v -= campaign_progress_space * 0.5
|
||||
self._campaign_progress_text = ba.textwidget(
|
||||
|
|
@ -703,7 +703,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
else:
|
||||
self._campaign_progress_text = None
|
||||
|
||||
self._tickets_text: Optional[ba.Widget]
|
||||
self._tickets_text: ba.Widget | None
|
||||
if show_tickets:
|
||||
v -= tickets_space * 0.5
|
||||
self._tickets_text = ba.textwidget(parent=self._subcontainer,
|
||||
|
|
@ -753,7 +753,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
right_widget=_ba.get_special_widget('party_button'))
|
||||
ba.widget(edit=btn, left_widget=bbtn)
|
||||
|
||||
self._linked_accounts_text: Optional[ba.Widget]
|
||||
self._linked_accounts_text: ba.Widget | None
|
||||
if show_linked_accounts_text:
|
||||
v -= linked_accounts_text_space * 0.8
|
||||
self._linked_accounts_text = ba.textwidget(
|
||||
|
|
@ -808,7 +808,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
right_widget=_ba.get_special_widget('party_button'))
|
||||
ba.widget(edit=btn, left_widget=bbtn, show_buffer_bottom=50)
|
||||
|
||||
self._unlink_accounts_button: Optional[ba.Widget]
|
||||
self._unlink_accounts_button: ba.Widget | None
|
||||
if show_unlink_accounts_button:
|
||||
v -= unlink_accounts_button_space
|
||||
self._unlink_accounts_button = btn = ba.buttonwidget(
|
||||
|
|
@ -957,7 +957,7 @@ class AccountSettingsWindow(ba.Window):
|
|||
from ba.internal import getcampaign
|
||||
if self._campaign_progress_text is None:
|
||||
return
|
||||
p_str: Union[str, ba.Lstr]
|
||||
p_str: str | ba.Lstr
|
||||
try:
|
||||
campaign = getcampaign('Default')
|
||||
levels = campaign.levels
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import _ba
|
|||
import ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Optional
|
||||
from typing import Any
|
||||
|
||||
|
||||
class AccountUnlinkWindow(ba.Window):
|
||||
"""A window to kick off account unlinks."""
|
||||
|
||||
def __init__(self, origin_widget: ba.Widget = None):
|
||||
scale_origin: Optional[tuple[float, float]]
|
||||
scale_origin: tuple[float, float] | None
|
||||
if origin_widget is not None:
|
||||
self._transition_out = 'out_scale'
|
||||
scale_origin = origin_widget.get_screen_space_center()
|
||||
|
|
|
|||
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