latest cloudtool work

This commit is contained in:
Eric Froemling 2019-12-04 08:43:23 -08:00
parent e01573f418
commit ec5225856d
64 changed files with 372 additions and 218 deletions

View File

@ -11,6 +11,7 @@
<w>aaah</w> <w>aaah</w>
<w>aaai</w> <w>aaai</w>
<w>aarch</w> <w>aarch</w>
<w>abcdefghijklmnopqrstuvwxyz</w>
<w>abeb</w> <w>abeb</w>
<w>abot</w> <w>abot</w>
<w>abtn</w> <w>abtn</w>
@ -78,7 +79,13 @@
<w>argval</w> <w>argval</w>
<w>armeabi</w> <w>armeabi</w>
<w>arraymodule</w> <w>arraymodule</w>
<w>assetbundle</w>
<w>assetcache</w> <w>assetcache</w>
<w>assetdata</w>
<w>assetpackage</w>
<w>assetpath</w>
<w>assettype</w>
<w>assettypestr</w>
<w>astcenc</w> <w>astcenc</w>
<w>astroid</w> <w>astroid</w>
<w>asus</w> <w>asus</w>
@ -741,6 +748,7 @@
<w>incrementbuild</w> <w>incrementbuild</w>
<w>indentfilter</w> <w>indentfilter</w>
<w>indentstr</w> <w>indentstr</w>
<w>indexfilename</w>
<w>indicies</w> <w>indicies</w>
<w>indstr</w> <w>indstr</w>
<w>inet</w> <w>inet</w>
@ -1233,6 +1241,7 @@
<w>pushdocs</w> <w>pushdocs</w>
<w>pushish</w> <w>pushish</w>
<w>pushlist</w> <w>pushlist</w>
<w>putasset</w>
<w>pval</w> <w>pval</w>
<w>pvars</w> <w>pvars</w>
<w>pvrtc</w> <w>pvrtc</w>

View File

@ -88,7 +88,7 @@
</list> </list>
</option> </option>
</inspection_tool> </inspection_tool>
<inspection_tool class="PyUnusedLocalInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true"> <inspection_tool class="PyUnusedLocalInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false">
<scope name="UncheckedPython" level="WEAK WARNING" enabled="false"> <scope name="UncheckedPython" level="WEAK WARNING" enabled="false">
<option name="ignoreTupleUnpacking" value="true" /> <option name="ignoreTupleUnpacking" value="true" />
<option name="ignoreLambdaParameters" value="true" /> <option name="ignoreLambdaParameters" value="true" />

View File

@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand.
""" """
# (hash we can use to see if this file is out of date) # (hash we can use to see if this file is out of date)
# SOURCES_HASH=221041082183416610193123748095056578345 # SOURCES_HASH=161757749075580767394847135785091690137
# I'm sorry Pylint. I know this file saddens you. Be strong. # I'm sorry Pylint. I know this file saddens you. Be strong.
# pylint: disable=useless-suppression # pylint: disable=useless-suppression
@ -388,7 +388,8 @@ class Material:
label: str label: str
def add_actions(self, actions: Tuple, def add_actions(self,
actions: Tuple,
conditions: Optional[Tuple] = None) -> None: conditions: Optional[Tuple] = None) -> None:
"""add_actions(actions: Tuple, conditions: Optional[Tuple] = None) """add_actions(actions: Tuple, conditions: Optional[Tuple] = None)
-> None -> None
@ -939,7 +940,9 @@ class Player:
""" """
return None return None
def set_name(self, name: str, full_name: str = None, def set_name(self,
name: str,
full_name: str = None,
real: bool = True) -> None: real: bool = True) -> None:
"""set_name(name: str, full_name: str = None, real: bool = True) """set_name(name: str, full_name: str = None, real: bool = True)
-> None -> None
@ -2050,7 +2053,8 @@ def get_idle_time() -> int:
return int() return int()
def get_input_device(name: str, unique_id: str, def get_input_device(name: str,
unique_id: str,
doraise: bool = True) -> ba.InputDevice: doraise: bool = True) -> ba.InputDevice:
"""get_input_device(name: str, unique_id: str, doraise: bool = True) """get_input_device(name: str, unique_id: str, doraise: bool = True)
-> ba.InputDevice -> ba.InputDevice
@ -3330,9 +3334,9 @@ def set_have_mods(have_mods: bool) -> None:
return None return None
def set_internal_language_keys(listobj: List[Tuple[str, str]], def set_internal_language_keys(
random_names_list: List[Tuple[str, str]] listobj: List[Tuple[str, str]],
) -> None: random_names_list: List[Tuple[str, str]]) -> None:
"""set_internal_language_keys(listobj: List[Tuple[str, str]], """set_internal_language_keys(listobj: List[Tuple[str, str]],
random_names_list: List[Tuple[str, str]]) -> None random_names_list: List[Tuple[str, str]]) -> None
@ -3349,8 +3353,8 @@ def set_low_level_config_value(key: str, value: int) -> None:
return None return None
def set_map_bounds(bounds: Tuple[float, float, float, float, float, float] def set_map_bounds(
) -> None: bounds: Tuple[float, float, float, float, float, float]) -> None:
"""set_map_bounds(bounds: Tuple[float, float, float, float, float, float]) """set_map_bounds(bounds: Tuple[float, float, float, float, float, float])
-> None -> None
@ -3729,8 +3733,8 @@ def time(timetype: ba.TimeType = TimeType.SIM,
return 0.0 return 0.0
def time_format_check(time_format: ba.TimeFormat, def time_format_check(time_format: ba.TimeFormat, length: Union[float,
length: Union[float, int]) -> None: int]) -> None:
"""time_format_check(time_format: ba.TimeFormat, length: Union[float, int]) """time_format_check(time_format: ba.TimeFormat, length: Union[float, int])
-> None -> None
@ -3839,7 +3843,8 @@ def unlock_all_input() -> None:
return None return None
def value_test(arg: str, change: float = None, def value_test(arg: str,
change: float = None,
absolute: float = None) -> float: absolute: float = None) -> float:
"""value_test(arg: str, change: float = None, absolute: float = None) """value_test(arg: str, change: float = None, absolute: float = None)
-> float -> float

View File

@ -516,7 +516,9 @@ class Activity(DependencyComponent):
def handlemessage(self, msg: Any) -> Any: def handlemessage(self, msg: Any) -> Any:
"""General message handling; can be passed any message object.""" """General message handling; can be passed any message object."""
def end(self, results: Any = None, delay: float = 0.0, def end(self,
results: Any = None,
delay: float = 0.0,
force: bool = False) -> None: force: bool = False) -> None:
"""Commences Activity shutdown and delivers results to the ba.Session. """Commences Activity shutdown and delivers results to the ba.Session.

View File

@ -377,8 +377,8 @@ class App:
self.main_menu_selection: Optional[str] = None # FIXME: Kill this. self.main_menu_selection: Optional[str] = None # FIXME: Kill this.
self.have_party_queue_window = False self.have_party_queue_window = False
self.quit_window: Any = None self.quit_window: Any = None
self.dismiss_wii_remotes_window_call: ( self.dismiss_wii_remotes_window_call: (Optional[Callable[[],
Optional[Callable[[], Any]]) = None Any]]) = None
self.value_test_defaults: dict = {} self.value_test_defaults: dict = {}
self.main_menu_window_refresh_check_count = 0 self.main_menu_window_refresh_check_count = 0
self.first_main_menu = True # FIXME: Move to mainmenu class. self.first_main_menu = True # FIXME: Move to mainmenu class.

View File

@ -32,9 +32,9 @@ class AppDelegate:
"""Defines handlers for high level app functionality.""" """Defines handlers for high level app functionality."""
def create_default_game_config_ui( def create_default_game_config_ui(
self, gameclass: Type[ba.GameActivity], self, gameclass: Type[ba.GameActivity], sessionclass: Type[ba.Session],
sessionclass: Type[ba.Session], config: Optional[Dict[str, Any]], config: Optional[Dict[str, Any]],
completion_call: Callable[[Optional[Dict[str, Any]]], None] completion_call: Callable[[Optional[Dict[str, Any]]], None]
) -> None: ) -> None:
"""Launch a UI to configure the given game config. """Launch a UI to configure the given game config.

View File

@ -202,7 +202,8 @@ class CoopGameActivity(GameActivity):
spaz.play_big_death_sound = True spaz.play_big_death_sound = True
return spaz return spaz
def _award_achievement(self, achievement_name: str, def _award_achievement(self,
achievement_name: str,
sound: bool = True) -> None: sound: bool = True) -> None:
"""Award an achievement. """Award an achievement.

View File

@ -207,9 +207,8 @@ class CoopSession(Session):
else: else:
self.end() self.end()
def _on_tournament_restart_menu_press(self, def _on_tournament_restart_menu_press(
resume_callback: Callable[[], Any] self, resume_callback: Callable[[], Any]) -> None:
) -> None:
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
from bastd.ui.tournamententry import TournamentEntryWindow from bastd.ui.tournamententry import TournamentEntryWindow
from ba._gameactivity import GameActivity from ba._gameactivity import GameActivity

View File

@ -48,9 +48,8 @@ class GameActivity(Activity):
@classmethod @classmethod
def create_config_ui( def create_config_ui(
cls, sessionclass: Type[ba.Session], cls, sessionclass: Type[ba.Session], config: Optional[Dict[str, Any]],
config: Optional[Dict[str, Any]], completion_call: Callable[[Optional[Dict[str, Any]]], None]
completion_call: Callable[[Optional[Dict[str, Any]]], None]
) -> None: ) -> None:
"""Launch an in-game UI to configure settings for a game type. """Launch an in-game UI to configure settings for a game type.
@ -171,8 +170,8 @@ class GameActivity(Activity):
return '' return ''
@classmethod @classmethod
def get_description_display_string(cls, sessiontype: Type[ba.Session] def get_description_display_string(
) -> ba.Lstr: cls, sessiontype: Type[ba.Session]) -> ba.Lstr:
"""Return a translated version of get_description(). """Return a translated version of get_description().
Sub-classes should override get_description(); not this. Sub-classes should override get_description(); not this.
@ -181,8 +180,9 @@ class GameActivity(Activity):
return Lstr(translate=('gameDescriptions', description)) return Lstr(translate=('gameDescriptions', description))
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
""" """
Called by the default ba.GameActivity.create_config_ui() Called by the default ba.GameActivity.create_config_ui()
implementation; should return a dict of config options to be presented implementation; should return a dict of config options to be presented
@ -643,8 +643,8 @@ class GameActivity(Activity):
callback=WeakCall( callback=WeakCall(
self._on_tournament_query_response)) self._on_tournament_query_response))
def _on_tournament_query_response(self, def _on_tournament_query_response(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
from ba._account import cache_tournament_info from ba._account import cache_tournament_info
if data is not None: if data is not None:
data_t = data['t'] # This used to be the whole payload. data_t = data['t'] # This used to be the whole payload.
@ -935,7 +935,9 @@ class GameActivity(Activity):
animate(combine, 'input3', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0}) animate(combine, 'input3', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0})
_ba.timer(5.0, tnode.delete) _ba.timer(5.0, tnode.delete)
def end(self, results: Any = None, delay: float = 0.0, def end(self,
results: Any = None,
delay: float = 0.0,
force: bool = False) -> None: force: bool = False) -> None:
from ba._gameresults import TeamGameResults from ba._gameresults import TeamGameResults

View File

@ -187,8 +187,8 @@ class TeamGameResults:
team = score[0]() team = score[0]()
assert team is not None assert team is not None
sval.append(team) sval.append(team)
results: List[Tuple[Optional[int], List[ba.Team]]] = list( results: List[Tuple[Optional[int],
winners.items()) List[ba.Team]]] = list(winners.items())
results.sort(reverse=not self._lower_is_better) results.sort(reverse=not self._lower_is_better)
# Also group the 'None' scores. # Also group the 'None' scores.
@ -200,8 +200,8 @@ class TeamGameResults:
# Add the Nones to the list (either as winners or losers # Add the Nones to the list (either as winners or losers
# depending on the rules). # depending on the rules).
if none_teams: if none_teams:
nones: List[Tuple[Optional[int], List[ba.Team]]] = [(None, nones: List[Tuple[Optional[int],
none_teams)] List[ba.Team]]] = [(None, none_teams)]
if self._none_is_winner: if self._none_is_winner:
results = nones + results results = nones + results
else: else:

View File

@ -171,11 +171,11 @@ class Level:
if campaign is None: if campaign is None:
raise Exception("level is not in a campaign") raise Exception("level is not in a campaign")
campaign_config = campaign.get_config_dict() campaign_config = campaign.get_config_dict()
val: Dict[str, Any] = campaign_config.setdefault( val: Dict[str,
self._name, { Any] = campaign_config.setdefault(self._name, {
'Rating': 0.0, 'Rating': 0.0,
'Complete': False 'Complete': False
}) })
assert isinstance(val, dict) assert isinstance(val, dict)
return val return val

View File

@ -47,10 +47,10 @@ class JoinInfo:
from ba._enums import SpecialChar from ba._enums import SpecialChar
can_switch_teams = (len(lobby.teams) > 1) can_switch_teams = (len(lobby.teams) > 1)
self._state = 0 self._state = 0
press_to_punch: Union[str, ba.Lstr] = _ba.charstr( press_to_punch: Union[str,
SpecialChar.LEFT_BUTTON) ba.Lstr] = _ba.charstr(SpecialChar.LEFT_BUTTON)
press_to_bomb: Union[str, ba.Lstr] = _ba.charstr( press_to_bomb: Union[str,
SpecialChar.RIGHT_BUTTON) ba.Lstr] = _ba.charstr(SpecialChar.RIGHT_BUTTON)
# If we have a keyboard, grab keys for punch and pickup. # If we have a keyboard, grab keys for punch and pickup.
# FIXME: This of course is only correct on the local device; # FIXME: This of course is only correct on the local device;

View File

@ -293,7 +293,8 @@ class Map(Actor):
# FIXME: this should be part of game; not map. # FIXME: this should be part of game; not map.
self._next_ffa_start_index = 0 self._next_ffa_start_index = 0
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
"""Return whether the provided point is near an edge of the map. """Return whether the provided point is near an edge of the map.
@ -306,7 +307,7 @@ class Map(Actor):
return False return False
def get_def_bound_box( def get_def_bound_box(
self, name: str self, name: str
) -> Optional[Tuple[float, float, float, float, float, float]]: ) -> Optional[Tuple[float, float, float, float, float, float]]:
"""Return a 6 member bounds tuple or None if it is not defined.""" """Return a 6 member bounds tuple or None if it is not defined."""
try: try:
@ -352,8 +353,8 @@ class Map(Actor):
pnt[2] + random.uniform(*z_range)) pnt[2] + random.uniform(*z_range))
return pnt return pnt
def get_ffa_start_position(self, players: Sequence[ba.Player] def get_ffa_start_position(
) -> Sequence[float]: self, players: Sequence[ba.Player]) -> Sequence[float]:
"""Return a random starting position in one of the FFA spawn areas. """Return a random starting position in one of the FFA spawn areas.
If a list of ba.Players is provided; the returned points will be If a list of ba.Players is provided; the returned points will be

View File

@ -337,8 +337,8 @@ class ITunesThread(threading.Thread):
self._commands.append(['GET_PLAYLISTS', callback]) self._commands.append(['GET_PLAYLISTS', callback])
self._commands_available.set() self._commands_available.set()
def _handle_get_playlists_command(self, target: Callable[[List[str]], None] def _handle_get_playlists_command(
) -> None: self, target: Callable[[List[str]], None]) -> None:
from ba._general import Call from ba._general import Call
try: try:
playlists = _ba.itunes_get_playlists() playlists = _ba.itunes_get_playlists()

View File

@ -158,19 +158,19 @@ class ServerCallThread(threading.Thread):
from_other_thread=True) from_other_thread=True)
def serverget(request: str, def serverget(
data: Dict[str, Any], request: str,
callback: Optional[ServerCallbackType] = None, data: Dict[str, Any],
response_type: ServerResponseType = ServerResponseType.JSON callback: Optional[ServerCallbackType] = None,
) -> None: response_type: ServerResponseType = ServerResponseType.JSON) -> None:
"""Make a call to the master server via a http GET.""" """Make a call to the master server via a http GET."""
ServerCallThread(request, 'get', data, callback, response_type).start() ServerCallThread(request, 'get', data, callback, response_type).start()
def serverput(request: str, def serverput(
data: Dict[str, Any], request: str,
callback: Optional[ServerCallbackType] = None, data: Dict[str, Any],
response_type: ServerResponseType = ServerResponseType.JSON callback: Optional[ServerCallbackType] = None,
) -> None: response_type: ServerResponseType = ServerResponseType.JSON) -> None:
"""Make a call to the master server via a http POST.""" """Make a call to the master server via a http POST."""
ServerCallThread(request, 'post', data, callback, response_type).start() ServerCallThread(request, 'post', data, callback, response_type).start()

View File

@ -67,7 +67,8 @@ def get_player_profile_icon(profilename: str) -> str:
def get_player_profile_colors( def get_player_profile_colors(
profilename: Optional[str], profiles: Dict[str, Dict[str, Any]] = None profilename: Optional[str],
profiles: Dict[str, Dict[str, Any]] = None
) -> Tuple[Tuple[float, float, float], Tuple[float, float, float]]: ) -> Tuple[Tuple[float, float, float], Tuple[float, float, float]]:
"""Given a profile, return colors for them.""" """Given a profile, return colors for them."""
bs_config = _ba.app.config bs_config = _ba.app.config

View File

@ -43,7 +43,8 @@ class EntityMixin:
class are accessible on the new type. class are accessible on the new type.
""" """
def __init__(self, d_data: Dict[str, Any] = None, def __init__(self,
d_data: Dict[str, Any] = None,
error: bool = False) -> None: error: bool = False) -> None:
super().__init__() super().__init__()
if not isinstance(self, CompoundValue): if not isinstance(self, CompoundValue):
@ -69,8 +70,8 @@ class EntityMixin:
assert isinstance(self, CompoundValue) assert isinstance(self, CompoundValue)
self.apply_fields_to_data(self.d_data, error=error) self.apply_fields_to_data(self.d_data, error=error)
def copy_data(self, def copy_data(self, target: Union[CompoundValue,
target: Union[CompoundValue, BoundCompoundValue]) -> None: BoundCompoundValue]) -> None:
"""Copy data from a target Entity or compound-value. """Copy data from a target Entity or compound-value.
This first verifies that the target has a matching set of fields This first verifies that the target has a matching set of fields

View File

@ -83,7 +83,9 @@ class Field(BaseField, Generic[T]):
class CompoundField(BaseField, Generic[TC]): class CompoundField(BaseField, Generic[TC]):
"""Field consisting of a single compound value.""" """Field consisting of a single compound value."""
def __init__(self, d_key: str, value: TC, def __init__(self,
d_key: str,
value: TC,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(d_key) super().__init__(d_key)
if __debug__ is True: if __debug__ is True:
@ -283,7 +285,9 @@ class CompoundListField(BaseField, Generic[TC]):
ie: mylist[10].fieldattr = 'foo' ie: mylist[10].fieldattr = 'foo'
""" """
def __init__(self, d_key: str, valuetype: TC, def __init__(self,
d_key: str,
valuetype: TC,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(d_key) super().__init__(d_key)
self.d_value = valuetype self.d_value = valuetype
@ -421,7 +425,8 @@ class CompoundDictField(BaseField, Generic[TK, TC]):
... ...
@overload @overload
def __get__(self, obj: Any, def __get__(self,
obj: Any,
cls: Any = None) -> BoundCompoundDictField[TK, TC]: cls: Any = None) -> BoundCompoundDictField[TK, TC]:
... ...

View File

@ -45,8 +45,8 @@ class BoundCompoundValue:
Allows access to its values through our own equivalent attributes. Allows access to its values through our own equivalent attributes.
""" """
def __init__(self, value: CompoundValue, def __init__(self, value: CompoundValue, d_data: Union[List[Any],
d_data: Union[List[Any], Dict[str, Any]]): Dict[str, Any]]):
self.d_value: CompoundValue self.d_value: CompoundValue
self.d_data: Union[List[Any], Dict[str, Any]] self.d_data: Union[List[Any], Dict[str, Any]]
# need to use base setters to avoid triggering our own overrides # need to use base setters to avoid triggering our own overrides
@ -374,8 +374,8 @@ class BoundCompoundListField(Generic[TC]):
class BoundCompoundDictField(Generic[TK, TC]): class BoundCompoundDictField(Generic[TK, TC]):
"""A CompoundDictField bound to its entity sub-data.""" """A CompoundDictField bound to its entity sub-data."""
def __init__(self, field: CompoundDictField[TK, TC], def __init__(self, field: CompoundDictField[TK, TC], d_data: Dict[Any,
d_data: Dict[Any, Any]): Any]):
self.d_field = field self.d_field = field
self.d_data = d_data self.d_data = d_data

View File

@ -146,7 +146,8 @@ class OptionalStringValue(SimpleValue[Optional[str]]):
class BoolValue(SimpleValue[bool]): class BoolValue(SimpleValue[bool]):
"""Value consisting of a single bool.""" """Value consisting of a single bool."""
def __init__(self, default: bool = False, def __init__(self,
default: bool = False,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(default, store_default, bool, (int, float)) super().__init__(default, store_default, bool, (int, float))
@ -246,7 +247,8 @@ class IntValue(SimpleValue[int]):
class OptionalIntValue(SimpleValue[Optional[int]]): class OptionalIntValue(SimpleValue[Optional[int]]):
"""Value consisting of a single int or None""" """Value consisting of a single int or None"""
def __init__(self, default: int = None, def __init__(self,
default: int = None,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(default, super().__init__(default,
store_default, store_default,
@ -257,7 +259,8 @@ class OptionalIntValue(SimpleValue[Optional[int]]):
class FloatValue(SimpleValue[float]): class FloatValue(SimpleValue[float]):
"""Value consisting of a single float.""" """Value consisting of a single float."""
def __init__(self, default: float = 0.0, def __init__(self,
default: float = 0.0,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(default, store_default, float, (bool, int)) super().__init__(default, store_default, float, (bool, int))
@ -265,7 +268,8 @@ class FloatValue(SimpleValue[float]):
class OptionalFloatValue(SimpleValue[Optional[float]]): class OptionalFloatValue(SimpleValue[Optional[float]]):
"""Value consisting of a single float or None.""" """Value consisting of a single float or None."""
def __init__(self, default: float = None, def __init__(self,
default: float = None,
store_default: bool = False) -> None: store_default: bool = False) -> None:
super().__init__(default, super().__init__(default,
store_default, store_default,

View File

@ -30,9 +30,9 @@ if TYPE_CHECKING:
from bafoundation.entity._support import BoundCompoundValue from bafoundation.entity._support import BoundCompoundValue
def diff_compound_values(obj1: Union[BoundCompoundValue, CompoundValue], def diff_compound_values(
obj2: Union[BoundCompoundValue, CompoundValue] obj1: Union[BoundCompoundValue, CompoundValue],
) -> str: obj2: Union[BoundCompoundValue, CompoundValue]) -> str:
"""Generate a string showing differences between two compound values. """Generate a string showing differences between two compound values.
Both must be associated with data and have the same set of fields. Both must be associated with data and have the same set of fields.
@ -108,8 +108,9 @@ def have_matching_fields(val1: CompoundValue, val2: CompoundValue) -> bool:
return val1.get_fields() == val2.get_fields() return val1.get_fields() == val2.get_fields()
def get_compound_value_and_data(obj: Union[BoundCompoundValue, CompoundValue] def get_compound_value_and_data(
) -> Tuple[CompoundValue, Any]: obj: Union[BoundCompoundValue, CompoundValue]
) -> Tuple[CompoundValue, Any]:
"""Return value and data for bound or unbound compound values.""" """Return value and data for bound or unbound compound values."""
# pylint: disable=cyclic-import # pylint: disable=cyclic-import
from bafoundation.entity._support import BoundCompoundValue from bafoundation.entity._support import BoundCompoundValue

View File

@ -145,8 +145,8 @@ if TYPE_CHECKING:
class _Call5Args(Generic[In1T, In2T, In3T, In4T, In5T, OutT]): class _Call5Args(Generic[In1T, In2T, In3T, In4T, In5T, OutT]):
"""Five argument variant of call wrapper""" """Five argument variant of call wrapper"""
def __init__(self, def __init__(self, _call: Callable[[In1T, In2T, In3T, In4T, In5T],
_call: Callable[[In1T, In2T, In3T, In4T, In5T], OutT]): OutT]):
... ...
def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T, def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T,
@ -156,9 +156,9 @@ if TYPE_CHECKING:
class _Call6Args(Generic[In1T, In2T, In3T, In4T, In5T, In6T, OutT]): class _Call6Args(Generic[In1T, In2T, In3T, In4T, In5T, In6T, OutT]):
"""Six argument variant of call wrapper""" """Six argument variant of call wrapper"""
def __init__( def __init__(self,
self, _call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T],
_call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T], OutT]): OutT]):
... ...
def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T, def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T,
@ -169,9 +169,8 @@ if TYPE_CHECKING:
"""Seven argument variant of call wrapper""" """Seven argument variant of call wrapper"""
def __init__( def __init__(
self, self, _call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T, In7T],
_call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T, In7T], OutT]):
OutT]):
... ...
def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T, def __call__(self, _arg1: In1T, _arg2: In2T, _arg3: In3T, _arg4: In4T,
@ -240,8 +239,9 @@ if TYPE_CHECKING:
# 3 arg call; no args bundled. # 3 arg call; no args bundled.
# noinspection PyPep8Naming # noinspection PyPep8Naming
@overload @overload
def Call(call: Callable[[In1T, In2T, In3T], OutT] def Call(
) -> _Call3Args[In1T, In2T, In3T, OutT]: call: Callable[[In1T, In2T, In3T], OutT]
) -> _Call3Args[In1T, In2T, In3T, OutT]:
... ...
# 4 arg call; 4 args bundled. # 4 arg call; 4 args bundled.
@ -254,17 +254,17 @@ if TYPE_CHECKING:
# 5 arg call; 5 args bundled. # 5 arg call; 5 args bundled.
# noinspection PyPep8Naming # noinspection PyPep8Naming
@overload @overload
def Call(call: Callable[[In1T, In2T, In3T, In4T, In5T], OutT], arg1: In1T, def Call(call: Callable[[In1T, In2T, In3T, In4T, In5T],
arg2: In2T, arg3: In3T, arg4: In4T, OutT], arg1: In1T, arg2: In2T, arg3: In3T,
arg5: In5T) -> _CallNoArgs[OutT]: arg4: In4T, arg5: In5T) -> _CallNoArgs[OutT]:
... ...
# 6 arg call; 6 args bundled. # 6 arg call; 6 args bundled.
# noinspection PyPep8Naming # noinspection PyPep8Naming
@overload @overload
def Call(call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T], OutT], def Call(call: Callable[[In1T, In2T, In3T, In4T, In5T, In6T],
arg1: In1T, arg2: In2T, arg3: In3T, arg4: In4T, arg5: In5T, OutT], arg1: In1T, arg2: In2T, arg3: In3T,
arg6: In6T) -> _CallNoArgs[OutT]: arg4: In4T, arg5: In5T, arg6: In6T) -> _CallNoArgs[OutT]:
... ...
# 7 arg call; 7 args bundled. # 7 arg call; 7 args bundled.

View File

@ -60,8 +60,9 @@ class DispatchMethodWrapper(Generic[TARG, TRET]):
# noinspection PyTypeHints, PyProtectedMember # noinspection PyTypeHints, PyProtectedMember
def dispatchmethod(func: Callable[[Any, TARG], TRET] def dispatchmethod(
) -> DispatchMethodWrapper[TARG, TRET]: func: Callable[[Any, TARG], TRET]
) -> DispatchMethodWrapper[TARG, TRET]:
"""A variation of functools.singledispatch for methods.""" """A variation of functools.singledispatch for methods."""
from functools import singledispatch, update_wrapper from functools import singledispatch, update_wrapper
origwrapper: Any = singledispatch(func) origwrapper: Any = singledispatch(func)
@ -224,8 +225,9 @@ class ValueDispatcher(Generic[TVAL, TRET]):
return partial(self._add_handler, value) return partial(self._add_handler, value)
def valuedispatch1arg(call: Callable[[TVAL, TARG], TRET] def valuedispatch1arg(
) -> ValueDispatcher1Arg[TVAL, TARG, TRET]: call: Callable[[TVAL, TARG], TRET]
) -> ValueDispatcher1Arg[TVAL, TARG, TRET]:
"""Like valuedispatch but for functions taking an extra argument.""" """Like valuedispatch but for functions taking an extra argument."""
return ValueDispatcher1Arg(call) return ValueDispatcher1Arg(call)

View File

@ -98,10 +98,12 @@ class CoopJoiningActivity(JoiningActivity):
spacing = 25 spacing = 25
delay_inc = 0.1 delay_inc = 0.1
def _add_t(text: Union[str, ba.Lstr], def _add_t(
h_offs: float = 0.0, text: Union[str, ba.Lstr],
scale: float = 1.0, h_offs: float = 0.0,
color: Sequence[float] = (1.0, 1.0, 1.0, 0.46)) -> None: scale: float = 1.0,
color: Sequence[float] = (1.0, 1.0, 1.0, 0.46)
) -> None:
Text(text, Text(text,
scale=scale * 0.76, scale=scale * 0.76,
h_align='left', h_align='left',

View File

@ -118,8 +118,8 @@ class TeamsScoreScreenActivity(ScoreScreenActivity):
assert self.stats assert self.stats
valid_players = list(self.stats.get_records().items()) valid_players = list(self.stats.get_records().items())
def _get_player_score_set_entry(player: ba.Player def _get_player_score_set_entry(
) -> Optional[PlayerRecord]: player: ba.Player) -> Optional[PlayerRecord]:
for p_rec in valid_players: for p_rec in valid_players:
# PyCharm incorrectly thinks valid_players is a List[str] # PyCharm incorrectly thinks valid_players is a List[str]
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences

View File

@ -99,8 +99,10 @@ class OnScreenTimer(ba.Actor):
self.inputnode.timemax = endtime_ms - self._starttime self.inputnode.timemax = endtime_ms - self._starttime
def getstarttime(self, timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS def getstarttime(
) -> Union[int, float]: self,
timeformat: ba.TimeFormat = ba.TimeFormat.SECONDS
) -> Union[int, float]:
"""Return the sim-time when start() was called. """Return the sim-time when start() was called.
Time will be returned in seconds if timeformat is SECONDS or Time will be returned in seconds if timeformat is SECONDS or

View File

@ -243,8 +243,8 @@ class Spaz(ba.Actor):
self._bomb_held = False self._bomb_held = False
if self.default_shields: if self.default_shields:
self.equip_shields() self.equip_shields()
self._dropped_bomb_callbacks: List[ self._dropped_bomb_callbacks: List[Callable[[Spaz, ba.Actor],
Callable[[Spaz, ba.Actor], Any]] = [] Any]] = []
self._score_text: Optional[ba.Node] = None self._score_text: Optional[ba.Node] = None
self._score_text_hide_timer: Optional[ba.Timer] = None self._score_text_hide_timer: Optional[ba.Timer] = None
@ -262,8 +262,8 @@ class Spaz(ba.Actor):
self.punch_callback = None self.punch_callback = None
self.pick_up_powerup_callback = None self.pick_up_powerup_callback = None
def add_dropped_bomb_callback(self, call: Callable[[Spaz, ba.Actor], Any] def add_dropped_bomb_callback(
) -> None: self, call: Callable[[Spaz, ba.Actor], Any]) -> None:
""" """
Add a call to be run whenever this Spaz drops a bomb. Add a call to be run whenever this Spaz drops a bomb.
The spaz and the newly-dropped bomb are passed as arguments. The spaz and the newly-dropped bomb are passed as arguments.

View File

@ -179,8 +179,8 @@ class SpazBot(basespaz.Spaz):
assert mval is not None assert mval is not None
return mval return mval
def _get_target_player_pt(self def _get_target_player_pt(
) -> Tuple[Optional[ba.Vec3], Optional[ba.Vec3]]: self) -> Tuple[Optional[ba.Vec3], Optional[ba.Vec3]]:
"""Returns the position and velocity of our target. """Returns the position and velocity of our target.
Both values will be None in the case of no target. Both values will be None in the case of no target.

View File

@ -33,9 +33,9 @@ class AppDelegate(ba.AppDelegate):
"""Defines handlers for high level app functionality.""" """Defines handlers for high level app functionality."""
def create_default_game_config_ui( def create_default_game_config_ui(
self, gameclass: Type[ba.GameActivity], self, gameclass: Type[ba.GameActivity], sessionclass: Type[ba.Session],
sessionclass: Type[ba.Session], config: Optional[Dict[str, Any]], config: Optional[Dict[str, Any]],
completion_call: Callable[[Optional[Dict[str, Any]]], Any] completion_call: Callable[[Optional[Dict[str, Any]]], Any]
) -> None: ) -> None:
"""(internal)""" """(internal)"""

View File

@ -56,8 +56,9 @@ class AssaultGame(ba.TeamGameActivity):
return ba.getmaps('team_flag') return ba.getmaps('team_flag')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [('Score to Win', {'min_value': 1, 'default': 3}), return [('Score to Win', {'min_value': 1, 'default': 3}),
('Time Limit', { ('Time Limit', {
'choices': [('None', 0), ('1 Minute', 60), 'choices': [('None', 0), ('1 Minute', 60),

View File

@ -89,8 +89,9 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
return ba.getmaps('team_flag') return ba.getmaps('team_flag')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [ return [
('Score to Win', {'min_value': 1, 'default': 3}), ('Score to Win', {'min_value': 1, 'default': 3}),
('Flag Touch Return Time', { ('Flag Touch Return Time', {

View File

@ -62,8 +62,9 @@ class ChosenOneGame(ba.TeamGameActivity):
return ba.getmaps('keep_away') return ba.getmaps('keep_away')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [("Chosen One Time", { return [("Chosen One Time", {
'min_value': 10, 'min_value': 10,
'default': 30, 'default': 30,

View File

@ -77,8 +77,9 @@ class ConquestGame(ba.TeamGameActivity):
return ba.getmaps("conquest") return ba.getmaps("conquest")
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [ return [
("Time Limit", { ("Time Limit", {
'choices': [('None', 0), ('1 Minute', 60), 'choices': [('None', 0), ('1 Minute', 60),

View File

@ -56,8 +56,9 @@ class DeathMatchGame(ba.TeamGameActivity):
return ba.getmaps("melee") return ba.getmaps("melee")
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
settings: List[Tuple[str, Dict[str, Any]]] = [ settings: List[Tuple[str, Dict[str, Any]]] = [
("Kills to Win Per Player", { ("Kills to Win Per Player", {
'min_value': 1, 'min_value': 1,

View File

@ -67,8 +67,9 @@ class EasterEggHuntGame(ba.TeamGameActivity):
or issubclass(sessiontype, ba.FreeForAllSession)) or issubclass(sessiontype, ba.FreeForAllSession))
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [("Pro Mode", {'default': False})] return [("Pro Mode", {'default': False})]
def __init__(self, settings: Dict[str, Any]): def __init__(self, settings: Dict[str, Any]):

View File

@ -193,8 +193,9 @@ class EliminationGame(ba.TeamGameActivity):
return ba.getmaps("melee") return ba.getmaps("melee")
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
settings: List[Tuple[str, Dict[str, Any]]] = [ settings: List[Tuple[str, Dict[str, Any]]] = [
("Lives Per Player", { ("Lives Per Player", {
'default': 1, 'min_value': 1, 'default': 1, 'min_value': 1,

View File

@ -87,8 +87,9 @@ class FootballTeamGame(ba.TeamGameActivity):
return ba.getmaps('football') return ba.getmaps('football')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [ return [
("Score to Win", { ("Score to Win", {
'min_value': 7, 'min_value': 7,

View File

@ -126,8 +126,9 @@ class HockeyGame(ba.TeamGameActivity):
return ba.getmaps('hockey') return ba.getmaps('hockey')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [ return [
("Score to Win", { ("Score to Win", {
'min_value': 1, 'default': 1, 'increment': 1 'min_value': 1, 'default': 1, 'increment': 1

View File

@ -67,8 +67,9 @@ class KeepAwayGame(ba.TeamGameActivity):
return ba.getmaps('keep_away') return ba.getmaps('keep_away')
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [ return [
("Hold Time", { ("Hold Time", {
'min_value': 10, 'min_value': 10,

View File

@ -68,8 +68,9 @@ class KingOfTheHillGame(ba.TeamGameActivity):
return ba.getmaps("king_of_the_hill") return ba.getmaps("king_of_the_hill")
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [("Hold Time", { return [("Hold Time", {
'min_value': 10, 'min_value': 10,
'default': 30, 'default': 30,

View File

@ -63,8 +63,9 @@ class MeteorShowerGame(ba.TeamGameActivity):
return ['Rampage'] return ['Rampage']
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [("Epic Mode", {'default': False})] return [("Epic Mode", {'default': False})]
# We support teams, free-for-all, and co-op sessions. # We support teams, free-for-all, and co-op sessions.

View File

@ -87,8 +87,9 @@ class RaceGame(ba.TeamGameActivity):
return ba.getmaps("race") return ba.getmaps("race")
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
settings: List[Tuple[str, Dict[str, Any]]] = [ settings: List[Tuple[str, Dict[str, Any]]] = [
("Laps", { ("Laps", {
'min_value': 1, 'min_value': 1,

View File

@ -822,9 +822,9 @@ class RunaroundGame(ba.CoopGameActivity):
elif path == 6: elif path == 6:
this_target_point_s *= 0.7 this_target_point_s *= 0.7
def _add_defender( def _add_defender(defender_type: Tuple[Type[spazbot.SpazBot],
defender_type: Tuple[Type[spazbot.SpazBot], float], float],
pnt: str) -> Tuple[float, Dict[str, Any]]: pnt: str) -> Tuple[float, Dict[str, Any]]:
# FIXME: should look into this warning # FIXME: should look into this warning
# pylint: disable=cell-var-from-loop # pylint: disable=cell-var-from-loop
return this_target_point_s * defender_type[1], { return this_target_point_s * defender_type[1], {

View File

@ -60,8 +60,9 @@ class TargetPracticeGame(ba.TeamGameActivity):
or issubclass(sessiontype, ba.TeamBaseSession)) or issubclass(sessiontype, ba.TeamBaseSession))
@classmethod @classmethod
def get_settings(cls, sessiontype: Type[ba.Session] def get_settings(
) -> List[Tuple[str, Dict[str, Any]]]: cls,
sessiontype: Type[ba.Session]) -> List[Tuple[str, Dict[str, Any]]]:
return [("Target Count", { return [("Target Count", {
'min_value': 1, 'min_value': 1,
'default': 3 'default': 3

View File

@ -171,7 +171,8 @@ class FootballStadium(ba.Map):
gnode.vr_camera_offset = (0, -0.8, -1.1) gnode.vr_camera_offset = (0, -0.8, -1.1)
gnode.vr_near_clip = 0.5 gnode.vr_near_clip = 0.5
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
box_position = self.defs.boxes['edge_box'][0:3] box_position = self.defs.boxes['edge_box'][0:3]
box_scale = self.defs.boxes['edge_box'][6:9] box_scale = self.defs.boxes['edge_box'][6:9]
@ -814,7 +815,8 @@ class DoomShroom(ba.Map):
gnode.vignette_outer = (0.76, 0.76, 0.76) gnode.vignette_outer = (0.76, 0.76, 0.76)
gnode.vignette_inner = (0.95, 0.95, 0.99) gnode.vignette_inner = (0.95, 0.95, 0.99)
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
xpos = point.x xpos = point.x
zpos = point.z zpos = point.z
@ -1162,7 +1164,8 @@ class TowerD(ba.Map):
gnode.vignette_outer = (0.7, 0.73, 0.7) gnode.vignette_outer = (0.7, 0.73, 0.7)
gnode.vignette_inner = (0.95, 0.95, 0.95) gnode.vignette_inner = (0.95, 0.95, 0.95)
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
# see if we're within edge_box # see if we're within edge_box
boxes = self.defs.boxes boxes = self.defs.boxes
@ -1453,7 +1456,8 @@ class Courtyard(ba.Map):
gnode.vignette_outer = (0.6, 0.6, 0.64) gnode.vignette_outer = (0.6, 0.6, 0.64)
gnode.vignette_inner = (0.95, 0.95, 0.93) gnode.vignette_inner = (0.95, 0.95, 0.93)
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
# count anything off our ground level as safe (for our platforms) # count anything off our ground level as safe (for our platforms)
# see if we're within edge_box # see if we're within edge_box
@ -1549,7 +1553,8 @@ class Rampage(ba.Map):
gnode.vignette_outer = (0.62, 0.64, 0.69) gnode.vignette_outer = (0.62, 0.64, 0.69)
gnode.vignette_inner = (0.97, 0.95, 0.93) gnode.vignette_inner = (0.97, 0.95, 0.93)
def is_point_near_edge(self, point: ba.Vec3, def is_point_near_edge(self,
point: ba.Vec3,
running: bool = False) -> bool: running: bool = False) -> bool:
box_position = self.defs.boxes['edge_box'][0:3] box_position = self.defs.boxes['edge_box'][0:3]
box_scale = self.defs.boxes['edge_box'][6:9] box_scale = self.defs.boxes['edge_box'][6:9]

View File

@ -1057,7 +1057,8 @@ class AccountSettingsWindow(ba.OldWindow):
ba.buttonwidget(edit=self._sign_out_button, ba.buttonwidget(edit=self._sign_out_button,
label=ba.Lstr(resource=self._r + '.signingOutText')) label=ba.Lstr(resource=self._r + '.signingOutText'))
def _sign_in_press(self, account_type: str, def _sign_in_press(self,
account_type: str,
show_test_warning: bool = True) -> None: show_test_warning: bool = True) -> None:
del show_test_warning # unused del show_test_warning # unused
_ba.sign_in(account_type) _ba.sign_in(account_type)

View File

@ -36,8 +36,8 @@ class ContinuesWindow(ba.OldWindow):
"""A window to continue a game.""" """A window to continue a game."""
def __init__(self, activity: ba.Activity, cost: int, def __init__(self, activity: ba.Activity, cost: int,
continue_call: Callable[[], Any], continue_call: Callable[[], Any], cancel_call: Callable[[],
cancel_call: Callable[[], Any]): Any]):
self._activity = weakref.ref(activity) self._activity = weakref.ref(activity)
self._cost = cost self._cost = cost
self._continue_call = continue_call self._continue_call = continue_call

View File

@ -569,8 +569,8 @@ class CoopBrowserWindow(ba.OldWindow):
('' + str(free_tries_remaining))), ('' + str(free_tries_remaining))),
color=(0.6, 0.6, 0.6, 1)) color=(0.6, 0.6, 0.6, 1))
def _on_tournament_query_response(self, def _on_tournament_query_response(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
from ba.internal import cache_tournament_info from ba.internal import cache_tournament_info
app = ba.app app = ba.app
if data is not None: if data is not None:

View File

@ -1351,8 +1351,8 @@ class GatherWindow(ba.OldWindow):
ba.textwidget(edit=self._internet_host_max_party_size_value, ba.textwidget(edit=self._internet_host_max_party_size_value,
text=str(val)) text=str(val))
def _on_public_party_query_result(self, result: Optional[Dict[str, Any]] def _on_public_party_query_result(
) -> None: self, result: Optional[Dict[str, Any]]) -> None:
with ba.Context('ui'): with ba.Context('ui'):
# any time we get any result at all, kill our loading status # any time we get any result at all, kill our loading status
status_text = self._internet_join_status_text status_text = self._internet_join_status_text
@ -1806,9 +1806,8 @@ class GatherWindow(ba.OldWindow):
fallback_resource='gatherWindow.stopAdvertisingText'), fallback_resource='gatherWindow.stopAdvertisingText'),
on_activate_call=self._on_stop_internet_advertising_press) on_activate_call=self._on_stop_internet_advertising_press)
def _on_public_party_accessible_response(self, def _on_public_party_accessible_response(
data: Optional[Dict[str, Any]] self, data: Optional[Dict[str, Any]]) -> None:
) -> None:
# If we've got status text widgets, update them. # If we've got status text widgets, update them.
text = self._internet_host_status_text text = self._internet_host_status_text
if text: if text:

View File

@ -230,8 +230,8 @@ class LeagueRankButton:
ba.print_exception('error doing smooth update') ba.print_exception('error doing smooth update')
self._smooth_update_timer = None self._smooth_update_timer = None
def _update_for_league_rank_data(self, def _update_for_league_rank_data(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
from ba.internal import get_league_rank_points from ba.internal import get_league_rank_points
@ -340,8 +340,8 @@ class LeagueRankButton:
ba.textwidget(edit=self._title_text, text=txt, color=t_color) ba.textwidget(edit=self._title_text, text=txt, color=t_color)
ba.textwidget(edit=self._value_text, text=status_text) ba.textwidget(edit=self._value_text, text=status_text)
def _on_power_ranking_query_response(self, data: Optional[Dict[str, Any]] def _on_power_ranking_query_response(
) -> None: self, data: Optional[Dict[str, Any]]) -> None:
from ba.internal import cache_league_rank_data from ba.internal import cache_league_rank_data
self._doing_power_ranking_query = False self._doing_power_ranking_query = False
cache_league_rank_data(data) cache_league_rank_data(data)

View File

@ -210,8 +210,8 @@ class LeagueRankWindow(ba.OldWindow):
else: else:
ba.playsound(ba.getsound('error')) ba.playsound(ba.getsound('error'))
def _on_power_ranking_query_response(self, data: Optional[Dict[str, Any]] def _on_power_ranking_query_response(
) -> None: self, data: Optional[Dict[str, Any]]) -> None:
from ba.internal import cache_league_rank_data from ba.internal import cache_league_rank_data
self._doing_power_ranking_query = False self._doing_power_ranking_query = False
# important: *only* cache this if we requested the current season.. # important: *only* cache this if we requested the current season..
@ -607,8 +607,8 @@ class LeagueRankWindow(ba.OldWindow):
'/highscores?list=powerRankings&v=2' + league_str + '/highscores?list=powerRankings&v=2' + league_str +
season_str + '&player=' + our_login_id) season_str + '&player=' + our_login_id)
def _update_for_league_rank_data(self, def _update_for_league_rank_data(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-locals # pylint: disable=too-many-locals

View File

@ -400,8 +400,9 @@ class MainMenuWindow(ba.OldWindow):
size=(0, 0), size=(0, 0),
scale=3.0 * t_scale) scale=3.0 * t_scale)
def _refresh_not_in_game(self, positions: List[Tuple[float, float, float]] def _refresh_not_in_game(
) -> Tuple[float, float, float]: self, positions: List[Tuple[float, float, float]]
) -> Tuple[float, float, float]:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
@ -654,8 +655,9 @@ class MainMenuWindow(ba.OldWindow):
self._tdelay += self._t_delay_inc self._tdelay += self._t_delay_inc
return h, v, scale return h, v, scale
def _refresh_in_game(self, positions: List[Tuple[float, float, float]] def _refresh_in_game(
) -> Tuple[float, float, float]: self, positions: List[Tuple[float, float, float]]
) -> Tuple[float, float, float]:
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
# pylint: disable=too-many-statements # pylint: disable=too-many-statements

View File

@ -538,8 +538,8 @@ class EditProfileWindow(ba.OldWindow):
tint_color=self._color, tint_color=self._color,
tint2_color=self._highlight) tint2_color=self._highlight)
def _make_picker(self, picker_type: str, def _make_picker(self, picker_type: str, origin: Tuple[float,
origin: Tuple[float, float]) -> None: float]) -> None:
from bastd.ui import colorpicker from bastd.ui import colorpicker
if picker_type == 'color': if picker_type == 'color':
initial_color = self._color initial_color = self._color

View File

@ -769,13 +769,13 @@ class AwaitGamepadInputWindow(ba.OldWindow):
"""Window for capturing a gamepad button press.""" """Window for capturing a gamepad button press."""
def __init__( def __init__(
self, self,
gamepad: ba.InputDevice, gamepad: ba.InputDevice,
button: str, button: str,
callback: Callable[[str, Dict[str, Any], AwaitGamepadInputWindow], callback: Callable[[str, Dict[str, Any], AwaitGamepadInputWindow],
Any], Any],
message: ba.Lstr = None, message: ba.Lstr = None,
message2: ba.Lstr = None): message2: ba.Lstr = None):
if message is None: if message is None:
print('AwaitGamepadInputWindow message is None!') print('AwaitGamepadInputWindow message is None!')
message = ba.Lstr( message = ba.Lstr(

View File

@ -348,12 +348,12 @@ class GamepadAdvancedSettingsWindow(ba.OldWindow):
for child in self._subcontainer.get_children(): for child in self._subcontainer.get_children():
ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30) ba.widget(edit=child, show_buffer_bottom=30, show_buffer_top=30)
def _capture_button(self, def _capture_button(
pos: Tuple[float, float], self,
name: ba.Lstr, pos: Tuple[float, float],
control: str, name: ba.Lstr,
message: Optional[ba.Lstr] = None control: str,
) -> Tuple[ba.Widget, ba.Widget]: message: Optional[ba.Lstr] = None) -> Tuple[ba.Widget, ba.Widget]:
if message is None: if message is None:
message = ba.Lstr(resource=self._parent_window.get_r() + message = ba.Lstr(resource=self._parent_window.get_r() +
'.pressAnyButtonText') '.pressAnyButtonText')
@ -416,17 +416,17 @@ class GamepadAdvancedSettingsWindow(ba.OldWindow):
ba.textwidget(edit=self._textwidgets[control], ba.textwidget(edit=self._textwidgets[control],
text=self._parent_window.get_control_value_name(control)) text=self._parent_window.get_control_value_name(control))
def _config_value_editor(self, def _config_value_editor(
name: ba.Lstr, self,
control: str, name: ba.Lstr,
position: Tuple[float, float], control: str,
min_val: float = 0.0, position: Tuple[float, float],
max_val: float = 100.0, min_val: float = 0.0,
increment: float = 1.0, max_val: float = 100.0,
change_sound: bool = True, increment: float = 1.0,
x_offset: float = 0.0, change_sound: bool = True,
displayname: ba.Lstr = None x_offset: float = 0.0,
) -> Tuple[ba.Widget, ba.Widget]: displayname: ba.Lstr = None) -> Tuple[ba.Widget, ba.Widget]:
if displayname is None: if displayname is None:
displayname = name displayname = name

View File

@ -445,7 +445,8 @@ class StoreBrowserWindow(ba.OldWindow):
resource='getTicketsWindow.unavailableText'), resource='getTicketsWindow.unavailableText'),
color=(1, 0, 0)) color=(1, 0, 0))
def _do_purchase_check(self, item: str, def _do_purchase_check(self,
item: str,
is_ticket_purchase: bool = False) -> None: is_ticket_purchase: bool = False) -> None:
from ba.internal import serverget from ba.internal import serverget

View File

@ -308,8 +308,8 @@ class TournamentEntryWindow(popup.PopupWindow):
self._update() self._update()
self._restore_state() self._restore_state()
def _on_tournament_query_response(self, def _on_tournament_query_response(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
from ba.internal import cache_tournament_info from ba.internal import cache_tournament_info
self._running_query = False self._running_query = False
if data is not None: if data is not None:

View File

@ -124,8 +124,8 @@ class TournamentScoresWindow(popup_ui.PopupWindow):
callback=ba.WeakCall( callback=ba.WeakCall(
self._on_tournament_query_response)) self._on_tournament_query_response))
def _on_tournament_query_response(self, def _on_tournament_query_response(self, data: Optional[Dict[str,
data: Optional[Dict[str, Any]]) -> None: Any]]) -> None:
if data is not None: if data is not None:
# this used to be the whole payload # this used to be the whole payload
data_t: List[Dict[str, Any]] = data['t'] data_t: List[Dict[str, Any]] = data['t']

View File

@ -123,8 +123,8 @@ def _get_default_config() -> Dict[str, Any]:
def _run_process_until_exit(process: subprocess.Popen, def _run_process_until_exit(process: subprocess.Popen,
input_commands: Sequence[str], input_commands: Sequence[str],
restart_minutes: int, restart_minutes: int, config: Dict[str,
config: Dict[str, Any]) -> None: Any]) -> None:
# So we pass our initial config. # So we pass our initial config.
config_dirty = True config_dirty = True

View File

@ -25,7 +25,8 @@
"bs_mapdefs_football_stadium", "bs_mapdefs_football_stadium",
"bs_mapdefs_tower_d", "bs_mapdefs_tower_d",
"bs_mapdefs_hockey_stadium", "bs_mapdefs_hockey_stadium",
"bs_mapdefs_roundabout" "bs_mapdefs_roundabout",
"yaml"
], ],
"python_paths": [ "python_paths": [
"assets/src/data/scripts", "assets/src/data/scripts",

View File

@ -1,6 +1,6 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND --> <!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
<!--DOCSHASH=51c5d02115be6a67ed7833c3ec13432e--> <!--DOCSHASH=f60857a13d4c5fd4ba30988f084e00a4-->
<h4><em>last updated on 2019-11-21 for Ballistica version 1.5.0 build 20001</em></h4> <h4><em>last updated on 2019-11-29 for Ballistica version 1.5.0 build 20001</em></h4>
<p>This page documents the Python classes and functions in the 'ba' module, <p>This page documents the Python classes and functions in the 'ba' module,
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p> which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
<hr> <hr>

View File

@ -27,13 +27,15 @@ from __future__ import annotations
import sys import sys
import os import os
from enum import Enum
from pathlib import Path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import urllib.request import urllib.request
import urllib.parse import urllib.parse
import urllib.error import urllib.error
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path
import json import json
import subprocess
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Optional, Dict, Any from typing import Optional, Dict, Any
@ -60,8 +62,12 @@ CLREND = '\033[0m' # End.
CMD_LOGIN = 'login' CMD_LOGIN = 'login'
CMD_LOGOUT = 'logout' CMD_LOGOUT = 'logout'
CMD_PUTASSET = 'putasset'
CMD_HELP = 'help' CMD_HELP = 'help'
ASSET_PATH_VALID_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_'
ASSET_PATH_MAX_LENGTH = 128
@dataclass @dataclass
class StateData: class StateData:
@ -81,6 +87,74 @@ class CleanError(Exception):
"""Exception resulting in a clean error string print and exit.""" """Exception resulting in a clean error string print and exit."""
class AssetType(Enum):
"""Types for asset files."""
TEXTURE = 'texture'
SOUND = 'sound'
class Asset:
"""Data for a single asset."""
def __init__(self, assettype: AssetType) -> None:
self.assettype = assettype
print('INITING ASSET OF TYPE', assettype)
def validate_asset_path(path: str) -> None:
"""Throw an exception on an invalid asset path."""
names = path.split('/')
for name in names:
if not name:
raise CleanError(f'Found empty component in asset path "{path}".')
for char in name:
if char not in ASSET_PATH_VALID_CHARS:
raise CleanError(
f'Found invalid char "{char}" in asset path "{path}".')
class AssetBundle:
"""Data for local or remote asset bundles."""
def __init__(self) -> None:
self.assets: Dict[str, Asset] = {}
@classmethod
def load_from_disk(cls, path: Path) -> AssetBundle:
"""Load an asset bundle from an existing one on disk."""
import yaml
indexfilename = 'assetbundle.yaml'
bundle = AssetBundle()
if not path.is_dir():
raise CleanError(f'Directory not found: "{path}"')
with open(Path(path, indexfilename)) as infile:
index = yaml.safe_load(infile)
if not isinstance(index, dict):
raise CleanError(f'Root dict not found in {indexfilename}')
assets = index.get('assets')
if not isinstance(assets, dict):
raise CleanError(f'No "assets" dict found in {indexfilename}')
for assetpath, assetdata in assets.items():
validate_asset_path(assetpath)
if len(assetpath) > ASSET_PATH_MAX_LENGTH:
raise CleanError(f'Asset path is too long: "{assetpath}"')
if not isinstance(assetdata, dict):
raise CleanError(
f'Invalid asset data for {assetpath} in {indexfilename}')
assettypestr = assetdata.get('type')
if not isinstance(assettypestr, str):
raise CleanError(
f'Invalid asset type for {assetpath} in {indexfilename}')
assettype = AssetType(assettypestr)
print('looking at', assetpath, assetdata)
bundle.assets[assetpath] = Asset(assettype)
return bundle
class App: class App:
"""Context for a run of the tool.""" """Context for a run of the tool."""
@ -95,6 +169,14 @@ class App:
raise CleanError( raise CleanError(
'This tool must be run from ballistica project root.') 'This tool must be run from ballistica project root.')
# Also run project prereqs checks so we can hopefully inform the user
# of missing python modules/etc. instead of just failing cryptically.
try:
subprocess.run(['make', '--quiet', 'prereqs'], check=True)
except subprocess.CalledProcessError:
raise CleanError('"make prereqs" check failed. '
'Install missing requirements and try again.')
self._load_cache() self._load_cache()
if len(sys.argv) < 2: if len(sys.argv) < 2:
@ -106,6 +188,8 @@ class App:
self.do_login() self.do_login()
elif cmd == CMD_LOGOUT: elif cmd == CMD_LOGOUT:
self.do_logout() self.do_logout()
elif cmd == CMD_PUTASSET:
self.do_putasset()
else: else:
# For all other commands, simply pass them to the server verbatim. # For all other commands, simply pass them to the server verbatim.
self.do_misc_command() self.do_misc_command()
@ -182,6 +266,15 @@ class App:
self._state.login_token = None self._state.login_token = None
print(f'{CLRGRN}Cloudtool is now logged out.{CLREND}') print(f'{CLRGRN}Cloudtool is now logged out.{CLREND}')
def do_putasset(self) -> None:
"""Run a putasset command."""
if len(sys.argv) != 3:
raise CleanError('Expected a path to an assetpackage directory.')
path = Path(sys.argv[2])
_bundle = AssetBundle.load_from_disk(path)
def do_misc_command(self) -> None: def do_misc_command(self) -> None:
"""Run a miscellaneous command.""" """Run a miscellaneous command."""

View File

@ -504,7 +504,8 @@ def _filter_module_name(mpath: str) -> str:
return mpath[:-9] if mpath.endswith('.__init__') else mpath return mpath[:-9] if mpath.endswith('.__init__') else mpath
def runmypy(filenames: List[str], full: bool = False, def runmypy(filenames: List[str],
full: bool = False,
check: bool = True) -> None: check: bool = True) -> None:
"""Run MyPy on provided filenames.""" """Run MyPy on provided filenames."""
args = [ args = [

View File

@ -293,7 +293,7 @@ def gen_fulltest_buildfile_linux() -> None:
dayoffset = datetime.datetime.now().timetuple().tm_yday dayoffset = datetime.datetime.now().timetuple().tm_yday
targets = ['build', 'server-build'] targets = ['build', 'server-build']
linflav = 'LINUX_FLAVOR=linux64-u19s' linflav = 'LINUX_FLAVOR=u18s'
lines = [] lines = []
for target in targets: for target in targets:
lines.append(f'{linflav} make linux-{target}') lines.append(f'{linflav} make linux-{target}')
@ -714,7 +714,7 @@ def checkenv() -> None:
for modname, minver, packagename in [ for modname, minver, packagename in [
('pylint', [2, 4, 4], None), ('pylint', [2, 4, 4], None),
('mypy', [0, 740], None), ('mypy', [0, 740], None),
('yapf', [0, 28, 0], None), ('yapf', [0, 29, 0], None),
('typing_extensions', None, None), ('typing_extensions', None, None),
('pytz', None, None), ('pytz', None, None),
('yaml', None, 'PyYAML'), ('yaml', None, 'PyYAML'),