From e02f1dbe52ea923b261d7afe05bac1029442bab0 Mon Sep 17 00:00:00 2001 From: Ayush Saini <36878972+imayushsaini@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:00:00 +0530 Subject: [PATCH] syncing 1.7.60 ballistica binary --- dist/ba_data/python/babase/__init__.py | 63 +- dist/ba_data/python/babase/_analytics.py | 73 ++ dist/ba_data/python/babase/_app.py | 21 +- dist/ba_data/python/babase/_appcomponent.py | 1 + dist/ba_data/python/babase/_appconfig.py | 1 + dist/ba_data/python/babase/_appintent.py | 1 + dist/ba_data/python/babase/_appmode.py | 1 + .../ba_data/python/babase/_appmodeselector.py | 1 + dist/ba_data/python/babase/_appsubsystem.py | 2 +- dist/ba_data/python/babase/_apputils.py | 1 + dist/ba_data/python/babase/_cloud.py | 1 + dist/ba_data/python/babase/_devconsole.py | 1 + dist/ba_data/python/babase/_devconsoletabs.py | 1 + dist/ba_data/python/babase/_discord.py | 1 + dist/ba_data/python/babase/_emptyappmode.py | 3 +- dist/ba_data/python/babase/_env.py | 25 +- dist/ba_data/python/babase/_gc.py | 1 + dist/ba_data/python/babase/_general.py | 457 +++++-- dist/ba_data/python/babase/_hooks.py | 3 +- dist/ba_data/python/babase/_language.py | 22 +- dist/ba_data/python/babase/_locale.py | 2 + dist/ba_data/python/babase/_mgen/enums.py | 8 +- dist/ba_data/python/babase/_net.py | 1 + dist/ba_data/python/babase/_ui.py | 1 + dist/ba_data/python/babase/modutils.py | 1 + dist/ba_data/python/baclassic/_achievement.py | 12 +- dist/ba_data/python/baclassic/_analytics.py | 2 +- dist/ba_data/python/baclassic/_appmode.py | 196 +-- .../ba_data/python/baclassic/_appsubsystem.py | 49 +- dist/ba_data/python/baclassic/_benchmark.py | 23 +- dist/ba_data/python/baclassic/_chest.py | 3 +- .../ba_data/python/baclassic/_clienteffect.py | 63 +- dist/ba_data/python/baclassic/_displayitem.py | 39 +- dist/ba_data/python/baclassic/_hooks.py | 1 + dist/ba_data/python/baclassic/_input.py | 1 + dist/ba_data/python/baclassic/_music.py | 1 + dist/ba_data/python/baclassic/_net.py | 7 +- dist/ba_data/python/baclassic/_servermode.py | 1 + dist/ba_data/python/baclassic/_store.py | 18 +- dist/ba_data/python/baclassic/_tips.py | 1 + dist/ba_data/python/baclassic/_tournament.py | 2 +- dist/ba_data/python/baclassic/macmusicapp.py | 9 +- dist/ba_data/python/baclassic/osmusic.py | 5 +- dist/ba_data/python/bacommon/analytics.py | 75 ++ dist/ba_data/python/bacommon/assets.py | 8 +- dist/ba_data/python/bacommon/bacloud.py | 43 +- dist/ba_data/python/bacommon/build.py | 8 +- .../python/bacommon/classic/__init__.py | 71 ++ .../python/bacommon/classic/_account.py | 83 ++ .../ba_data/python/bacommon/classic/_chest.py | 67 + .../python/bacommon/classic/_classic.py | 9 + .../python/bacommon/classic/_displayitem.py | 28 + dist/ba_data/python/bacommon/classic/_msg.py | 249 ++++ dist/ba_data/python/bacommon/clienteffect.py | 224 ++++ dist/ba_data/python/bacommon/cloud.py | 107 +- .../python/bacommon/clouddialog/__init__.py | 29 + .../bacommon/clouddialog/_clouddialog.py | 142 +++ .../python/bacommon/clouddialog/basic.py | 233 ++++ dist/ba_data/python/bacommon/displayitem.py | 198 +++ .../ba_data/python/bacommon/docui/__init__.py | 30 + dist/ba_data/python/bacommon/docui/_docui.py | 172 +++ dist/ba_data/python/bacommon/docui/v1.py | 783 ++++++++++++ dist/ba_data/python/bacommon/locale.py | 30 +- dist/ba_data/python/bacommon/loggercontrol.py | 5 + dist/ba_data/python/bacommon/logging.py | 2 +- dist/ba_data/python/bacommon/login.py | 4 +- dist/ba_data/python/bacommon/net.py | 8 +- dist/ba_data/python/bacommon/securedata.py | 8 +- dist/ba_data/python/bacommon/servermanager.py | 1 + dist/ba_data/python/bacommon/text.py | 121 ++ dist/ba_data/python/bacommon/transfer.py | 8 +- .../python/bacommon/workspace/assetsv1.py | 35 +- dist/ba_data/python/baenv.py | 7 +- dist/ba_data/python/baplus/_ads.py | 1 + dist/ba_data/python/baplus/_appsubsystem.py | 11 +- dist/ba_data/python/baplus/_cloud.py | 94 +- dist/ba_data/python/baplus/_hooks.py | 1 + dist/ba_data/python/bascenev1/__init__.py | 15 +- dist/ba_data/python/bascenev1/_activity.py | 10 +- .../python/bascenev1/_activitytypes.py | 6 +- dist/ba_data/python/bascenev1/_campaign.py | 1 + dist/ba_data/python/bascenev1/_collision.py | 8 +- dist/ba_data/python/bascenev1/_coopgame.py | 7 +- dist/ba_data/python/bascenev1/_coopsession.py | 9 +- dist/ba_data/python/bascenev1/_debug.py | 1 + .../python/bascenev1/_dualteamsession.py | 1 + .../ba_data/python/bascenev1/_gameactivity.py | 19 +- dist/ba_data/python/bascenev1/_gameresults.py | 1 + dist/ba_data/python/bascenev1/_hooks.py | 1 + dist/ba_data/python/bascenev1/_level.py | 10 +- dist/ba_data/python/bascenev1/_lobby.py | 25 +- dist/ba_data/python/bascenev1/_map.py | 1 + dist/ba_data/python/bascenev1/_messages.py | 2 +- .../python/bascenev1/_multiteamsession.py | 1 + dist/ba_data/python/bascenev1/_net.py | 1 + dist/ba_data/python/bascenev1/_player.py | 5 +- dist/ba_data/python/bascenev1/_profile.py | 1 + dist/ba_data/python/bascenev1/_session.py | 11 +- dist/ba_data/python/bascenev1/_stats.py | 4 +- dist/ba_data/python/bascenev1/_team.py | 3 +- .../python/bascenev1lib/activity/coopjoin.py | 4 +- .../python/bascenev1lib/activity/coopscore.py | 65 +- .../bascenev1lib/activity/dualteamscore.py | 6 +- .../activity/freeforallvictory.py | 26 +- .../bascenev1lib/activity/multiteamscore.py | 1 + .../bascenev1lib/activity/multiteamvictory.py | 18 +- .../ba_data/python/bascenev1lib/actor/bomb.py | 20 +- .../bascenev1lib/actor/controlsguide.py | 15 +- .../ba_data/python/bascenev1lib/actor/flag.py | 4 +- .../python/bascenev1lib/actor/image.py | 2 +- .../bascenev1lib/actor/onscreentimer.py | 1 + .../python/bascenev1lib/actor/popuptext.py | 2 +- .../python/bascenev1lib/actor/powerupbox.py | 4 +- .../python/bascenev1lib/actor/respawnicon.py | 7 +- .../python/bascenev1lib/actor/scoreboard.py | 4 +- .../ba_data/python/bascenev1lib/actor/spaz.py | 46 +- .../bascenev1lib/actor/spazappearance.py | 7 +- .../python/bascenev1lib/actor/spazbot.py | 122 +- .../ba_data/python/bascenev1lib/actor/text.py | 2 +- .../python/bascenev1lib/actor/tipstext.py | 2 +- .../python/bascenev1lib/actor/zoomtext.py | 10 +- .../python/bascenev1lib/game/assault.py | 4 +- .../bascenev1lib/game/capturetheflag.py | 6 +- .../python/bascenev1lib/game/chosenone.py | 6 +- .../python/bascenev1lib/game/conquest.py | 4 +- .../python/bascenev1lib/game/easteregghunt.py | 2 +- .../python/bascenev1lib/game/elimination.py | 7 +- .../python/bascenev1lib/game/football.py | 27 +- .../python/bascenev1lib/game/keepaway.py | 2 +- .../python/bascenev1lib/game/kingofthehill.py | 44 +- .../python/bascenev1lib/game/meteorshower.py | 2 +- .../python/bascenev1lib/game/onslaught.py | 35 +- dist/ba_data/python/bascenev1lib/game/race.py | 5 +- .../python/bascenev1lib/game/runaround.py | 28 +- .../bascenev1lib/game/targetpractice.py | 2 +- .../python/bascenev1lib/game/thelaststand.py | 14 +- dist/ba_data/python/bascenev1lib/mainmenu.py | 90 +- dist/ba_data/python/bascenev1lib/maps.py | 46 +- dist/ba_data/python/bascenev1lib/tutorial.py | 34 +- .../python/batemplatefs/_appsubsystem.py | 1 + dist/ba_data/python/bauiv1/__init__.py | 14 +- dist/ba_data/python/bauiv1/_appsubsystem.py | 59 +- dist/ba_data/python/bauiv1/_hooks.py | 1 + dist/ba_data/python/bauiv1/_uitypes.py | 20 + dist/ba_data/python/bauiv1/_window.py | 12 + .../ba_data/python/bauiv1/onscreenkeyboard.py | 6 +- .../python/bauiv1lib/account/settings.py | 39 +- .../python/bauiv1lib/account/signin.py | 4 +- .../python/bauiv1lib/account/v2proxy.py | 21 +- .../python/bauiv1lib/account/viewer.py | 2 +- dist/ba_data/python/bauiv1lib/achievements.py | 2 + dist/ba_data/python/bauiv1lib/appinvite.py | 2 +- .../python/bauiv1lib/characterpicker.py | 5 +- dist/ba_data/python/bauiv1lib/chest.py | 181 ++- dist/ba_data/python/bauiv1lib/colorpicker.py | 28 +- dist/ba_data/python/bauiv1lib/config.py | 4 +- dist/ba_data/python/bauiv1lib/connect.py | 2 +- dist/ba_data/python/bauiv1lib/connectivity.py | 2 +- dist/ba_data/python/bauiv1lib/coop/browser.py | 179 ++- .../python/bauiv1lib/coop/gamebutton.py | 4 +- .../python/bauiv1lib/coop/tournamentbutton.py | 10 +- dist/ba_data/python/bauiv1lib/discord.py | 2 +- .../python/bauiv1lib/docui/__init__.py | 11 + .../python/bauiv1lib/docui/_controller.py | 971 +++++++++++++++ .../ba_data/python/bauiv1lib/docui/_window.py | 546 +++++++++ .../python/bauiv1lib/docui/v1prep/__init__.py | 40 + .../python/bauiv1lib/docui/v1prep/_calls.py | 778 ++++++++++++ .../python/bauiv1lib/docui/v1prep/_calls2.py | 604 +++++++++ .../python/bauiv1lib/docui/v1prep/_types.py | 73 ++ dist/ba_data/python/bauiv1lib/docuitest.py | 1092 +++++++++++++++++ dist/ba_data/python/bauiv1lib/fileselector.py | 8 +- .../python/bauiv1lib/gather/__init__.py | 1 - .../python/bauiv1lib/gather/_gather.py | 2 +- .../python/bauiv1lib/gather/abouttab.py | 6 +- .../python/bauiv1lib/gather/manualtab.py | 40 +- .../python/bauiv1lib/gather/nearbytab.py | 15 +- .../python/bauiv1lib/gather/privatetab.py | 26 +- .../python/bauiv1lib/gather/publictab.py | 50 +- dist/ba_data/python/bauiv1lib/gettokens.py | 91 +- dist/ba_data/python/bauiv1lib/help.py | 16 +- dist/ba_data/python/bauiv1lib/iconpicker.py | 4 +- dist/ba_data/python/bauiv1lib/inbox.py | 107 +- dist/ba_data/python/bauiv1lib/ingamemenu.py | 20 +- dist/ba_data/python/bauiv1lib/inventory.py | 496 ++++++-- dist/ba_data/python/bauiv1lib/kiosk.py | 24 +- .../python/bauiv1lib/league/presidency.py | 40 + .../python/bauiv1lib/league/rankwindow.py | 169 ++- dist/ba_data/python/bauiv1lib/mainmenu.py | 17 +- dist/ba_data/python/bauiv1lib/party.py | 14 +- dist/ba_data/python/bauiv1lib/partyqueue.py | 10 +- dist/ba_data/python/bauiv1lib/play.py | 2 +- .../python/bauiv1lib/playlist/addgame.py | 44 +- .../python/bauiv1lib/playlist/browser.py | 8 +- .../bauiv1lib/playlist/customizebrowser.py | 54 +- .../ba_data/python/bauiv1lib/playlist/edit.py | 14 +- .../python/bauiv1lib/playlist/editgame.py | 24 +- .../python/bauiv1lib/playlist/mapselect.py | 39 +- .../python/bauiv1lib/playlist/share.py | 2 +- dist/ba_data/python/bauiv1lib/playoptions.py | 45 +- dist/ba_data/python/bauiv1lib/popup.py | 4 +- dist/ba_data/python/bauiv1lib/profile/edit.py | 223 +++- .../python/bauiv1lib/profile/upgrade.py | 10 +- dist/ba_data/python/bauiv1lib/qrcode.py | 1 + dist/ba_data/python/bauiv1lib/radiogroup.py | 2 +- .../python/bauiv1lib/resourcetypeinfo.py | 7 +- dist/ba_data/python/bauiv1lib/sendinfo.py | 2 +- .../python/bauiv1lib/settings/advanced.py | 24 +- .../python/bauiv1lib/settings/allsettings.py | 7 +- .../python/bauiv1lib/settings/audio.py | 3 +- .../python/bauiv1lib/settings/benchmarks.py | 12 +- .../python/bauiv1lib/settings/gamepad.py | 14 +- .../bauiv1lib/settings/gamepadadvanced.py | 8 +- .../bauiv1lib/settings/gamepadselect.py | 2 +- .../python/bauiv1lib/settings/graphics.py | 2 +- .../python/bauiv1lib/settings/keyboard.py | 4 +- .../python/bauiv1lib/settings/nettesting.py | 4 +- .../python/bauiv1lib/settings/plugins.py | 28 +- .../python/bauiv1lib/settings/testing.py | 8 +- .../python/bauiv1lib/settings/touchscreen.py | 1 + .../python/bauiv1lib/soundtrack/browser.py | 58 +- .../python/bauiv1lib/soundtrack/edit.py | 8 +- .../bauiv1lib/soundtrack/entrytypeselect.py | 1 + .../bauiv1lib/soundtrack/macmusicapp.py | 2 +- dist/ba_data/python/bauiv1lib/store.py | 59 + dist/ba_data/python/bauiv1lib/tabs.py | 2 +- .../python/bauiv1lib/teamnamescolors.py | 2 +- dist/ba_data/python/bauiv1lib/template.py | 2 +- .../python/bauiv1lib/tournamententry.py | 19 +- .../python/bauiv1lib/tournamentscores.py | 4 +- dist/ba_data/python/bauiv1lib/watch.py | 10 +- dist/ba_data/python/efro/dataclassio/_base.py | 50 +- dist/ba_data/python/efro/dataclassio/_prep.py | 320 ++--- .../efro/dataclassio/templatemultitype.py | 10 +- dist/ba_data/python/efro/debug.py | 1 + dist/ba_data/python/efro/error.py | 1 + dist/ba_data/python/efro/logging.py | 1 + dist/ba_data/python/efro/message/_receiver.py | 4 +- dist/ba_data/python/efro/terminal.py | 1 + dist/ba_data/python/efro/threadpool.py | 7 +- dist/ba_data/python/efro/util.py | 91 +- dist/bombsquad_headless | Bin 8132888 -> 8176152 bytes 241 files changed, 10185 insertions(+), 1827 deletions(-) create mode 100644 dist/ba_data/python/babase/_analytics.py create mode 100644 dist/ba_data/python/bacommon/analytics.py create mode 100644 dist/ba_data/python/bacommon/classic/__init__.py create mode 100644 dist/ba_data/python/bacommon/classic/_account.py create mode 100644 dist/ba_data/python/bacommon/classic/_chest.py create mode 100644 dist/ba_data/python/bacommon/classic/_classic.py create mode 100644 dist/ba_data/python/bacommon/classic/_displayitem.py create mode 100644 dist/ba_data/python/bacommon/classic/_msg.py create mode 100644 dist/ba_data/python/bacommon/clienteffect.py create mode 100644 dist/ba_data/python/bacommon/clouddialog/__init__.py create mode 100644 dist/ba_data/python/bacommon/clouddialog/_clouddialog.py create mode 100644 dist/ba_data/python/bacommon/clouddialog/basic.py create mode 100644 dist/ba_data/python/bacommon/displayitem.py create mode 100644 dist/ba_data/python/bacommon/docui/__init__.py create mode 100644 dist/ba_data/python/bacommon/docui/_docui.py create mode 100644 dist/ba_data/python/bacommon/docui/v1.py create mode 100644 dist/ba_data/python/bacommon/text.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/__init__.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/_controller.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/_window.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/v1prep/__init__.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/v1prep/_calls.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/v1prep/_calls2.py create mode 100644 dist/ba_data/python/bauiv1lib/docui/v1prep/_types.py create mode 100644 dist/ba_data/python/bauiv1lib/docuitest.py create mode 100644 dist/ba_data/python/bauiv1lib/league/presidency.py create mode 100644 dist/ba_data/python/bauiv1lib/store.py diff --git a/dist/ba_data/python/babase/__init__.py b/dist/ba_data/python/babase/__init__.py index b1e689d..7253a15 100644 --- a/dist/ba_data/python/babase/__init__.py +++ b/dist/ba_data/python/babase/__init__.py @@ -7,6 +7,7 @@ directly. Instead one should use purpose-built packages such as :mod:`bascenev1` or :mod:`bauiv1` which themselves import various functionality from here and reexpose it in a more focused way. """ + # pylint: disable=redefined-builtin # ba_meta require api 9 @@ -15,7 +16,8 @@ functionality from here and reexpose it in a more focused way. # from other modules/packages. Code *within* this package should import # things from this package's submodules directly to reduce the chance of # dependency loops. The exception is TYPE_CHECKING blocks and -# annotations since those aren't evaluated at runtime. +# annotations - since those aren't evaluated at runtime, it is cleaner +# looking to use top level names directly. import _babase from _babase import ( @@ -125,6 +127,7 @@ from _babase import ( ) from babase._accountv2 import AccountV2Handle, AccountV2Subsystem +from babase._analytics import AnalyticsSubsystem from babase._app import App, AppState from babase._appcomponent import AppComponentSubsystem from babase._appconfig import commit_app_config @@ -134,68 +137,71 @@ from babase._appsubsystem import AppSubsystem from babase._appmodeselector import AppModeSelector from babase._appconfig import AppConfig from babase._apputils import ( + AppHealthSubsystem, + get_remote_app_name, handle_leftover_v1_cloud_log_file, is_browser_likely_available, - get_remote_app_name, - AppHealthSubsystem, utc_now_cloud, ) from babase._cloud import CloudSubscription from babase._devconsole import ( DevConsoleButtonDef, + DevConsoleSubsystem, DevConsoleTab, DevConsoleTabEntry, - DevConsoleSubsystem, ) from babase._discord import DiscordSubsystem from babase._emptyappmode import EmptyAppMode from babase._error import ( + ActivityNotFoundError, + ActorNotFoundError, ContextError, + DelegateNotFoundError, + InputDeviceNotFoundError, + MapNotFoundError, + NodeNotFoundError, NotFoundError, PlayerNotFoundError, - SessionPlayerNotFoundError, - NodeNotFoundError, - ActorNotFoundError, - InputDeviceNotFoundError, - WidgetNotFoundError, - ActivityNotFoundError, - TeamNotFoundError, - MapNotFoundError, - SessionTeamNotFoundError, SessionNotFoundError, - DelegateNotFoundError, + SessionPlayerNotFoundError, + SessionTeamNotFoundError, + TeamNotFoundError, + WidgetNotFoundError, ) from babase._gc import GarbageCollectionSubsystem from babase._general import ( - DisplayTime, AppTime, - WeakCall, Call, - existing, + CallPartial, + CallStrict, + DisplayTime, Existable, - verify_object_death, - storagename, - getclass, + WeakCall, + WeakCallPartial, + WeakCallStrict, + existing, get_type_name, + getclass, + storagename, + verify_object_death, ) -from babase._language import Lstr, LanguageSubsystem +from babase._language import LanguageSubsystem, Lstr from babase._locale import LocaleSubsystem from babase._logging import ( - balog, accountlog, applog, + balog, lifecyclelog, netlog, uilog, ) from babase._login import LoginAdapter, LoginInfo - from babase._mgen.enums import ( - Permission, - SpecialChar, InputType, - UIScale, + Permission, QuitType, + SpecialChar, + UIScale, ) from babase._math import normalized_color, is_point_in_box, vec3validate from babase._meta import MetadataSubsystem @@ -216,6 +222,7 @@ __all__ = [ 'ActorNotFoundError', 'allows_ticket_sales', 'add_clean_frame_callback', + 'AnalyticsSubsystem', 'android_get_external_files_dir', 'app', 'App', @@ -242,6 +249,8 @@ __all__ = [ 'atexit', 'balog', 'Call', + 'CallPartial', + 'CallStrict', 'fullscreen_control_available', 'fullscreen_control_get', 'fullscreen_control_key_shortcut', @@ -391,6 +400,8 @@ __all__ = [ 'vec3validate', 'verify_object_death', 'WeakCall', + 'WeakCallPartial', + 'WeakCallStrict', 'WidgetNotFoundError', 'workspaces_in_use', 'WorkspaceSubsystem', diff --git a/dist/ba_data/python/babase/_analytics.py b/dist/ba_data/python/babase/_analytics.py new file mode 100644 index 0000000..93aadac --- /dev/null +++ b/dist/ba_data/python/babase/_analytics.py @@ -0,0 +1,73 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Analytics functionality.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import bacommon.cloud +import _babase + +from babase._logging import balog + +if TYPE_CHECKING: + from bacommon.analytics import AnalyticsEvent + + +class AnalyticsSubsystem: + """Subsystem for wrangling analytics. + + Access the single shared instance of this class via the + :attr:`~babase.App.analytics` attr on the :class:`~babase.App` + class. + """ + + def __init__(self) -> None: + self.enabled: bool = True + + def submit_event(self, event: AnalyticsEvent) -> None: + """Submit an event. + + Should only be called from the logic thread. + """ + + if not _babase.in_logic_thread(): + balog.error( + 'submit_event() called outside logic thread.', stack_info=True + ) + return + + # No-op if analytics are disabled or we don't have plus. + if not self.enabled: + return + + plus = _babase.app.plus + if plus is None: + return + + # Currently just no-op if it seems we're not connected. Perhaps + # in the future we'd want to save these and submit later when we + # are. + if not plus.cloud.is_connected(): + return + + # Just kick off an immediate send in the bg with or without + # account info. + account = plus.accounts.primary + if account is None: + plus.cloud.send_message_cb( + bacommon.cloud.AnalyticsEventMessage(event), + on_response=self._on_analytics_message_response, + ) + else: + with account: + plus.cloud.send_message_cb( + bacommon.cloud.AnalyticsEventMessage(event), + on_response=self._on_analytics_message_response, + ) + + def _on_analytics_message_response( + self, response: Exception | None + ) -> None: + pass diff --git a/dist/ba_data/python/babase/_app.py b/dist/ba_data/python/babase/_app.py index 8a2673f..8ac0177 100644 --- a/dist/ba_data/python/babase/_app.py +++ b/dist/ba_data/python/babase/_app.py @@ -2,10 +2,12 @@ # # pylint: disable=too-many-lines """Functionality related to the high level state of the app.""" + from __future__ import annotations import os import time +import asyncio import logging from enum import Enum from functools import partial @@ -28,12 +30,12 @@ from babase._appmodeselector import AppModeSelector from babase._appintent import AppIntentDefault, AppIntentExec from babase._stringedit import StringEditSubsystem from babase._devconsole import DevConsoleSubsystem +from babase._analytics import AnalyticsSubsystem from babase._appconfig import AppConfig from babase._logging import lifecyclelog, applog from babase._gc import GarbageCollectionSubsystem if TYPE_CHECKING: - import asyncio from typing import Any, Callable, Coroutine, Generator, Awaitable from concurrent.futures import Future @@ -152,6 +154,9 @@ class App: #: Subsystem for wrangling the dev-console UI. self.devconsole: DevConsoleSubsystem = DevConsoleSubsystem() + #: Subsystem for wrangling analytics. + self.analytics: AnalyticsSubsystem = AnalyticsSubsystem() + #: Incremented each time the app leaves the #: :attr:`~babase.AppState.SUSPENDED` state. This can be a simple #: way to determine if network data should be refreshed/etc. @@ -281,8 +286,9 @@ class App: def mode_selector(self, selector: babase.AppModeSelector) -> None: self._mode_selector = selector - def _on_task_done(self, task: asyncio.Task) -> None: + def _on_task_done(self, task: Any) -> None: # Report any errors that occurred. + assert isinstance(task, asyncio.Task) try: exc = task.exception() if exc is not None: @@ -1028,7 +1034,6 @@ class App: ) async def _shutdown(self) -> None: - import asyncio _babase.lock_all_input() try: @@ -1054,13 +1059,16 @@ class App: self, coro: Coroutine[None, None, None] ) -> None: """Run a shutdown task; report errors and abort if taking too long.""" - import asyncio task = asyncio.create_task(coro) try: await asyncio.wait_for(task, self.SHUTDOWN_TASK_TIMEOUT_SECONDS) + except TimeoutError: + # Log simple error message if it times out. + logging.error('Timed out waiting for shutdown task %s.', coro) except Exception: - logging.exception('Error in shutdown task (%s).', coro) + # Go with full ugly stack trace for anything unexpected. + logging.exception('Error in shutdown task %s.', coro) def _on_suspend(self) -> None: """Called when the app goes to a suspended state.""" @@ -1136,7 +1144,6 @@ class App: ) async def _wait_for_shutdown_suppressions(self) -> None: - import asyncio # Spin and wait for anything blocking shutdown to complete. starttime = _babase.apptime() @@ -1153,7 +1160,6 @@ class App: ) async def _fade_and_shutdown_graphics(self) -> None: - import asyncio # Kick off a short fade and give it time to complete. lifecyclelog.info('fade-and-shutdown-graphics begin') @@ -1189,7 +1195,6 @@ class App: lifecyclelog.info('fade-and-shutdown-graphics end') async def _fade_and_shutdown_audio(self) -> None: - import asyncio # Tell the audio system to go down and give it a bit of # time to do so gracefully. diff --git a/dist/ba_data/python/babase/_appcomponent.py b/dist/ba_data/python/babase/_appcomponent.py index e02ea02..1d92ba0 100644 --- a/dist/ba_data/python/babase/_appcomponent.py +++ b/dist/ba_data/python/babase/_appcomponent.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides the AppComponent class.""" + from __future__ import annotations from typing import TYPE_CHECKING, cast diff --git a/dist/ba_data/python/babase/_appconfig.py b/dist/ba_data/python/babase/_appconfig.py index e331071..56f271a 100644 --- a/dist/ba_data/python/babase/_appconfig.py +++ b/dist/ba_data/python/babase/_appconfig.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides the AppConfig class.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/babase/_appintent.py b/dist/ba_data/python/babase/_appintent.py index d6d80e9..3b09079 100644 --- a/dist/ba_data/python/babase/_appintent.py +++ b/dist/ba_data/python/babase/_appintent.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides AppIntent functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/babase/_appmode.py b/dist/ba_data/python/babase/_appmode.py index 48f19f9..ffb27ae 100644 --- a/dist/ba_data/python/babase/_appmode.py +++ b/dist/ba_data/python/babase/_appmode.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides AppMode functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/babase/_appmodeselector.py b/dist/ba_data/python/babase/_appmodeselector.py index bd4da08..298fc9b 100644 --- a/dist/ba_data/python/babase/_appmodeselector.py +++ b/dist/ba_data/python/babase/_appmodeselector.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Contains AppModeSelector base class.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/babase/_appsubsystem.py b/dist/ba_data/python/babase/_appsubsystem.py index 11efcf4..6af6e86 100644 --- a/dist/ba_data/python/babase/_appsubsystem.py +++ b/dist/ba_data/python/babase/_appsubsystem.py @@ -1,11 +1,11 @@ # Released under the MIT License. See LICENSE for details. # """Provides the AppSubsystem base class.""" + from __future__ import annotations from typing import TYPE_CHECKING - if TYPE_CHECKING: from babase import UIScale diff --git a/dist/ba_data/python/babase/_apputils.py b/dist/ba_data/python/babase/_apputils.py index 7915970..9bf7326 100644 --- a/dist/ba_data/python/babase/_apputils.py +++ b/dist/ba_data/python/babase/_apputils.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Utility functionality related to the overall operation of the app.""" + from __future__ import annotations import os diff --git a/dist/ba_data/python/babase/_cloud.py b/dist/ba_data/python/babase/_cloud.py index 9ea0662..43cbd2d 100644 --- a/dist/ba_data/python/babase/_cloud.py +++ b/dist/ba_data/python/babase/_cloud.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Cloud related functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/babase/_devconsole.py b/dist/ba_data/python/babase/_devconsole.py index 24c4d2f..ba90111 100644 --- a/dist/ba_data/python/babase/_devconsole.py +++ b/dist/ba_data/python/babase/_devconsole.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Dev-Console functionality.""" + from __future__ import annotations import os diff --git a/dist/ba_data/python/babase/_devconsoletabs.py b/dist/ba_data/python/babase/_devconsoletabs.py index 18221f1..e535888 100644 --- a/dist/ba_data/python/babase/_devconsoletabs.py +++ b/dist/ba_data/python/babase/_devconsoletabs.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Predefined tabs for the dev console.""" + from __future__ import annotations import math diff --git a/dist/ba_data/python/babase/_discord.py b/dist/ba_data/python/babase/_discord.py index 27015ac..3c5aa39 100644 --- a/dist/ba_data/python/babase/_discord.py +++ b/dist/ba_data/python/babase/_discord.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. """Functionality related to discord sdk integration""" + from __future__ import annotations from typing import TYPE_CHECKING, override diff --git a/dist/ba_data/python/babase/_emptyappmode.py b/dist/ba_data/python/babase/_emptyappmode.py index 2c83a14..9add278 100644 --- a/dist/ba_data/python/babase/_emptyappmode.py +++ b/dist/ba_data/python/babase/_emptyappmode.py @@ -1,12 +1,11 @@ # Released under the MIT License. See LICENSE for details. # """Provides AppMode functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING, override -# from bacommon.app import AppExperience - import _babase from babase._appmode import AppMode from babase._appintent import AppIntentExec, AppIntentDefault diff --git a/dist/ba_data/python/babase/_env.py b/dist/ba_data/python/babase/_env.py index 4eb1660..2d1afe4 100644 --- a/dist/ba_data/python/babase/_env.py +++ b/dist/ba_data/python/babase/_env.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Environment related functionality.""" + from __future__ import annotations import os @@ -158,26 +159,6 @@ def on_main_thread_start_app() -> None: # situations. __main__.__builtins__.help = _CustomHelper() - # UPDATE: As of May 2025 I'm no longer seeing the below issue, so - # disabling this workaround for now and will remove it soon if no - # issues arise. - - # On Windows I'm seeing the following error creating asyncio loops - # in background threads with the default proactor setup: - - # ValueError: set_wakeup_fd only works in main thread of the main - # interpreter. - - # So let's explicitly request selector loops. Interestingly this - # error only started showing up once I moved Python init to the main - # thread; previously the various asyncio bg thread loops were - # working fine (maybe something caused them to default to selector - # in that case?.. - if sys.platform == 'win32' and bool(False): - import asyncio - - asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) - # Kick off networking bootstrapping. We do this here instead of in # our app net-subsystem so that it can proceed in parallel with the # rest of our bootstrapping (as networking stuff is often an overall @@ -647,5 +628,5 @@ class _CustomHelper: 'Interactive help is not available in this environment.\n' 'Type help(object) for help about object.' ) - return None - return pydoc.help(*args, **kwds) + return + pydoc.help(*args, **kwds) diff --git a/dist/ba_data/python/babase/_gc.py b/dist/ba_data/python/babase/_gc.py index 0729add..4d5672d 100644 --- a/dist/ba_data/python/babase/_gc.py +++ b/dist/ba_data/python/babase/_gc.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Utility functionality related to the overall operation of the app.""" + from __future__ import annotations import gc diff --git a/dist/ba_data/python/babase/_general.py b/dist/ba_data/python/babase/_general.py index d8982e2..18ebd2e 100644 --- a/dist/ba_data/python/babase/_general.py +++ b/dist/ba_data/python/babase/_general.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Utility snippets applying to generic Python code.""" + from __future__ import annotations import sys @@ -9,6 +10,7 @@ import weakref import random import logging import inspect +import warnings from typing import TYPE_CHECKING, TypeVar, Protocol, NewType, override from efro.terminal import Clr @@ -17,7 +19,7 @@ import _babase if TYPE_CHECKING: import functools - from typing import Any + from typing import Any, Callable # Declare distinct types for different time measurements we use so the @@ -93,160 +95,351 @@ def get_type_name(cls: type) -> str: return f'{cls.__module__}.{cls.__qualname__}' -class _WeakCall: - """Wrap a callable and arguments into a single callable object. +# Note: Something here is wonky with pylint, possibly related to our +# custom pylint plugin. Disabling all checks seems to fix it. +# pylint: disable=all +if TYPE_CHECKING: + # For type-checking, we point WeakCall and Call at + # functools.partial. This gives decent type-checking considering the + # open-ended nature of these calls (args being supplied at create + # time and/or at call time). Just remember that we're slightly lying + # to the type-checker here. + WeakCallPartial = functools.partial + CallPartial = functools.partial + WeakCall = functools.partial + Call = functools.partial +else: - When passed a bound method as the callable, the instance portion of - it is weak-referenced, meaning the underlying instance is free to - die if all other references to it go away. Should this occur, - calling the weak-call is simply a no-op. + class WeakCallPartial: + """Wrap a callable and arguments into a single callable object. - Think of this as a handy way to tell an object to do something at - some point in the future if it happens to still exist. + When passed a bound method as the callable, the instance portion of + it is weak-referenced, meaning the underlying instance is free to + die if all other references to it go away. Should this occur, + calling the weak-call is simply a no-op. - **EXAMPLE A:** This code will create a ``FooClass`` instance and - call its ``bar()`` method 5 seconds later; it will be kept alive - even though we overwrite its variable with None because the bound - method we pass as a timer callback (``foo.bar``) strong-references - it:: + Think of this as a handy way to tell an object to do something at + some point in the future if it happens to still exist. - foo = FooClass() - babase.apptimer(5.0, foo.bar) - foo = None + **EXAMPLE A:** This code will create a ``FooClass`` instance and + call its ``bar()`` method 5 seconds later; it will be kept alive + even though we overwrite its variable with None because the bound + method we pass as a timer callback (``foo.bar``) strong-references + it:: - **EXAMPLE B:** This code will *not* keep our object alive; it will - die when we overwrite it with ``None`` and the timer will be a no-op - when it fires:: + foo = FooClass() + babase.apptimer(5.0, foo.bar) + foo = None - foo = FooClass() - babase.apptimer(5.0, ba.WeakCall(foo.bar)) - foo = None + **EXAMPLE B:** This code will *not* keep our object alive; it will + die when we overwrite it with ``None`` and the timer will be a no-op + when it fires:: - **EXAMPLE C:** Wrap a method call with some positional and keyword - args:: + foo = FooClass() + babase.apptimer(5.0, ba.WeakCall(foo.bar)) + foo = None - myweakcall = babase.WeakCall(self.dostuff, argval1, - namedarg=argval2) + **EXAMPLE C:** Wrap a method call with some positional and keyword + args:: - # Now we have a single callable to run that whole mess. - # The same as calling myobj.dostuff(argval1, namedarg=argval2) - # (provided my_obj still exists; this will do nothing otherwise). - myweakcall() + myweakcall = babase.WeakCall(self.dostuff, argval1, + namedarg=argval2) - Note: additional args and keywords you provide to the weak-call - constructor are stored as regular strong-references; you'll need to - wrap them in weakrefs manually if desired. + # Now we have a single callable to run that whole mess. + # The same as calling myobj.dostuff(argval1, namedarg=argval2) + # (provided my_obj still exists; this will do nothing otherwise). + myweakcall() + + Note: additional args and keywords you provide to the weak-call + constructor are stored as regular strong-references; you'll need to + wrap them in weakrefs manually if desired. + """ + + # Optimize performance a bit; we shouldn't need to be super dynamic. + __slots__ = ['_call', '_args', '_keywds'] + + _did_invalid_call_warning = False + + def __init__(self, call: Any, /, *args: Any, **keywds: Any) -> None: + # Note: keeping _call, _args, _keywds private in this case + # since we sub functools.partial for ourself in + # type-checking so they will be unrecognized anyway. Use + # non-partial versions if you want to access those. + if hasattr(call, '__func__'): + self._call = WeakMethod(call) + else: + app = _babase.app + if not self._did_invalid_call_warning: + logging.warning( + 'Warning: callable passed to WeakCall() is not' + ' weak-referencable (%s); use regular Call() instead' + ' to avoid this warning.', + args[0], + stack_info=True, + ) + type(self)._did_invalid_call_warning = True + self._call = call + self._args = args + self._keywds = keywds + + def __call__(self, *args_extra: Any, **keywds_extra: Any) -> Any: + # Fast path: no extra args or kwargs. + if not args_extra and not keywds_extra: + return self._call(*self._args, **self._keywds) + + # Slightly slower path: handle extra args. + if not keywds_extra: + # Only extra positional args; skip dict merge. + return self._call(*(self._args + args_extra), **self._keywds) + + # Handle kw overrides (call-time kwargs overriding stored). + merged = {**self._keywds, **keywds_extra} + return self._call(*(self._args + args_extra), **merged) + + @override + def __repr__(self) -> str: + return ( + f'' + ) + + class CallPartial: + """Wraps a callable and args into a single callable object. + + The callable is strong-referenced so it won't die until this + object does. + + Note that a bound method (ex: ``myobj.dosomething``) contains a + reference to ``self`` (``myobj`` in that case), so you will be + keeping that object alive too. Use babase.WeakCall if you want + to pass a method to a callback without keeping its object alive. + + Example: Wrap a method call with 1 positional and 1 keyword arg:: + + mycall = babase.Call(myobj.dostuff, argval, namedarg=argval2) + + # Now we have a single callable to run that whole mess. + # ..the same as calling myobj.dostuff(argval, namedarg=argval2) + mycall() + """ + + # Optimize performance a bit; we shouldn't need to be super dynamic. + __slots__ = ['_call', '_args', '_keywds'] + + def __init__(self, call: Any, /, *args: Any, **keywds: Any): + # Note: keeping _call, _args, _keywds private in this case + # since we sub functools.partial for ourself in + # type-checking so they will be unrecognized anyway. Use + # non-partial versions if you want to access those. + self._call = call + self._args = args + self._keywds = keywds + + def __call__(self, *args_extra: Any, **keywds_extra: Any) -> Any: + # Fast path: no extra args or kwargs. + if not args_extra and not keywds_extra: + return self._call(*self._args, **self._keywds) + + # Slightly slower path: handle extra args. + if not keywds_extra: + # Only extra positional args; skip dict merge. + return self._call(*(self._args + args_extra), **self._keywds) + + # Handle kw overrides (call-time kwargs overriding stored). + merged = {**self._keywds, **keywds_extra} + return self._call(*(self._args + args_extra), **merged) + + @override + def __repr__(self) -> str: + return ( + f'' + ) + + class WeakCall: + """Currently alias of :meth:`WeakCallPartial`.""" + + # Optimize performance a bit; we shouldn't need to be super dynamic. + __slots__ = ['_call', '_args', '_keywds'] + + _did_invalid_call_warning = False + + def __init__(self, call: Any, /, *args: Any, **keywds: Any) -> None: + warnings.warn( + 'WeakCall should be replaced with either WeakCallPartial' + ' (if passing extra args at call time) or WeakCallStrict' + ' (it not). Once API 9 support ends, WeakCall can again be' + ' used, but it will behave like WeakCallStrict instead of' + ' WeakCallPartial.', + DeprecationWarning, + stacklevel=2, + ) + # Note: keeping _call, _args, _keywds private in this case + # since we sub functools.partial for ourself in + # type-checking so they will be unrecognized anyway. Use + # non-partial versions if you want to access those. + if hasattr(call, '__func__'): + self._call = WeakMethod(call) + else: + app = _babase.app + if not self._did_invalid_call_warning: + logging.warning( + 'Warning: callable passed to WeakCall() is not' + ' weak-referencable (%r); use regular Call() instead' + ' to avoid this warning.', + args[0], + stack_info=True, + ) + type(self)._did_invalid_call_warning = True + self._call = call + self._args = args + self._keywds = keywds + + def __call__(self, *args_extra: Any, **keywds_extra: Any) -> Any: + # Fast path: no extra args or kwargs. + if not args_extra and not keywds_extra: + return self._call(*self._args, **self._keywds) + + # Slightly slower path: handle extra args. + if not keywds_extra: + # Only extra positional args; skip dict merge. + return self._call(*(self._args + args_extra), **self._keywds) + + # Handle kw overrides (call-time kwargs overriding stored). + merged = {**self._keywds, **keywds_extra} + return self._call(*(self._args + args_extra), **merged) + + @override + def __repr__(self) -> str: + return ( + f'' + ) + + class Call: + """Currently alias of :meth:`CallPartial`.""" + + # Optimize performance a bit; we shouldn't need to be super dynamic. + __slots__ = ['_call', '_args', '_keywds'] + + def __init__(self, call: Any, /, *args: Any, **keywds: Any): + warnings.warn( + 'Call should be replaced with either CallPartial' + ' (if passing extra args at call time) or CallStrict' + ' (it not). Once API 9 support ends, Call can again be' + ' used, but it will behave like CallStrict instead' + ' of CallPartial.', + DeprecationWarning, + stacklevel=2, + ) + # Note: keeping _call, _args, _keywds private in this case + # since we sub functools.partial for ourself in + # type-checking so they will be unrecognized anyway. Use + # non-partial versions if you want to access those. + self._call = call + self._args = args + self._keywds = keywds + + def __call__(self, *args_extra: Any, **keywds_extra: Any) -> Any: + # Fast path: no extra args or kwargs. + if not args_extra and not keywds_extra: + return self._call(*self._args, **self._keywds) + + # Slightly slower path: handle extra args. + if not keywds_extra: + # Only extra positional args; skip dict merge. + return self._call(*(self._args + args_extra), **self._keywds) + + # Handle kw overrides (call-time kwargs overriding stored). + merged = {**self._keywds, **keywds_extra} + return self._call(*(self._args + args_extra), **merged) + + @override + def __repr__(self) -> str: + return ( + f'' + ) + + +# pylint: enable=all + + +class CallStrict[**P, T]: + """Like :meth:`CallPartial()` but disallows extra args at call time. + + This allows more complete type checking to occur, so this is + recommended if you do not need extra args at call time. """ - # Optimize performance a bit; we shouldn't need to be super dynamic. - __slots__ = ['_call', '_args', '_keywds'] + __slots__ = ('call', 'args', 'kwargs') + + def __init__( + self, call: Callable[P, T], /, *args: P.args, **kwargs: P.kwargs + ) -> None: + # Note: we allow access to these here since we don't use any + # tricks like pointing at functools.partial for type checking or + # whatnot that would break this. + self.call = call + self.args = args + self.kwargs = kwargs + + def __call__(self) -> T: + return self.call(*self.args, **self.kwargs) + + @override + def __repr__(self) -> str: + return ( + f'' + ) + + +class WeakCallStrict[**P, T]: + """Like :meth:`WeakCallPartial()` but disallows extra args at call time. + + This allows more complete type checking to occur, so this is + recommended if you do not need extra args at call time. + """ + + __slots__ = ('call', 'args', 'kwargs') _did_invalid_call_warning = False - def __init__(self, *args: Any, **keywds: Any) -> None: - if hasattr(args[0], '__func__'): - self._call = WeakMethod(args[0]) + def __init__( + self, call: Callable[P, T], /, *args: P.args, **kwargs: P.kwargs + ) -> None: + # Note: we allow access to these here since we don't use any + # tricks like pointing at functools.partial for type checking or + # whatnot that would break this. + if hasattr(call, '__func__'): + self.call: Any = WeakMethod(call) # type: ignore else: app = _babase.app if not self._did_invalid_call_warning: logging.warning( - 'Warning: callable passed to babase.WeakCall() is not' - ' weak-referencable (%s); use functools.partial instead' + 'Warning: callable passed to WeakCallStrict() is not' + ' weak-referencable (%r); use regular CallStrict() instead' ' to avoid this warning.', args[0], stack_info=True, ) type(self)._did_invalid_call_warning = True - self._call = args[0] - self._args = args[1:] - self._keywds = keywds + self.call = call + self.args = args + self.kwargs = kwargs - def __call__(self, *args_extra: Any) -> Any: - return self._call(*self._args + args_extra, **self._keywds) + def __call__(self) -> T: + return self.call(*self.args, **self.kwargs) # type: ignore @override - def __str__(self) -> str: + def __repr__(self) -> str: return ( - '' + f'' ) -class _Call: - """Wraps a callable and arguments into a single callable object. - - The callable is strong-referenced so it won't die until this - object does. - - Note that a bound method (ex: ``myobj.dosomething``) contains a reference - to ``self`` (``myobj`` in that case), so you will be keeping that object - alive too. Use babase.WeakCall if you want to pass a method to a callback - without keeping its object alive. - - Example: Wrap a method call with 1 positional and 1 keyword arg:: - - mycall = babase.Call(myobj.dostuff, argval, namedarg=argval2) - - # Now we have a single callable to run that whole mess. - # ..the same as calling myobj.dostuff(argval, namedarg=argval2) - mycall() - """ - - # Optimize performance a bit; we shouldn't need to be super dynamic. - __slots__ = ['_call', '_args', '_keywds'] - - def __init__(self, *args: Any, **keywds: Any): - self._call = args[0] - self._args = args[1:] - self._keywds = keywds - - def __call__(self, *args_extra: Any) -> Any: - return self._call(*self._args + args_extra, **self._keywds) - - @override - def __str__(self) -> str: - return ( - '' - ) - - -if TYPE_CHECKING: - # For type-checking, point at functools.partial which gives us full - # type checking on both positional and keyword arguments (as of mypy - # 1.11). - - # FIXME: Actually, currently (as of Dec 2024) mypy doesn't fully - # type check partial. The partial() call itself is checked, but the - # resulting callable seems to be essentially untyped. We should - # probably revise this stuff so that Call and WeakCall are for 100% - # complete calls so we can fully type check them using ParamSpecs or - # whatnot. We could then write a weak_partial() call if we actually - # need that particular combination of functionality. - - # Note: Something here is wonky with pylint, possibly related to our - # custom pylint plugin. Disabling all checks seems to fix it. - # pylint: disable=all - - WeakCall = functools.partial - Call = functools.partial -else: - WeakCall = _WeakCall - WeakCall.__name__ = 'WeakCall' - Call = _Call - Call.__name__ = 'Call' - - class WeakMethod: """A weak-referenced bound method. @@ -255,22 +448,22 @@ class WeakMethod: """ # Optimize performance a bit; we shouldn't need to be super dynamic. - __slots__ = ['_func', '_obj'] + __slots__ = ['func', 'obj'] def __init__(self, call: types.MethodType): assert isinstance(call, types.MethodType) - self._func = call.__func__ - self._obj = weakref.ref(call.__self__) + self.func = call.__func__ + self.obj = weakref.ref(call.__self__) def __call__(self, *args: Any, **keywds: Any) -> Any: - obj = self._obj() + obj: Any = self.obj() if obj is None: return None - return self._func(*((obj,) + args), **keywds) + return self.func(*((obj,) + args), **keywds) @override - def __str__(self) -> str: - return '' + def __repr__(self) -> str: + return f'' def verify_object_death(obj: object) -> None: @@ -292,7 +485,7 @@ def verify_object_death(obj: object) -> None: # Make this timer in an empty context; don't want it dying with the # scene/etc. with _babase.ContextRef.empty(): - _babase.apptimer(delay, Call(_verify_object_death, ref)) + _babase.apptimer(delay, CallStrict(_verify_object_death, ref)) def _verify_object_death(wref: weakref.ref) -> None: diff --git a/dist/ba_data/python/babase/_hooks.py b/dist/ba_data/python/babase/_hooks.py index 4c9b771..5021d57 100644 --- a/dist/ba_data/python/babase/_hooks.py +++ b/dist/ba_data/python/babase/_hooks.py @@ -9,6 +9,7 @@ until it broke at runtime. By instead defining such snippets here and then capturing references to them all at launch it is possible to allow linting and type-checking magic to happen and most issues will be caught immediately. """ + # (most of these are self-explanatory) # pylint: disable=missing-function-docstring from __future__ import annotations @@ -42,7 +43,7 @@ def get_v2_account_id() -> str | None: if account is not None: accountid = account.accountid # (Avoids mypy complaints when plus is not present) - assert isinstance(accountid, (str, type(None))) + assert isinstance(accountid, str | None) return accountid return None except Exception: diff --git a/dist/ba_data/python/babase/_language.py b/dist/ba_data/python/babase/_language.py index b8f3c6b..7f381e4 100644 --- a/dist/ba_data/python/babase/_language.py +++ b/dist/ba_data/python/babase/_language.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Language related functionality.""" + from __future__ import annotations import os @@ -561,7 +562,7 @@ class Lstr: You should avoid doing this as much as possible and instead pass and store ``Lstr`` values. """ - return _babase.evaluate_lstr(self._get_json()) + return _babase.evaluate_lstr(self.as_json()) def is_flat_value(self) -> bool: """Return whether this instance represents a 'flat' value. @@ -573,22 +574,13 @@ class Lstr: """ return bool('v' in self.args and not self.args.get('s', [])) - def _get_json(self) -> str: - try: - return json.dumps(self.args, separators=(',', ':')) - except Exception: - from babase import _error - - applog.exception('_get_json failed for %s.', self.args) - return 'JSON_ERR' - - @override - def __str__(self) -> str: - return f'' + def as_json(self) -> str: + """Return the json dict representation of the Lstr.""" + return json.dumps(self.args, separators=(',', ':')) @override def __repr__(self) -> str: - return f'' + return f'' @staticmethod def from_json(json_string: str) -> babase.Lstr: @@ -616,7 +608,7 @@ def _add_to_attr_dict(dst: AttrDict, src: dict) -> None: ) _add_to_attr_dict(dst_dict, value) else: - if not isinstance(value, (float, int, bool, str, str, type(None))): + if not isinstance(value, float | int | bool | str | None): raise TypeError( "invalid value type for res '" + key diff --git a/dist/ba_data/python/babase/_locale.py b/dist/ba_data/python/babase/_locale.py index c8de05e..5371d13 100644 --- a/dist/ba_data/python/babase/_locale.py +++ b/dist/ba_data/python/babase/_locale.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Locale related functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING, override, assert_never @@ -144,6 +145,7 @@ class LocaleSubsystem(AppSubsystem): or rlocale is cls.TAMIL or rlocale is cls.THAI or rlocale is cls.VIETNAMESE + or rlocale is cls.JAPANESE ): # Return True only if we can display full unicode. return _babase.supports_unicode_display() diff --git a/dist/ba_data/python/babase/_mgen/enums.py b/dist/ba_data/python/babase/_mgen/enums.py index 697fe4d..ceb45dd 100644 --- a/dist/ba_data/python/babase/_mgen/enums.py +++ b/dist/ba_data/python/babase/_mgen/enums.py @@ -85,7 +85,9 @@ class Permission(Enum): class SpecialChar(Enum): - """Special characters the game can print.""" + """Special characters the engine can diplay. Note that this currently + needs to be manually kept in sync with bacommon.text.SpecialChar. + """ DOWN_ARROW = 0 UP_ARROW = 1 @@ -185,3 +187,7 @@ class SpecialChar(Enum): MIKIROG = 95 V2_LOGO = 96 CLOSE = 97 + SANTA_HAT = 98 + POTATO = 99 + PALM_TREE = 100 + BOXING_GLOVE = 101 diff --git a/dist/ba_data/python/babase/_net.py b/dist/ba_data/python/babase/_net.py index 16c1e7c..6cbaaa0 100644 --- a/dist/ba_data/python/babase/_net.py +++ b/dist/ba_data/python/babase/_net.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Networking related functionality.""" + from __future__ import annotations import socket diff --git a/dist/ba_data/python/babase/_ui.py b/dist/ba_data/python/babase/_ui.py index 55c895b..9956580 100644 --- a/dist/ba_data/python/babase/_ui.py +++ b/dist/ba_data/python/babase/_ui.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """UI related bits of babase.""" + from __future__ import annotations from typing import TYPE_CHECKING, override diff --git a/dist/ba_data/python/babase/modutils.py b/dist/ba_data/python/babase/modutils.py index 831e9dd..b822734 100644 --- a/dist/ba_data/python/babase/modutils.py +++ b/dist/ba_data/python/babase/modutils.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to modding.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/baclassic/_achievement.py b/dist/ba_data/python/baclassic/_achievement.py index 6641829..a6acf62 100644 --- a/dist/ba_data/python/baclassic/_achievement.py +++ b/dist/ba_data/python/baclassic/_achievement.py @@ -1,12 +1,13 @@ # Released under the MIT License. See LICENSE for details. # """Various functionality related to achievements.""" + from __future__ import annotations import logging from typing import TYPE_CHECKING -from bacommon.bs import ClassicChestAppearance +from bacommon.classic import ClassicChestAppearance from baclassic._chest import ( CHEST_APPEARANCE_DISPLAY_INFOS, CHEST_APPEARANCE_DISPLAY_INFO_DEFAULT, @@ -727,7 +728,10 @@ class Achievement: ) def get_award_chest_type(self) -> ClassicChestAppearance: - """Return the type of chest given for this achievement.""" + """Return the type of chest given for this achievement. + + :meta private: + """ # For now just map our old ticket values to chest types. # Can add distinct values if need be later. @@ -1520,5 +1524,7 @@ class Achievement: for actor in objs: bascenev1.timer( out_time + 1.000, - babase.WeakCall(actor.handlemessage, bascenev1.DieMessage()), + babase.WeakCallStrict( + actor.handlemessage, bascenev1.DieMessage() + ), ) diff --git a/dist/ba_data/python/baclassic/_analytics.py b/dist/ba_data/python/baclassic/_analytics.py index 41a68a8..ad5fe8a 100644 --- a/dist/ba_data/python/baclassic/_analytics.py +++ b/dist/ba_data/python/baclassic/_analytics.py @@ -1,6 +1,6 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to analytics.""" +"""Functionality related to classic analytics.""" from __future__ import annotations diff --git a/dist/ba_data/python/baclassic/_appmode.py b/dist/ba_data/python/baclassic/_appmode.py index ce065b1..20246ba 100644 --- a/dist/ba_data/python/baclassic/_appmode.py +++ b/dist/ba_data/python/baclassic/_appmode.py @@ -1,5 +1,6 @@ # Released under the MIT License. See LICENSE for details. # +# pylint: disable=too-many-lines """Contains ClassicAppMode.""" from __future__ import annotations @@ -11,11 +12,11 @@ from functools import partial from typing import TYPE_CHECKING, override from efro.error import CommunicationError -import bacommon.bs +import bacommon.clienteffect as clfx +import bacommon.classic from babase import AppMode import bauiv1 as bui from bauiv1lib.connectivity import wait_for_connectivity -from bauiv1lib.account.signin import show_sign_in_prompt import _baclassic @@ -233,19 +234,19 @@ class ClassicAppMode(AppMode): if item_id.startswith('tokens'): if item_id == 'tokens1': - tokens = bacommon.bs.TOKENS1_COUNT + tokens = bacommon.classic.TOKENS1_COUNT tokens_str = str(tokens) anim_time = 2.0 elif item_id == 'tokens2': - tokens = bacommon.bs.TOKENS2_COUNT + tokens = bacommon.classic.TOKENS2_COUNT tokens_str = str(tokens) anim_time = 2.5 elif item_id == 'tokens3': - tokens = bacommon.bs.TOKENS3_COUNT + tokens = bacommon.classic.TOKENS3_COUNT tokens_str = str(tokens) anim_time = 3.0 elif item_id == 'tokens4': - tokens = bacommon.bs.TOKENS4_COUNT + tokens = bacommon.classic.TOKENS4_COUNT tokens_str = str(tokens) anim_time = 3.5 else: @@ -257,21 +258,19 @@ class ClassicAppMode(AppMode): ) assert bui.app.classic is not None - effects: list[bacommon.bs.ClientEffect] = [ - bacommon.bs.ClientEffectTokensAnimation( + effects: list[clfx.Effect] = [ + clfx.TokensAnimation( duration=anim_time, startvalue=self._last_tokens_value, endvalue=self._last_tokens_value + tokens, ), - bacommon.bs.ClientEffectDelay(anim_time), - bacommon.bs.ClientEffectScreenMessage( + clfx.Delay(anim_time), + clfx.LegacyScreenMessage( message='You got ${COUNT} tokens!', subs=['${COUNT}', tokens_str], color=(0, 1, 0), ), - bacommon.bs.ClientEffectSound( - sound=bacommon.bs.ClientEffectSound.Sound.CASH_REGISTER - ), + clfx.PlaySound(clfx.Sound.CASH_REGISTER), ] bui.app.classic.run_bs_client_effects(effects) @@ -345,14 +344,14 @@ class ClassicAppMode(AppMode): with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.GetClassicPurchasesMessage(), - on_response=bui.WeakCall( + bacommon.classic.GetClassicPurchasesMessage(), + on_response=bui.WeakCallPartial( self._on_get_classic_purchases_response ), ) def _on_get_classic_purchases_response( - self, response: bacommon.bs.GetClassicPurchasesResponse | Exception + self, response: bacommon.classic.GetClassicPurchasesResponse | Exception ) -> None: assert self._purchase_request_in_flight self._purchase_request_in_flight = False @@ -471,6 +470,7 @@ class ClassicAppMode(AppMode): chest_1_ad_allow_time=-1.0, chest_2_ad_allow_time=-1.0, chest_3_ad_allow_time=-1.0, + store_style='', ) self._have_account_values = False self._update_ui_live_state() @@ -505,7 +505,7 @@ class ClassicAppMode(AppMode): print(f'GOT SUB TEST UPDATE: {val}') def _on_classic_account_data_change( - self, val: bacommon.bs.ClassicAccountLiveData + self, val: bacommon.classic.ClassicLiveAccountClientData ) -> None: achp = round(val.achievements / max(val.achievements_total, 1) * 100.0) @@ -666,6 +666,7 @@ class ClassicAppMode(AppMode): if chest3 is None or chest3.ad_allow_time is None else chest3.ad_allow_time.timestamp() ), + store_style=val.store_style.value, ) # Note that we have values and updated faded state accordingly. @@ -723,44 +724,56 @@ class ClassicAppMode(AppMode): def _root_ui_achievements_press(self) -> None: from bauiv1lib.achievements import AchievementsWindow - if not self._ensure_signed_in_v1(): + btn = bui.get_special_widget('achievements_button') + + if not self._ensure_signed_in(origin_widget=btn): return wait_for_connectivity( on_connected=lambda: bui.app.ui_v1.auxiliary_window_activate( win_type=AchievementsWindow, - win_create_call=lambda: AchievementsWindow( - origin_widget=bui.get_special_widget('achievements_button') - ), + win_create_call=lambda: AchievementsWindow(origin_widget=btn), ) ) def _root_ui_inbox_press(self) -> None: from bauiv1lib.inbox import InboxWindow - if not self._ensure_signed_in(): + btn = bui.get_special_widget('inbox_button') + + if not self._ensure_signed_in(origin_widget=btn): return wait_for_connectivity( on_connected=lambda: bui.app.ui_v1.auxiliary_window_activate( win_type=InboxWindow, - win_create_call=lambda: InboxWindow( - origin_widget=bui.get_special_widget('inbox_button') - ), + win_create_call=lambda: InboxWindow(origin_widget=btn), ) ) def _root_ui_store_press(self) -> None: - from bauiv1lib.store.browser import StoreBrowserWindow + import bacommon.docui.v1 as dui1 - if not self._ensure_signed_in_v1(): + from bauiv1lib.docui import DocUIWindow + from bauiv1lib.store import StoreUIController + + btn = bui.get_special_widget('store_button') + + if not self._ensure_signed_in(origin_widget=btn): return + # Pop up an auxiliary window wherever we are in the nav stack. wait_for_connectivity( on_connected=lambda: bui.app.ui_v1.auxiliary_window_activate( - win_type=StoreBrowserWindow, - win_create_call=lambda: StoreBrowserWindow( - origin_widget=bui.get_special_widget('store_button') + win_type=DocUIWindow, + win_create_call=bui.CallStrict( + StoreUIController().create_window, + dui1.Request('/'), + origin_widget=btn, + uiopenstateid='classicstore', + ), + win_extra_type_id=( + StoreUIController.get_window_extra_type_id() ), ) ) @@ -782,80 +795,76 @@ class ClassicAppMode(AppMode): def _root_ui_trophy_meter_press(self) -> None: from bauiv1lib.league.rankwindow import LeagueRankWindow - if not self._ensure_signed_in_v1(): + btn = bui.get_special_widget('trophy_meter') + + if not self._ensure_signed_in(origin_widget=btn): return bui.app.ui_v1.auxiliary_window_activate( win_type=LeagueRankWindow, - win_create_call=lambda: LeagueRankWindow( - origin_widget=bui.get_special_widget('trophy_meter') - ), + win_create_call=lambda: LeagueRankWindow(origin_widget=btn), ) def _root_ui_level_meter_press(self) -> None: from bauiv1lib.resourcetypeinfo import ResourceTypeInfoWindow - ResourceTypeInfoWindow( - 'xp', origin_widget=bui.get_special_widget('level_meter') - ) + btn = bui.get_special_widget('level_meter') - def _root_ui_inventory_press(self) -> None: - from bauiv1lib.inventory import InventoryWindow - - if not self._ensure_signed_in_v1(): + if not self._ensure_signed_in(origin_widget=btn): return + ResourceTypeInfoWindow('xp', origin_widget=btn) + + def _root_ui_inventory_press(self) -> None: + import bacommon.docui.v1 as dui1 + + from bauiv1lib.docui import DocUIWindow + from bauiv1lib.inventory import InventoryUIController + + # Pop up an auxiliary window wherever we are in the nav stack. bui.app.ui_v1.auxiliary_window_activate( - win_type=InventoryWindow, - win_create_call=lambda: InventoryWindow( - origin_widget=bui.get_special_widget('inventory_button') + win_type=DocUIWindow, + win_create_call=bui.CallStrict( + InventoryUIController().create_window, + dui1.Request('/'), + origin_widget=bui.get_special_widget('inventory_button'), + uiopenstateid='classicinventory', ), + win_extra_type_id=InventoryUIController.get_window_extra_type_id(), ) - def _ensure_signed_in(self) -> bool: + def _ensure_signed_in(self, *, origin_widget: bui.Widget | None) -> bool: """Make sure we're signed in (requiring modern v2 accounts).""" + from bauiv1lib.account.signin import show_sign_in_prompt + plus = bui.app.plus if plus is None: bui.screenmessage('This requires plus.', color=(1, 0, 0)) bui.getsound('error').play() return False if plus.accounts.primary is None: - show_sign_in_prompt() - return False - return True - - def _ensure_signed_in_v1(self) -> bool: - """Make sure we're signed in (allowing legacy v1-only accounts).""" - plus = bui.app.plus - if plus is None: - bui.screenmessage('This requires plus.', color=(1, 0, 0)) - bui.getsound('error').play() - return False - if plus.get_v1_account_state() != 'signed_in': - show_sign_in_prompt() + show_sign_in_prompt(origin_widget=origin_widget) return False return True def _root_ui_get_tokens_press(self) -> None: - from bauiv1lib.gettokens import GetTokensWindow + from bauiv1lib.gettokens import GetTokensWindow, show_get_tokens_window - if not self._ensure_signed_in(): + btn = bui.get_special_widget('get_tokens_button') + + if not self._ensure_signed_in(origin_widget=btn): return - bui.app.ui_v1.auxiliary_window_activate( - win_type=GetTokensWindow, - win_create_call=lambda: GetTokensWindow( - origin_widget=bui.get_special_widget('get_tokens_button') - ), - ) + if bool(True): + show_get_tokens_window(origin_widget=btn, toggle=True) + else: + bui.app.ui_v1.auxiliary_window_activate( + win_type=GetTokensWindow, + win_create_call=lambda: GetTokensWindow(origin_widget=btn), + ) def _root_ui_chest_slot_pressed(self, index: int) -> None: - from bauiv1lib.chest import ( - ChestWindow0, - ChestWindow1, - ChestWindow2, - ChestWindow3, - ) + from bauiv1lib.chest import ChestWindow widgetid: Literal[ 'chest_0_button', @@ -866,16 +875,20 @@ class ClassicAppMode(AppMode): winclass: type[ChestWindow] if index == 0: widgetid = 'chest_0_button' - winclass = ChestWindow0 + winclass = ChestWindow + extratypeid = '0' elif index == 1: widgetid = 'chest_1_button' - winclass = ChestWindow1 + winclass = ChestWindow + extratypeid = '1' elif index == 2: widgetid = 'chest_2_button' - winclass = ChestWindow2 + winclass = ChestWindow + extratypeid = '2' elif index == 3: widgetid = 'chest_3_button' - winclass = ChestWindow3 + winclass = ChestWindow + extratypeid = '3' else: raise RuntimeError(f'Invalid index {index}') @@ -886,6 +899,7 @@ class ClassicAppMode(AppMode): index=index, origin_widget=bui.get_special_widget(widgetid), ), + win_extra_type_id=extratypeid, ) ) @@ -953,16 +967,26 @@ class ClassicAppMode(AppMode): return [ bui.DevConsoleButtonDef( 'MainWindow Template', - bui.WeakCall(self._main_win_template_press), + bui.WeakCallStrict(self._main_win_template_press), ), bui.DevConsoleButtonDef( - 'CloudUI Test', bui.WeakCall(self._cloud_ui_test_press) + 'DocUI Test', bui.WeakCallStrict(self._doc_ui_test_press) ), ] def _main_win_template_press(self) -> None: from bauiv1lib.template import show_template_main_window + # This only works if a main ui is up. + if bui.app.ui_v1.get_main_window() is None: + bui.screenmessage( + 'This requires a main-window to be present.' + ' Open a menu or whatnot first.', + color=(1, 0, 0), + ) + bui.getsound('error').play() + return + # Unintuitively, swish sounds come from buttons, not windows. # And dev-console buttons don't make sounds. So we need to # explicitly do so here. @@ -970,12 +994,22 @@ class ClassicAppMode(AppMode): show_template_main_window() - def _cloud_ui_test_press(self) -> None: - from bauiv1 import show_cloud_ui_window + def _doc_ui_test_press(self) -> None: + from bauiv1lib.docuitest import show_test_doc_ui_window + + # This only works if a main ui is up. + if bui.app.ui_v1.get_main_window() is None: + bui.screenmessage( + 'This requires a main-window to be present.' + ' Open a menu or whatnot first.', + color=(1, 0, 0), + ) + bui.getsound('error').play() + return # Unintuitively, swish sounds come from buttons, not windows. # And dev-console buttons don't make sounds. So we need to # explicitly do so here. bui.getsound('swish').play() - show_cloud_ui_window() + show_test_doc_ui_window() diff --git a/dist/ba_data/python/baclassic/_appsubsystem.py b/dist/ba_data/python/baclassic/_appsubsystem.py index 9244069..65381dd 100644 --- a/dist/ba_data/python/baclassic/_appsubsystem.py +++ b/dist/ba_data/python/baclassic/_appsubsystem.py @@ -3,6 +3,7 @@ # pylint: disable=too-many-lines """Provides classic app subsystem.""" + from __future__ import annotations import random @@ -27,7 +28,9 @@ from baclassic import _input if TYPE_CHECKING: from typing import Callable, Any, Sequence - import bacommon.bs + import bacommon.classic + import bacommon.clienteffect as clfx + import bacommon.clouddialog.basic as bcdlg from bascenev1lib.actor import spazappearance from bauiv1lib.party import PartyWindow @@ -408,7 +411,7 @@ class ClassicAppSubsystem(babase.AppSubsystem): # Otherwise just force the issue. else: babase.pushcall( - babase.Call(bascenev1.new_host_session, MainMenuSession) + babase.CallStrict(bascenev1.new_host_session, MainMenuSession) ) def getmaps(self, playtype: str) -> list[str]: @@ -702,7 +705,7 @@ class ClassicAppSubsystem(babase.AppSubsystem): if sddata is not None: babase.apptimer( delay, - babase.Call(ServerDialogWindow, sddata), + babase.CallStrict(ServerDialogWindow, sddata), ) def show_url_window(self, address: str) -> None: @@ -751,10 +754,13 @@ class ClassicAppSubsystem(babase.AppSubsystem): self, transition: str = 'in_right', origin_widget: bauiv1.Widget | None = None, - selected_profile: str | None = None, + # selected_profile: str | None = None, ) -> None: """Pop up a browser window from within a game.""" - from bauiv1lib.profile.browser import ProfileBrowserWindow + import bacommon.docui.v1 as dui1 + + # from bauiv1lib.profile.browser import ProfileBrowserWindow + from bauiv1lib.inventory import InventoryUIController main_window = babase.app.ui_v1.get_main_window() if main_window is not None: @@ -765,15 +771,16 @@ class ClassicAppSubsystem(babase.AppSubsystem): return babase.app.ui_v1.set_main_window( - ProfileBrowserWindow( + InventoryUIController(player_profiles_only=True).create_window( + dui1.Request('/'), + uiopenstateid='classicinventory', transition=transition, - selected_profile=selected_profile, origin_widget=origin_widget, - minimal_toolbar=True, ), is_top_level=True, back_state=None, suppress_warning=True, + extra_type_id=InventoryUIController.get_window_extra_type_id(), ) def preload_map_preview_media(self) -> None: @@ -835,6 +842,7 @@ class ClassicAppSubsystem(babase.AppSubsystem): suppress_warning=True, # Reset selections to default for consistency. restore_shared_state=False, + extra_type_id='', ) def save_ui_state(self) -> None: @@ -876,11 +884,17 @@ class ClassicAppSubsystem(babase.AppSubsystem): is_top_level=True, back_state=None, suppress_warning=True, + extra_type_id='', ) else: # If there's a saved ui state, restore that. if self.saved_ui_state is not None: app.ui_v1.restore_main_window_state(self.saved_ui_state) + # Kill the state now that we're back; we'll + # generate a new one when we leave. This keeps + # UIOpenStates stored in the state doing the + # right thing. + self.saved_ui_state = None else: # Otherwise start fresh at the main menu. from bauiv1lib.mainmenu import MainMenuWindow @@ -890,25 +904,32 @@ class ClassicAppSubsystem(babase.AppSubsystem): is_top_level=True, back_state=None, suppress_warning=True, + extra_type_id='', ) @staticmethod def run_bs_client_effects( - effects: list[bacommon.bs.ClientEffect], delay: float = 0.0 + effects: list[clfx.Effect], delay: float = 0.0 ) -> None: - """Run client effects sent from the master server.""" + """Run client effects sent from the master server. + + :meta private: + """ from baclassic._clienteffect import run_bs_client_effects run_bs_client_effects(effects, delay=delay) @staticmethod def basic_client_ui_button_label_str( - label: bacommon.bs.BasicCloudDialog.ButtonLabel, + label: bcdlg.ButtonLabel, ) -> babase.Lstr: - """Given a client-ui label, return an Lstr.""" - import bacommon.bs + """Given a client-ui label, return an Lstr. - cls = bacommon.bs.BasicCloudDialog.ButtonLabel + :meta private: + """ + import bacommon.clouddialog.basic as bcdlg + + cls = bcdlg.ButtonLabel if label is cls.UNKNOWN: # Server should not be sending us unknown stuff; make noise # if they do. diff --git a/dist/ba_data/python/baclassic/_benchmark.py b/dist/ba_data/python/baclassic/_benchmark.py index b110e25..91be0c6 100644 --- a/dist/ba_data/python/baclassic/_benchmark.py +++ b/dist/ba_data/python/baclassic/_benchmark.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Benchmark/Stress-Test related functionality.""" + from __future__ import annotations import random @@ -130,9 +131,9 @@ def _start_stress_test(args: _StressTestArgs) -> None: appconfig['Team Tournament Playlist Randomize'] = 1 babase.apptimer( 1.0, - babase.Call( + babase.CallStrict( babase.pushcall, - babase.Call(bascenev1.new_host_session, DualTeamSession), + babase.CallStrict(bascenev1.new_host_session, DualTeamSession), ), ) else: @@ -140,18 +141,22 @@ def _start_stress_test(args: _StressTestArgs) -> None: appconfig['Free-for-All Playlist Randomize'] = 1 babase.apptimer( 1.0, - babase.Call( + babase.CallStrict( babase.pushcall, - babase.Call(bascenev1.new_host_session, FreeForAllSession), + babase.CallStrict( + bascenev1.new_host_session, FreeForAllSession + ), ), ) _baclassic.set_stress_testing(True, args.player_count, args.attract_mode) classic.stress_test_update_timer = babase.AppTimer( - args.round_duration, babase.Call(_reset_stress_test, args) + args.round_duration, babase.CallStrict(_reset_stress_test, args) ) if args.attract_mode: classic.stress_test_update_timer_2 = babase.AppTimer( - 0.48, babase.Call(_update_attract_mode_test, args), repeat=True + 0.48, + babase.CallStrict(_update_attract_mode_test, args), + repeat=True, ) @@ -176,7 +181,7 @@ def _reset_stress_test(args: _StressTestArgs) -> None: # we just end back at the main menu. If things are idle there then # we'll get sent back to a new stress test. if not args.attract_mode: - babase.apptimer(1.0, babase.Call(_start_stress_test, args)) + babase.apptimer(1.0, babase.CallStrict(_start_stress_test, args)) def run_media_reload_benchmark() -> None: @@ -200,8 +205,8 @@ def run_media_reload_benchmark() -> None: color=(1, 1, 0), ) - babase.add_clean_frame_callback(babase.Call(doit, start_time)) + babase.add_clean_frame_callback(babase.CallStrict(doit, start_time)) # The reload starts (should add a completion callback to the reload # func to fix this). - babase.apptimer(0.05, babase.Call(delay_add, babase.apptime())) + babase.apptimer(0.05, babase.CallStrict(delay_add, babase.apptime())) diff --git a/dist/ba_data/python/baclassic/_chest.py b/dist/ba_data/python/baclassic/_chest.py index b5e18ce..0fed2f6 100644 --- a/dist/ba_data/python/baclassic/_chest.py +++ b/dist/ba_data/python/baclassic/_chest.py @@ -1,12 +1,13 @@ # Released under the MIT License. See LICENSE for details. # """Chest related functionality.""" + from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from bacommon.bs import ClassicChestAppearance +from bacommon.classic import ClassicChestAppearance if TYPE_CHECKING: pass diff --git a/dist/ba_data/python/baclassic/_clienteffect.py b/dist/ba_data/python/baclassic/_clienteffect.py index 50e3be7..da91995 100644 --- a/dist/ba_data/python/baclassic/_clienteffect.py +++ b/dist/ba_data/python/baclassic/_clienteffect.py @@ -9,26 +9,25 @@ from typing import TYPE_CHECKING, assert_never from efro.util import strict_partial -import bacommon.bs import bauiv1 import _baclassic if TYPE_CHECKING: - pass + import bacommon.clienteffect as clfx def run_bs_client_effects( - effects: list[bacommon.bs.ClientEffect], delay: float = 0.0 + effects: list[clfx.Effect], delay: float = 0.0 ) -> None: """Run effects.""" # pylint: disable=too-many-branches - from bacommon.bs import ClientEffectTypeID + import bacommon.clienteffect as clfx for effect in effects: effecttype = effect.get_type_id() - if effecttype is ClientEffectTypeID.SCREEN_MESSAGE: - assert isinstance(effect, bacommon.bs.ClientEffectScreenMessage) + if effecttype is clfx.EffectTypeID.LEGACY_SCREEN_MESSAGE: + assert isinstance(effect, clfx.LegacyScreenMessage) textfin = bauiv1.Lstr( translate=('serverResponses', effect.message) ).evaluate() @@ -46,22 +45,33 @@ def run_bs_client_effects( bauiv1.screenmessage, textfin, color=effect.color ), ) + elif effecttype is clfx.EffectTypeID.SCREEN_MESSAGE: + assert isinstance(effect, clfx.ScreenMessage) + bauiv1.apptimer( + delay, + strict_partial( + bauiv1.screenmessage, + effect.message, + color=effect.color, + literal=not effect.is_lstr, + ), + ) - elif effecttype is ClientEffectTypeID.SOUND: - assert isinstance(effect, bacommon.bs.ClientEffectSound) - smcls = bacommon.bs.ClientEffectSound.Sound + elif effecttype is clfx.EffectTypeID.SOUND: + assert isinstance(effect, clfx.PlaySound) + scls = clfx.Sound soundfile: str | None = None - if effect.sound is smcls.UNKNOWN: + if effect.sound is scls.UNKNOWN: # Server should avoid sending us sounds we don't # support. Make some noise if it happens. - logging.error('Got unrecognized bacommon.bs.ClientEffectSound.') - elif effect.sound is smcls.CASH_REGISTER: + logging.error('Got unrecognized bacommon.classic.Sound.') + elif effect.sound is scls.CASH_REGISTER: soundfile = 'cashRegister' - elif effect.sound is smcls.ERROR: + elif effect.sound is scls.ERROR: soundfile = 'error' - elif effect.sound is smcls.POWER_DOWN: + elif effect.sound is scls.POWER_DOWN: soundfile = 'powerdown01' - elif effect.sound is smcls.GUN_COCKING: + elif effect.sound is scls.GUN_COCKING: soundfile = 'gunCocking' else: assert_never(effect.sound) @@ -73,14 +83,12 @@ def run_bs_client_effects( ), ) - elif effecttype is ClientEffectTypeID.DELAY: - assert isinstance(effect, bacommon.bs.ClientEffectDelay) + elif effecttype is clfx.EffectTypeID.DELAY: + assert isinstance(effect, clfx.Delay) delay += effect.seconds - elif effecttype is ClientEffectTypeID.CHEST_WAIT_TIME_ANIMATION: - assert isinstance( - effect, bacommon.bs.ClientEffectChestWaitTimeAnimation - ) + elif effecttype is clfx.EffectTypeID.CHEST_WAIT_TIME_ANIMATION: + assert isinstance(effect, clfx.ChestWaitTimeAnimation) bauiv1.apptimer( delay, strict_partial( @@ -92,8 +100,8 @@ def run_bs_client_effects( ), ) - elif effecttype is ClientEffectTypeID.TICKETS_ANIMATION: - assert isinstance(effect, bacommon.bs.ClientEffectTicketsAnimation) + elif effecttype is clfx.EffectTypeID.TICKETS_ANIMATION: + assert isinstance(effect, clfx.TicketsAnimation) bauiv1.apptimer( delay, strict_partial( @@ -104,8 +112,8 @@ def run_bs_client_effects( ), ) - elif effecttype is ClientEffectTypeID.TOKENS_ANIMATION: - assert isinstance(effect, bacommon.bs.ClientEffectTokensAnimation) + elif effecttype is clfx.EffectTypeID.TOKENS_ANIMATION: + assert isinstance(effect, clfx.TokensAnimation) bauiv1.apptimer( delay, strict_partial( @@ -116,12 +124,11 @@ def run_bs_client_effects( ), ) - elif effecttype is ClientEffectTypeID.UNKNOWN: + elif effecttype is clfx.EffectTypeID.UNKNOWN: # Server should not send us stuff we can't digest. Make # some noise if it happens. logging.error( - 'Got unrecognized bacommon.bs.ClientEffect;' - ' should not happen.' + 'Got unrecognized bacommon.classic.Effect; should not happen.' ) else: diff --git a/dist/ba_data/python/baclassic/_displayitem.py b/dist/ba_data/python/baclassic/_displayitem.py index da8215c..195ddbd 100644 --- a/dist/ba_data/python/baclassic/_displayitem.py +++ b/dist/ba_data/python/baclassic/_displayitem.py @@ -1,28 +1,33 @@ # Released under the MIT License. See LICENSE for details. # """Display-item related functionality.""" + from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, assert_never from efro.util import pairs_from_flat -import bacommon.bs +import bacommon.displayitem as ditm +import bacommon.classic import bauiv1 - if TYPE_CHECKING: pass +# FIXME - migrate to use the doc-ui rendering for these instead. def show_display_item( - itemwrapper: bacommon.bs.DisplayItemWrapper, + itemwrapper: ditm.Wrapper, parent: bauiv1.Widget, pos: tuple[float, float], width: float, + debug: bool = False, ) -> None: """Create ui to depict a display-item.""" + # pylint: disable=too-many-locals - height = width * 0.666 + # Let's go with 4:3 aspect ratio. + height = width * 0.75 # Silent no-op if our parent ui is dead. if not parent: @@ -33,15 +38,24 @@ def show_display_item( text_y_offs = 0.0 show_text = True - if isinstance(itemwrapper.item, bacommon.bs.TicketsDisplayItem): + itemtype = itemwrapper.item.get_type_id() + + if itemtype is ditm.ItemTypeID.TICKETS: img = 'tickets' img_y_offs = width * 0.11 text_y_offs = width * -0.15 - elif isinstance(itemwrapper.item, bacommon.bs.TokensDisplayItem): + elif itemtype is ditm.ItemTypeID.TICKETS_PURPLE: + img = 'ticketsPurple' + img_y_offs = width * 0.11 + text_y_offs = width * -0.15 + elif itemtype is ditm.ItemTypeID.TOKENS: img = 'coin' img_y_offs = width * 0.11 text_y_offs = width * -0.15 - elif isinstance(itemwrapper.item, bacommon.bs.ChestDisplayItem): + elif itemtype is ditm.ItemTypeID.CHEST: + assert isinstance( + itemwrapper.item, bacommon.classic.ClassicChestDisplayItem + ) from baclassic._chest import ( CHEST_APPEARANCE_DISPLAY_INFOS, CHEST_APPEARANCE_DISPLAY_INFO_DEFAULT, @@ -63,9 +77,14 @@ def show_display_item( tint_color=c_info.tint, tint2_color=c_info.tint2, ) + elif ( + itemtype is ditm.ItemTypeID.TEST or itemtype is ditm.ItemTypeID.UNKNOWN + ): + pass + else: + assert_never(itemtype) - # Enable this for testing spacing. - if bool(False): + if debug: bauiv1.imagewidget( parent=parent, position=( diff --git a/dist/ba_data/python/baclassic/_hooks.py b/dist/ba_data/python/baclassic/_hooks.py index 2b37f25..f5b002c 100644 --- a/dist/ba_data/python/baclassic/_hooks.py +++ b/dist/ba_data/python/baclassic/_hooks.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Hooks for C++ layer to use for ClassicAppMode.""" + from __future__ import annotations import logging diff --git a/dist/ba_data/python/baclassic/_input.py b/dist/ba_data/python/baclassic/_input.py index 0effcb5..feaa6d5 100644 --- a/dist/ba_data/python/baclassic/_input.py +++ b/dist/ba_data/python/baclassic/_input.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Input related functionality""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/baclassic/_music.py b/dist/ba_data/python/baclassic/_music.py index 5d63316..4a2ffce 100644 --- a/dist/ba_data/python/baclassic/_music.py +++ b/dist/ba_data/python/baclassic/_music.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Music related functionality.""" + from __future__ import annotations import copy diff --git a/dist/ba_data/python/baclassic/_net.py b/dist/ba_data/python/baclassic/_net.py index 4c1efc6..2ef3250 100644 --- a/dist/ba_data/python/baclassic/_net.py +++ b/dist/ba_data/python/baclassic/_net.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Networking related functionality.""" + from __future__ import annotations import zlib @@ -14,7 +15,7 @@ from typing import TYPE_CHECKING, override from efro.error import CommunicationError from efro.util import strip_exception_tracebacks -import bacommon.bs +import bacommon.classic import babase import bascenev1 @@ -113,7 +114,7 @@ class MasterServerV1CallThread(threading.Thread): dataenc = urllib.parse.urlencode(self._data) mresponse = plus.cloud.send_message( - bacommon.bs.LegacyRequest( + bacommon.classic.LegacyRequest( self._request, self._request_type, classic.legacy_user_agent_string, @@ -168,7 +169,7 @@ class MasterServerV1CallThread(threading.Thread): if self._callback is not None: babase.pushcall( - babase.Call(self._run_callback, response_data), + babase.CallStrict(self._run_callback, response_data), from_other_thread=True, ) diff --git a/dist/ba_data/python/baclassic/_servermode.py b/dist/ba_data/python/baclassic/_servermode.py index e0c39a0..d083818 100644 --- a/dist/ba_data/python/baclassic/_servermode.py +++ b/dist/ba_data/python/baclassic/_servermode.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to running the game in server-mode.""" + from __future__ import annotations import sys diff --git a/dist/ba_data/python/baclassic/_store.py b/dist/ba_data/python/baclassic/_store.py index 5dda5b5..6ed4dc5 100644 --- a/dist/ba_data/python/baclassic/_store.py +++ b/dist/ba_data/python/baclassic/_store.py @@ -292,6 +292,18 @@ class StoreSubsystem: 'icons.explodinary': { 'icon': babase.charstr(babase.SpecialChar.EXPLODINARY_LOGO) }, + 'icons.santa_hat': { + 'icon': babase.charstr(babase.SpecialChar.SANTA_HAT) + }, + 'icons.potato': { + 'icon': babase.charstr(babase.SpecialChar.POTATO) + }, + 'icons.palm_tree': { + 'icon': babase.charstr(babase.SpecialChar.PALM_TREE) + }, + 'icons.boxing_glove': { + 'icon': babase.charstr(babase.SpecialChar.BOXING_GLOVE) + }, } return babase.app.classic.store_items @@ -569,7 +581,7 @@ class StoreSubsystem: def get_unowned_maps(self) -> list[str]: """Return the list of local maps not owned by the current account.""" classic = babase.app.classic - purchases = classic.purchases if classic is not None else set() + purchases = classic.purchases if classic is not None else frozenset() unowned_maps: set[str] = set() if babase.app.env.gui: for map_section in self.get_store_layout()['maps']: @@ -583,7 +595,9 @@ class StoreSubsystem: """Return present game types not owned by the current account.""" try: classic = babase.app.classic - purchases = classic.purchases if classic is not None else set() + purchases = ( + classic.purchases if classic is not None else frozenset() + ) unowned_games: set[type[bascenev1.GameActivity]] = set() if babase.app.env.gui: for section in self.get_store_layout()['minigames']: diff --git a/dist/ba_data/python/baclassic/_tips.py b/dist/ba_data/python/baclassic/_tips.py index 5936c9c..ae18032 100644 --- a/dist/ba_data/python/baclassic/_tips.py +++ b/dist/ba_data/python/baclassic/_tips.py @@ -3,6 +3,7 @@ """Functionality related to classic game tips. These can be shown at opportune times such as between rounds.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/baclassic/_tournament.py b/dist/ba_data/python/baclassic/_tournament.py index e71d960..d1b7aea 100644 --- a/dist/ba_data/python/baclassic/_tournament.py +++ b/dist/ba_data/python/baclassic/_tournament.py @@ -6,7 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING -from bacommon.bs import ClassicChestAppearance +from bacommon.classic import ClassicChestAppearance import babase import bauiv1 import bascenev1 diff --git a/dist/ba_data/python/baclassic/macmusicapp.py b/dist/ba_data/python/baclassic/macmusicapp.py index 48a41e5..bcde38d 100644 --- a/dist/ba_data/python/baclassic/macmusicapp.py +++ b/dist/ba_data/python/baclassic/macmusicapp.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Music playback functionality using the Mac Music (formerly iTunes) app.""" + from __future__ import annotations import logging @@ -95,7 +96,7 @@ class _MacMusicAppThread(threading.Thread): def do_print() -> None: babase.apptimer( 0.5, - babase.Call( + babase.CallStrict( babase.screenmessage, babase.Lstr(resource='usingItunesText'), (0, 1, 0), @@ -198,7 +199,9 @@ class _MacMusicAppThread(threading.Thread): except Exception as exc: print('Error getting iTunes playlists:', exc) playlists = [] - babase.pushcall(babase.Call(target, playlists), from_other_thread=True) + babase.pushcall( + babase.CallStrict(target, playlists), from_other_thread=True + ) def _handle_play_command(self, target: str | None) -> None: if target is None: @@ -246,7 +249,7 @@ class _MacMusicAppThread(threading.Thread): pass else: babase.pushcall( - babase.Call( + babase.CallStrict( babase.screenmessage, babase.app.lang.get_resource('playlistNotFoundText') + ': \'' diff --git a/dist/ba_data/python/baclassic/osmusic.py b/dist/ba_data/python/baclassic/osmusic.py index 8a79bf7..c48b2fc 100644 --- a/dist/ba_data/python/baclassic/osmusic.py +++ b/dist/ba_data/python/baclassic/osmusic.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Music playback using OS functionality exposed through the C++ layer.""" + from __future__ import annotations import os @@ -151,7 +152,7 @@ class _PickFolderSongThread(threading.Thread): ).evaluate() ) babase.pushcall( - babase.Call(self._callback, all_files, None), + babase.CallStrict(self._callback, all_files, None), from_other_thread=True, ) except Exception as exc: @@ -162,6 +163,6 @@ class _PickFolderSongThread(threading.Thread): except Exception: err_str = '' babase.pushcall( - babase.Call(self._callback, self._path, err_str), + babase.CallStrict(self._callback, self._path, err_str), from_other_thread=True, ) diff --git a/dist/ba_data/python/bacommon/analytics.py b/dist/ba_data/python/bacommon/analytics.py new file mode 100644 index 0000000..fef2a9d --- /dev/null +++ b/dist/ba_data/python/bacommon/analytics.py @@ -0,0 +1,75 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Analytics support.""" + +from __future__ import annotations + +from typing import assert_never, override, Annotated + +from enum import Enum, unique +from dataclasses import dataclass + +from efro.dataclassio import ioprepped, IOMultiType, IOAttrs + + +class AnalyticsEventTypeID(Enum): + """Type ID for each of our subclasses.""" + + CLASSIC = 'c' + + +class AnalyticsEvent(IOMultiType[AnalyticsEventTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> AnalyticsEventTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: AnalyticsEventTypeID) -> type[AnalyticsEvent]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = AnalyticsEventTypeID + if type_id is t.CLASSIC: + return ClassicAnalyticsEvent + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + +@ioprepped +@dataclass +class ClassicAnalyticsEvent(AnalyticsEvent): + """Analytics event related to classic.""" + + @unique + class EventType(Enum): + """Types of classic events.""" + + JOIN_PUBLIC_PARTY = 'jpb' + JOIN_PRIVATE_PARTY = 'jpr' + JOIN_PARTY_BY_ADDRESS = 'ja' + JOIN_NEARBY_PARTY = 'jn' + START_TEAMS_SESSION = 'st' + START_FFA_SESSION = 'sf' + START_COOP_SESSION = 'sc' + START_TOURNEY_COOP_SESSION = 'stc' + + eventtype: Annotated[EventType, IOAttrs('t')] + extra: Annotated[str | None, IOAttrs('e', store_default=False)] = None + + @override + @classmethod + def get_type_id(cls) -> AnalyticsEventTypeID: + return AnalyticsEventTypeID.CLASSIC diff --git a/dist/ba_data/python/bacommon/assets.py b/dist/ba_data/python/bacommon/assets.py index 159307d..160a9e5 100644 --- a/dist/ba_data/python/bacommon/assets.py +++ b/dist/ba_data/python/bacommon/assets.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to cloud based assets.""" +"""Functionality related to cloud based assets. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations diff --git a/dist/ba_data/python/bacommon/bacloud.py b/dist/ba_data/python/bacommon/bacloud.py index 0ea6e86..37f1450 100644 --- a/dist/ba_data/python/bacommon/bacloud.py +++ b/dist/ba_data/python/bacommon/bacloud.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to the bacloud tool.""" +"""Functionality related to the bacloud tool. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations @@ -14,7 +20,7 @@ if TYPE_CHECKING: # 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 = 13 +BACLOUD_VERSION = 14 def asset_file_cache_path(filehash: str) -> str: @@ -91,12 +97,30 @@ class ResponseData: #: response processing (including error handling) occurs. message: Annotated[str | None, IOAttrs('m', store_default=False)] = None - #: End arg for message print() call. + #: Value for the 'end' arg of the message print() call. message_end: Annotated[str, IOAttrs('m_end', store_default=False)] = '\n' - #: If present, client should abort with this error message. + #: If present, client should print this message before any other + #: response processing (including error handling) occurs. + message_stderr: Annotated[ + str | None, IOAttrs('m2', store_default=False) + ] = None + + #: Value for the 'end' arg of the message print() call. + message_stderr_end: Annotated[ + str, IOAttrs('m2_end', store_default=False) + ] = '\n' + + #: If present, client should abort with this error message and + #: return-code 2. error: Annotated[str | None, IOAttrs('e', store_default=False)] = None + #: If present for an interactive command, specifies the return code + #: for the process. Note that this only applies if error is not set. + #: Standard return codes are 0 for success, 1 for a successful run + #: but negative result, and 2 for errors. + return_code: Annotated[int | None, IOAttrs('r', store_default=False)] = None + #: How long to wait before proceeding with remaining response (can #: be useful when waiting for server progress in a loop). delay_seconds: Annotated[float, IOAttrs('d', store_default=False)] = 0.0 @@ -170,6 +194,17 @@ class ResponseData: #: End arg for end_message print() call. end_message_end: Annotated[str, IOAttrs('eme', store_default=False)] = '\n' + #: If present, a message that should be printed after all other + #: response processing is done. + end_message_stderr: Annotated[ + str | None, IOAttrs('em2', store_default=False) + ] = None + + #: End arg for end_message print() call. + end_message_stderr_end: Annotated[ + str, IOAttrs('em2e', store_default=False) + ] = '\n' + #: If present, this command is run with these args at the end of #: response processing. end_command: Annotated[ diff --git a/dist/ba_data/python/bacommon/build.py b/dist/ba_data/python/bacommon/build.py index 7e26ed5..6d440f7 100644 --- a/dist/ba_data/python/bacommon/build.py +++ b/dist/ba_data/python/bacommon/build.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to game builds.""" +"""Functionality related to game builds. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations diff --git a/dist/ba_data/python/bacommon/classic/__init__.py b/dist/ba_data/python/bacommon/classic/__init__.py new file mode 100644 index 0000000..fbf3bcb --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/__init__.py @@ -0,0 +1,71 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Functionality related to bombsquad classic. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from bacommon.classic._account import ( + ClassicLiveAccountClientData, +) +from bacommon.classic._classic import ( + TOKENS1_COUNT, + TOKENS2_COUNT, + TOKENS3_COUNT, + TOKENS4_COUNT, +) +from bacommon.classic._chest import ( + ClassicChestAppearance, + ClassicChestDisplayItem, +) +from bacommon.classic._msg import ( + GetClassicLeaguePresidentButtonInfoMessage, + GetClassicLeaguePresidentButtonInfoResponse, + ChestInfoMessage, + ChestInfoResponse, + GetClassicPurchasesMessage, + GetClassicPurchasesResponse, + GlobalProfileCheckMessage, + GlobalProfileCheckResponse, + InboxRequestMessage, + InboxRequestResponse, + LegacyRequest, + LegacyResponse, + PrivatePartyMessage, + PrivatePartyResponse, + ScoreSubmitMessage, + ScoreSubmitResponse, + SendInfoMessage, + SendInfoResponse, +) + +__all__ = [ + 'ChestInfoMessage', + 'ChestInfoResponse', + 'ClassicLiveAccountClientData', + 'ClassicChestAppearance', + 'ClassicChestDisplayItem', + 'GetClassicLeaguePresidentButtonInfoMessage', + 'GetClassicLeaguePresidentButtonInfoResponse', + 'GetClassicPurchasesMessage', + 'GetClassicPurchasesResponse', + 'GlobalProfileCheckMessage', + 'GlobalProfileCheckResponse', + 'InboxRequestMessage', + 'InboxRequestResponse', + 'LegacyRequest', + 'LegacyResponse', + 'PrivatePartyMessage', + 'PrivatePartyResponse', + 'ScoreSubmitMessage', + 'ScoreSubmitResponse', + 'SendInfoMessage', + 'SendInfoResponse', + 'TOKENS1_COUNT', + 'TOKENS2_COUNT', + 'TOKENS3_COUNT', + 'TOKENS4_COUNT', +] diff --git a/dist/ba_data/python/bacommon/classic/_account.py b/dist/ba_data/python/bacommon/classic/_account.py new file mode 100644 index 0000000..41460f5 --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/_account.py @@ -0,0 +1,83 @@ +# Released under the MIT License. See LICENSE for details. +# +"""BombSquad specific bits.""" + +from __future__ import annotations + +import datetime +from enum import Enum +from dataclasses import dataclass +from typing import Annotated + +from efro.dataclassio import ioprepped, IOAttrs +from bacommon.classic._chest import ClassicChestAppearance + + +@ioprepped +@dataclass +class ClassicLiveAccountClientData: + """Live account data fed to the client in the bs classic app mode.""" + + @dataclass + class Chest: + """A lovely chest.""" + + appearance: Annotated[ + ClassicChestAppearance, + IOAttrs('a', enum_fallback=ClassicChestAppearance.UNKNOWN), + ] + create_time: Annotated[datetime.datetime, IOAttrs('c')] + unlock_time: Annotated[datetime.datetime, IOAttrs('t')] + unlock_tokens: Annotated[int, IOAttrs('k')] + ad_allow_time: Annotated[datetime.datetime | None, IOAttrs('at')] + + class LeagueType(Enum): + """Type of league we are in.""" + + BRONZE = 'b' + SILVER = 's' + GOLD = 'g' + DIAMOND = 'd' + + class Flag(Enum): + """Flags set for our account.""" + + ASK_FOR_REVIEW = 'r' + + class StoreStyle(Enum): + """Special looks for the store.""" + + NORMAL = 'n' + SANTA = 's' + + tickets: Annotated[int, IOAttrs('ti')] + + tokens: Annotated[int, IOAttrs('to')] + gold_pass: Annotated[bool, IOAttrs('g')] + remove_ads: Annotated[bool, IOAttrs('r')] + + achievements: Annotated[int, IOAttrs('a')] + achievements_total: Annotated[int, IOAttrs('at')] + + league_type: Annotated[LeagueType | None, IOAttrs('lt')] + league_num: Annotated[int | None, IOAttrs('ln')] + league_rank: Annotated[int | None, IOAttrs('lr')] + + level: Annotated[int, IOAttrs('lv')] + xp: Annotated[int, IOAttrs('xp')] + xpmax: Annotated[int, IOAttrs('xpm')] + + inbox_count: Annotated[int, IOAttrs('ibc')] + inbox_count_is_max: Annotated[bool, IOAttrs('ibcm')] + inbox_contains_prize: Annotated[bool, IOAttrs('icp')] + + chests: Annotated[dict[str, Chest], IOAttrs('c')] + + # State id of our purchases for builds 22459+. + purchases_state: Annotated[str | None, IOAttrs('p')] + + flags: Annotated[set[Flag], IOAttrs('f', soft_default_factory=set)] + + store_style: Annotated[ + StoreStyle, IOAttrs('s', enum_fallback=StoreStyle.NORMAL) + ] diff --git a/dist/ba_data/python/bacommon/classic/_chest.py b/dist/ba_data/python/bacommon/classic/_chest.py new file mode 100644 index 0000000..849e9af --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/_chest.py @@ -0,0 +1,67 @@ +# Released under the MIT License. See LICENSE for details. +# +"""BombSquad specific bits.""" + +from __future__ import annotations + +from enum import Enum +from typing import assert_never, Annotated, override +from dataclasses import dataclass + +from efro.dataclassio import ioprepped, IOAttrs +import bacommon.displayitem as ditm + + +class ClassicChestAppearance(Enum): + """Appearances bombsquad classic chests can have.""" + + UNKNOWN = 'u' + DEFAULT = 'd' + L1 = 'l1' + L2 = 'l2' + L3 = 'l3' + L4 = 'l4' + L5 = 'l5' + L6 = 'l6' + + @property + def pretty_name(self) -> str: + """Pretty name for the chest in English.""" + # pylint: disable=too-many-return-statements + cls = ClassicChestAppearance + + if self is cls.UNKNOWN: + return 'Unknown Chest' + if self is cls.DEFAULT: + return 'Chest' + if self is cls.L1: + return 'L1 Chest' + if self is cls.L2: + return 'L2 Chest' + if self is cls.L3: + return 'L3 Chest' + if self is cls.L4: + return 'L4 Chest' + if self is cls.L5: + return 'L5 Chest' + if self is cls.L6: + return 'L6 Chest' + + assert_never(self) + + +@ioprepped +@dataclass +class ClassicChestDisplayItem(ditm.Item): + """Display a chest.""" + + appearance: Annotated[ClassicChestAppearance, IOAttrs('a')] + + @override + @classmethod + def get_type_id(cls) -> ditm.ItemTypeID: + return ditm.ItemTypeID.CHEST + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + return self.appearance.pretty_name, [] diff --git a/dist/ba_data/python/bacommon/classic/_classic.py b/dist/ba_data/python/bacommon/classic/_classic.py new file mode 100644 index 0000000..e6eb11b --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/_classic.py @@ -0,0 +1,9 @@ +# Released under the MIT License. See LICENSE for details. +# +"""BombSquad specific bits.""" + +# Token counts for our various packs. +TOKENS1_COUNT = 50 +TOKENS2_COUNT = 500 +TOKENS3_COUNT = 1200 +TOKENS4_COUNT = 2600 diff --git a/dist/ba_data/python/bacommon/classic/_displayitem.py b/dist/ba_data/python/bacommon/classic/_displayitem.py new file mode 100644 index 0000000..917aa24 --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/_displayitem.py @@ -0,0 +1,28 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Display-item bits of classic.""" + +# from __future__ import annotations + +# from enum import Enum +# from typing import assert_never, Annotated, override +# from dataclasses import dataclass + +# from efro.dataclassio import ioprepped, IOAttrs +# import bacommon.displayitem as ditm + +# @ioprepped +# @dataclass +# class ClassicCharacterDisplayItem(ditm.Item): +# """Display a character.""" + +# : Annotated[ClassicChestAppearance, IOAttrs('a')] + +# @override +# @classmethod +# def get_type_id(cls) -> ditm.ItemTypeID: +# return ditm.ItemTypeID.CHEST + +# @override +# def get_description(self) -> tuple[str, list[tuple[str, str]]]: +# return self.appearance.pretty_name, [] diff --git a/dist/ba_data/python/bacommon/classic/_msg.py b/dist/ba_data/python/bacommon/classic/_msg.py new file mode 100644 index 0000000..198e8e4 --- /dev/null +++ b/dist/ba_data/python/bacommon/classic/_msg.py @@ -0,0 +1,249 @@ +# Released under the MIT License. See LICENSE for details. +# +"""BombSquad specific bits.""" + +from __future__ import annotations + +import datetime +from dataclasses import dataclass, field +from typing import Annotated, override + +from efro.dataclassio import ioprepped, IOAttrs +from efro.message import Message, Response + +import bacommon.displayitem as ditm +import bacommon.clouddialog as cdlg +import bacommon.clienteffect as clfx +from bacommon.classic._chest import ClassicChestAppearance + + +@ioprepped +@dataclass +class GetClassicLeaguePresidentButtonInfoMessage(Message): + """Curious who is president of my league?..""" + + season: Annotated[str | None, IOAttrs('s')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [GetClassicLeaguePresidentButtonInfoResponse] + + +@ioprepped +@dataclass +class GetClassicLeaguePresidentButtonInfoResponse(Response): + """Here's that info about the president you asked for boss.""" + + # Lstr for the name shown on the button. + name: Annotated[str | None, IOAttrs('n')] + + +@ioprepped +@dataclass +class GetClassicPurchasesMessage(Message): + """Asking for current account's classic purchases.""" + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [GetClassicPurchasesResponse] + + +@ioprepped +@dataclass +class GetClassicPurchasesResponse(Response): + """Here's those classic purchases ya asked for boss.""" + + purchases: Annotated[set[str], IOAttrs('p')] + + +@ioprepped +@dataclass +class GlobalProfileCheckMessage(Message): + """Is this global profile name available?""" + + name: Annotated[str, IOAttrs('n')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [GlobalProfileCheckResponse] + + +@ioprepped +@dataclass +class GlobalProfileCheckResponse(Response): + """Here's that profile check ya asked for boss.""" + + available: Annotated[bool, IOAttrs('a')] + ticket_cost: Annotated[int, IOAttrs('tc')] + + +@ioprepped +@dataclass +class InboxRequestMessage(Message): + """Message requesting our inbox.""" + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [InboxRequestResponse] + + +@ioprepped +@dataclass +class InboxRequestResponse(Response): + """Here's that inbox contents you asked for, boss.""" + + wrappers: Annotated[list[cdlg.Wrapper], IOAttrs('w')] + + # Printable error if something goes wrong. + error: Annotated[str | None, IOAttrs('e')] = None + + +@ioprepped +@dataclass +class LegacyRequest(Message): + """A generic request for the legacy master server.""" + + request: Annotated[str, IOAttrs('r')] + request_type: Annotated[str, IOAttrs('t')] + user_agent_string: Annotated[str, IOAttrs('u')] + data: Annotated[str, IOAttrs('d')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [LegacyResponse] + + +@ioprepped +@dataclass +class LegacyResponse(Response): + """Response for generic legacy request.""" + + data: Annotated[str | None, IOAttrs('d')] + zipped: Annotated[bool, IOAttrs('z')] + + +@ioprepped +@dataclass +class ChestInfoMessage(Message): + """Request info about a chest.""" + + chest_id: Annotated[str, IOAttrs('i')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [ChestInfoResponse] + + +@ioprepped +@dataclass +class ChestInfoResponse(Response): + """Here's that chest info you asked for, boss.""" + + @dataclass + class Chest: + """A lovely chest.""" + + @dataclass + class PrizeSet: + """A possible set of prizes for this chest.""" + + weight: Annotated[float, IOAttrs('w')] + contents: Annotated[list[ditm.Wrapper], IOAttrs('c')] + + appearance: Annotated[ + ClassicChestAppearance, + IOAttrs('a', enum_fallback=ClassicChestAppearance.UNKNOWN), + ] + + # How much it costs to unlock *now*. + unlock_tokens: Annotated[int, IOAttrs('tk')] + + # When it unlocks on its own. + unlock_time: Annotated[datetime.datetime, IOAttrs('t')] + + # Possible prizes we contain. + prizesets: Annotated[list[PrizeSet], IOAttrs('p')] + + # Are ads allowed now? + ad_allow: Annotated[bool, IOAttrs('aa')] + + chest: Annotated[Chest | None, IOAttrs('c')] + user_tokens: Annotated[int | None, IOAttrs('t')] + + +@ioprepped +@dataclass +class PrivatePartyMessage(Message): + """Message asking about info we need for private-party UI.""" + + need_datacode: Annotated[bool, IOAttrs('d')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [PrivatePartyResponse] + + +@ioprepped +@dataclass +class PrivatePartyResponse(Response): + """Here's that private party UI info you asked for, boss.""" + + success: Annotated[bool, IOAttrs('s')] + tokens: Annotated[int, IOAttrs('t')] + gold_pass: Annotated[bool, IOAttrs('g')] + datacode: Annotated[str | None, IOAttrs('d')] + + +@ioprepped +@dataclass +class ScoreSubmitMessage(Message): + """Let the server know we got some score in something.""" + + score_token: Annotated[str, IOAttrs('t')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [ScoreSubmitResponse] + + +@ioprepped +@dataclass +class ScoreSubmitResponse(Response): + """Did something to that inbox entry, boss.""" + + # Things we should show on our end. + effects: Annotated[list[clfx.Effect], IOAttrs('fx')] + + +@ioprepped +@dataclass +class SendInfoMessage(Message): + """User is using the send-info function.""" + + description: Annotated[str, IOAttrs('c')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [SendInfoResponse] + + +@ioprepped +@dataclass +class SendInfoResponse(Response): + """Response to sending info to the server.""" + + handled: Annotated[bool, IOAttrs('v')] + message: Annotated[str | None, IOAttrs('m', store_default=False)] = None + effects: Annotated[list[clfx.Effect], IOAttrs('e', store_default=False)] = ( + field(default_factory=list) + ) + legacy_code: Annotated[str | None, IOAttrs('l', store_default=False)] = None diff --git a/dist/ba_data/python/bacommon/clienteffect.py b/dist/ba_data/python/bacommon/clienteffect.py new file mode 100644 index 0000000..aa9ce5a --- /dev/null +++ b/dist/ba_data/python/bacommon/clienteffect.py @@ -0,0 +1,224 @@ +# Released under the MIT License. See LICENSE for details. +# +"""ClientEffect related functionality. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from __future__ import annotations + +import datetime +from enum import Enum +from dataclasses import dataclass, field +from typing import Annotated, override, assert_never + +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType + + +class EffectTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + LEGACY_SCREEN_MESSAGE = 'm' + SCREEN_MESSAGE = 'sm' + SOUND = 's' + DELAY = 'd' + CHEST_WAIT_TIME_ANIMATION = 't' + TICKETS_ANIMATION = 'ta' + TOKENS_ANIMATION = 'toa' + + +class Effect(IOMultiType[EffectTypeID]): + """Something that can happen on the client. + + This can include screen messages, sounds, visual effects, etc. + """ + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: EffectTypeID) -> type[Effect]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + # pylint: disable=too-many-return-statements + + t = EffectTypeID + if type_id is t.UNKNOWN: + return Unknown + if type_id is t.LEGACY_SCREEN_MESSAGE: + return LegacyScreenMessage + if type_id is t.SCREEN_MESSAGE: + return ScreenMessage + if type_id is t.SOUND: + return PlaySound + if type_id is t.DELAY: + return Delay + if type_id is t.CHEST_WAIT_TIME_ANIMATION: + return ChestWaitTimeAnimation + if type_id is t.TICKETS_ANIMATION: + return TicketsAnimation + if type_id is t.TOKENS_ANIMATION: + return TokensAnimation + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> Effect: + # If we encounter some future message type we don't know + # anything about, drop in a placeholder. + return Unknown() + + +@ioprepped +@dataclass +class Unknown(Effect): + """Fallback substitute for types we don't recognize.""" + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.UNKNOWN + + +@ioprepped +@dataclass +class LegacyScreenMessage(Effect): + """Display a screen-message (Legacy version). + + This will be processed as an Lstr with translation category + 'serverResponses'. + + When possible, migrate to using :class:`ScreenMessage`. + """ + + message: Annotated[str, IOAttrs('m')] + subs: Annotated[list[str], IOAttrs('s', store_default=False)] = field( + default_factory=list + ) + color: Annotated[ + tuple[float, float, float], IOAttrs('c', store_default=False) + ] = (1.0, 1.0, 1.0) + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.LEGACY_SCREEN_MESSAGE + + +@ioprepped +@dataclass +class ScreenMessage(Effect): + """Display a screen-message. + + Supported on engine build 22606 or newer. + + This version does no translation by default (expecting translation + to happen server-side). Pass a Lstr json string and set is_lstr=True + for client-side translation. + """ + + message: Annotated[str, IOAttrs('m')] + color: Annotated[ + tuple[float, float, float], IOAttrs('c', store_default=False) + ] = (1.0, 1.0, 1.0) + is_lstr: Annotated[bool, IOAttrs('l', store_default=False)] = False + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.SCREEN_MESSAGE + + +class Sound(Enum): + """Sounds that can be played.""" + + UNKNOWN = 'u' + CASH_REGISTER = 'c' + ERROR = 'e' + POWER_DOWN = 'p' + GUN_COCKING = 'g' + + +@ioprepped +@dataclass +class PlaySound(Effect): + """Play a sound.""" + + sound: Annotated[Sound, IOAttrs('s', enum_fallback=Sound.UNKNOWN)] + volume: Annotated[float, IOAttrs('v', store_default=False)] = 1.0 + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.SOUND + + +@ioprepped +@dataclass +class ChestWaitTimeAnimation(Effect): + """Animate chest wait time changing.""" + + chestid: Annotated[str, IOAttrs('c')] + duration: Annotated[float, IOAttrs('u')] + startvalue: Annotated[datetime.datetime, IOAttrs('o')] + endvalue: Annotated[datetime.datetime, IOAttrs('n')] + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.CHEST_WAIT_TIME_ANIMATION + + +@ioprepped +@dataclass +class TicketsAnimation(Effect): + """Animate tickets count.""" + + duration: Annotated[float, IOAttrs('u')] + startvalue: Annotated[int, IOAttrs('s')] + endvalue: Annotated[int, IOAttrs('e')] + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.TICKETS_ANIMATION + + +@ioprepped +@dataclass +class TokensAnimation(Effect): + """Animate tokens count.""" + + duration: Annotated[float, IOAttrs('u')] + startvalue: Annotated[int, IOAttrs('s')] + endvalue: Annotated[int, IOAttrs('e')] + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.TOKENS_ANIMATION + + +@ioprepped +@dataclass +class Delay(Effect): + """Delay effect processing.""" + + seconds: Annotated[float, IOAttrs('s')] + + @override + @classmethod + def get_type_id(cls) -> EffectTypeID: + return EffectTypeID.DELAY diff --git a/dist/ba_data/python/bacommon/cloud.py b/dist/ba_data/python/bacommon/cloud.py index 6a58091..1895a66 100644 --- a/dist/ba_data/python/bacommon/cloud.py +++ b/dist/ba_data/python/bacommon/cloud.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to cloud functionality.""" +"""Cloud related functionality. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations @@ -10,9 +16,13 @@ from typing import TYPE_CHECKING, Annotated, override from efro.message import Message, Response from efro.dataclassio import ioprepped, IOAttrs +from bacommon.analytics import AnalyticsEvent from bacommon.securedata import SecureDataChecker from bacommon.transfer import DirectoryManifest from bacommon.login import LoginType +from bacommon.docui import DocUIRequest, DocUIResponse +import bacommon.displayitem as ditm +import bacommon.clienteffect as clfx if TYPE_CHECKING: pass @@ -357,3 +367,98 @@ class CloudValsResponse(Response): """Here's them cloud vals ya asked for, boss.""" vals: Annotated[CloudVals, IOAttrs('v')] + + +@ioprepped +@dataclass +class ChestActionMessage(Message): + """Request action about a chest.""" + + class Action(Enum): + """Types of actions we can request.""" + + # Unlocking (for free or with tokens). + UNLOCK = 'u' + + # Watched an ad to reduce wait. + AD = 'ad' + + action: Annotated[Action, IOAttrs('a')] + + # Tokens we are paying (only applies to unlock). + token_payment: Annotated[int, IOAttrs('t')] + + chest_id: Annotated[str, IOAttrs('i')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [ChestActionResponse] + + +@ioprepped +@dataclass +class ChestActionResponse(Response): + """Here's the results of that action you asked for, boss.""" + + # Tokens that were actually charged. + tokens_charged: Annotated[int, IOAttrs('t')] = 0 + + # If present, signifies the chest has been opened and we should show + # the user this stuff that was in it. + contents: Annotated[list[ditm.Wrapper] | None, IOAttrs('c')] = None + + # If contents are present, which of the chest's prize-sets they + # represent. + prizeindex: Annotated[int, IOAttrs('i')] = 0 + + # Printable error if something goes wrong. + error: Annotated[str | None, IOAttrs('e')] = None + + # Printable warning. Shown in orange with an error sound. Does not + # mean the action failed; only that there's something to tell the + # users such as 'It looks like you are faking ad views; stop it or + # you won't have ad options anymore.' + warning: Annotated[str | None, IOAttrs('w', store_default=False)] = None + + # Printable success message. Shown in green with a cash-register + # sound. Can be used for things like successful wait reductions via + # ad views. Used in builds earlier than 22311; can remove once + # 22311+ is ubiquitous. + success_msg: Annotated[str | None, IOAttrs('s', store_default=False)] = None + + # Effects to show on the client. Replaces warning and success_msg in + # build 22311 or newer. + effects: Annotated[ + list[clfx.Effect], IOAttrs('fx', store_default=False) + ] = field(default_factory=list) + + +@ioprepped +@dataclass +class FulfillDocUIRequest(Message): + """Can a fella get a doc-ui round here?""" + + request: Annotated[DocUIRequest, IOAttrs('r')] + domain: Annotated[str, IOAttrs('d')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [FulfillDocUIResponse] + + +@ioprepped +@dataclass +class FulfillDocUIResponse(Response): + """Here's that doc-ui you asked for, boss.""" + + response: Annotated[DocUIResponse, IOAttrs('r')] + + +@ioprepped +@dataclass +class AnalyticsEventMessage(Message): + """Have a nice analytics event!""" + + event: Annotated[AnalyticsEvent, IOAttrs('e')] diff --git a/dist/ba_data/python/bacommon/clouddialog/__init__.py b/dist/ba_data/python/bacommon/clouddialog/__init__.py new file mode 100644 index 0000000..c6e6a4c --- /dev/null +++ b/dist/ba_data/python/bacommon/clouddialog/__init__.py @@ -0,0 +1,29 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Functionality related to cloud-dialogs. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from bacommon.clouddialog._clouddialog import ( + CloudDialogTypeID, + CloudDialog, + Unknown, + Wrapper, + Action, + ActionMessage, + ActionResponse, +) + +__all__ = [ + 'CloudDialogTypeID', + 'CloudDialog', + 'Unknown', + 'Wrapper', + 'Action', + 'ActionMessage', + 'ActionResponse', +] diff --git a/dist/ba_data/python/bacommon/clouddialog/_clouddialog.py b/dist/ba_data/python/bacommon/clouddialog/_clouddialog.py new file mode 100644 index 0000000..4ec1015 --- /dev/null +++ b/dist/ba_data/python/bacommon/clouddialog/_clouddialog.py @@ -0,0 +1,142 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Simple cloud-defined UIs for things like notifications. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from __future__ import annotations + +import datetime +from enum import Enum +from dataclasses import dataclass +from typing import Annotated, override, assert_never + +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType +from efro.message import Message, Response + +import bacommon.clienteffect as clfx + + +class CloudDialogTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + BASIC = 'b' + + +class CloudDialog(IOMultiType[CloudDialogTypeID]): + """Small self-contained ui bit provided by the cloud. + + These take care of updating and/or dismissing themselves based on + user input. Useful for things such as inbox messages. For more + complex UI construction, look at :mod:`bacommon.docui`. + """ + + @override + @classmethod + def get_type_id(cls) -> CloudDialogTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: CloudDialogTypeID) -> type[CloudDialog]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = CloudDialogTypeID + + if type_id is t.UNKNOWN: + return Unknown + + if type_id is t.BASIC: + from bacommon.clouddialog.basic import BasicCloudDialog + + return BasicCloudDialog + + # Make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> CloudDialog: + # If we encounter some future message type we don't know + # anything about, drop in a placeholder. + return Unknown() + + +@ioprepped +@dataclass +class Unknown(CloudDialog): + """Fallback type for unrecognized entries.""" + + @override + @classmethod + def get_type_id(cls) -> CloudDialogTypeID: + return CloudDialogTypeID.UNKNOWN + + +@ioprepped +@dataclass +class Wrapper: + """Wrapper for a CloudDialog and its common data.""" + + id: Annotated[str, IOAttrs('i')] + createtime: Annotated[datetime.datetime, IOAttrs('c')] + ui: Annotated[CloudDialog, IOAttrs('e')] + + +class Action(Enum): + """Types of actions we can run.""" + + BUTTON_PRESS_POSITIVE = 'p' + BUTTON_PRESS_NEGATIVE = 'n' + + +@ioprepped +@dataclass +class ActionMessage(Message): + """Do something to a client ui.""" + + id: Annotated[str, IOAttrs('i')] + action: Annotated[Action, IOAttrs('a')] + + @override + @classmethod + def get_response_types(cls) -> list[type[Response] | None]: + return [ActionResponse] + + +@ioprepped +@dataclass +class ActionResponse(Response): + """Did something to that inbox entry, boss.""" + + class ErrorType(Enum): + """Types of errors that may have occurred.""" + + # Probably a future error type we don't recognize. + UNKNOWN = 'u' + + # Something went wrong on the server, but specifics are not + # relevant. + INTERNAL = 'i' + + # The entry expired on the server. In various cases such as 'ok' + # buttons this can generally be ignored. + EXPIRED = 'e' + + error_type: Annotated[ + ErrorType | None, IOAttrs('et', enum_fallback=ErrorType.UNKNOWN) + ] + + # User facing error message in the case of errors. + error_message: Annotated[str | None, IOAttrs('em')] + + effects: Annotated[list[clfx.Effect], IOAttrs('fx')] diff --git a/dist/ba_data/python/bacommon/clouddialog/basic.py b/dist/ba_data/python/bacommon/clouddialog/basic.py new file mode 100644 index 0000000..635b2fb --- /dev/null +++ b/dist/ba_data/python/bacommon/clouddialog/basic.py @@ -0,0 +1,233 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Basic cloud-dialog.""" + +from __future__ import annotations + +import datetime +from enum import Enum +from dataclasses import dataclass, field +from typing import Annotated, override, assert_never + +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType + +import bacommon.displayitem as ditm +from bacommon.clouddialog._clouddialog import CloudDialog, CloudDialogTypeID + + +class ComponentTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + TEXT = 't' + LINK = 'l' + BS_CLASSIC_TOURNEY_RESULT = 'ct' + DISPLAY_ITEMS = 'di' + EXPIRE_TIME = 'd' + + +class Component(IOMultiType[ComponentTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: ComponentTypeID) -> type[Component]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = ComponentTypeID + if type_id is t.UNKNOWN: + return Unknown + if type_id is t.TEXT: + return Text + if type_id is t.LINK: + return Link + if type_id is t.BS_CLASSIC_TOURNEY_RESULT: + return ClassicTourneyResult + if type_id is t.DISPLAY_ITEMS: + return DisplayItems + if type_id is t.EXPIRE_TIME: + return ExpireTime + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> Component: + # If we encounter some future message type we don't know + # anything about, drop in a placeholder. + return Unknown() + + +@ioprepped +@dataclass +class Unknown(Component): + """An unknown basic client component type. + + In practice these should never show up since the master-server + generates these on the fly for the client and so should not send + clients one they can't digest. + """ + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.UNKNOWN + + +@ioprepped +@dataclass +class Text(Component): + """Show some text in the inbox message.""" + + text: Annotated[str, IOAttrs('t')] + subs: Annotated[list[str], IOAttrs('s', store_default=False)] = field( + default_factory=list + ) + scale: Annotated[float, IOAttrs('sc', store_default=False)] = 1.0 + color: Annotated[ + tuple[float, float, float, float], IOAttrs('c', store_default=False) + ] = (1.0, 1.0, 1.0, 1.0) + spacing_top: Annotated[float, IOAttrs('st', store_default=False)] = 0.0 + spacing_bottom: Annotated[float, IOAttrs('sb', store_default=False)] = 0.0 + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.TEXT + + +@ioprepped +@dataclass +class Link(Component): + """Show a link in the inbox message.""" + + url: Annotated[str, IOAttrs('u')] + label: Annotated[str, IOAttrs('l')] + subs: Annotated[list[str], IOAttrs('s', store_default=False)] = field( + default_factory=list + ) + spacing_top: Annotated[float, IOAttrs('st', store_default=False)] = 0.0 + spacing_bottom: Annotated[float, IOAttrs('sb', store_default=False)] = 0.0 + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.LINK + + +@ioprepped +@dataclass +class ClassicTourneyResult(Component): + """Show info about a classic tourney.""" + + tournament_id: Annotated[str, IOAttrs('t')] + game: Annotated[str, IOAttrs('g')] + players: Annotated[int, IOAttrs('p')] + rank: Annotated[int, IOAttrs('r')] + trophy: Annotated[str | None, IOAttrs('tr')] + prizes: Annotated[list[ditm.Wrapper], IOAttrs('pr')] + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.BS_CLASSIC_TOURNEY_RESULT + + +@ioprepped +@dataclass +class DisplayItems(Component): + """Show some display-items.""" + + items: Annotated[list[ditm.Wrapper], IOAttrs('d')] + width: Annotated[float, IOAttrs('w')] = 100.0 + spacing_top: Annotated[float, IOAttrs('st', store_default=False)] = 0.0 + spacing_bottom: Annotated[float, IOAttrs('sb', store_default=False)] = 0.0 + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.DISPLAY_ITEMS + + +@ioprepped +@dataclass +class ExpireTime(Component): + """Show expire-time.""" + + time: Annotated[datetime.datetime, IOAttrs('d')] + spacing_top: Annotated[float, IOAttrs('st', store_default=False)] = 0.0 + spacing_bottom: Annotated[float, IOAttrs('sb', store_default=False)] = 0.0 + + @override + @classmethod + def get_type_id(cls) -> ComponentTypeID: + return ComponentTypeID.EXPIRE_TIME + + +class ButtonLabel(Enum): + """Distinct button labels we support.""" + + UNKNOWN = 'u' + OK = 'o' + APPLY = 'a' + CANCEL = 'c' + ACCEPT = 'ac' + DECLINE = 'dn' + IGNORE = 'ig' + CLAIM = 'cl' + DISCARD = 'd' + + +class InteractionStyle(Enum): + """Overall interaction styles we support.""" + + UNKNOWN = 'u' + BUTTON_POSITIVE = 'p' + BUTTON_POSITIVE_NEGATIVE = 'pn' + + +@ioprepped +@dataclass +class BasicCloudDialog(CloudDialog): + """A basic UI for the client.""" + + components: Annotated[list[Component], IOAttrs('s')] + + interaction_style: Annotated[ + InteractionStyle, IOAttrs('i', enum_fallback=InteractionStyle.UNKNOWN) + ] = InteractionStyle.BUTTON_POSITIVE + + button_label_positive: Annotated[ + ButtonLabel, IOAttrs('p', enum_fallback=ButtonLabel.UNKNOWN) + ] = ButtonLabel.OK + + button_label_negative: Annotated[ + ButtonLabel, IOAttrs('n', enum_fallback=ButtonLabel.UNKNOWN) + ] = ButtonLabel.CANCEL + + @override + @classmethod + def get_type_id(cls) -> CloudDialogTypeID: + return CloudDialogTypeID.BASIC + + def contains_unknown_elements(self) -> bool: + """Whether something within us is an unknown type or enum.""" + return ( + self.interaction_style is InteractionStyle.UNKNOWN + or self.button_label_positive is ButtonLabel.UNKNOWN + or self.button_label_negative is ButtonLabel.UNKNOWN + or any( + c.get_type_id() is ComponentTypeID.UNKNOWN + for c in self.components + ) + ) diff --git a/dist/ba_data/python/bacommon/displayitem.py b/dist/ba_data/python/bacommon/displayitem.py new file mode 100644 index 0000000..566695b --- /dev/null +++ b/dist/ba_data/python/bacommon/displayitem.py @@ -0,0 +1,198 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Functionality for displaying currencies, prizes, owned items, etc. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from __future__ import annotations + +from enum import Enum +from dataclasses import dataclass +from typing import Annotated, override, assert_never + +from efro.util import pairs_to_flat +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType + + +class ItemTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + TICKETS = 't' + TICKETS_PURPLE = 'tp' + TOKENS = 'k' + TEST = 's' + CHEST = 'c' + + +class Item(IOMultiType[ItemTypeID]): + """Some amount of something that can be shown or described. + + Used to depict chest contents, inventory, rewards, etc. + """ + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: ItemTypeID) -> type[Item]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = ItemTypeID + if type_id is t.UNKNOWN: + return Unknown + if type_id is t.TICKETS: + return Tickets + if type_id is t.TICKETS_PURPLE: + return PurpleTickets + if type_id is t.TOKENS: + return Tokens + if type_id is t.TEST: + return Test + if type_id is t.CHEST: + from bacommon.classic._chest import ClassicChestDisplayItem + + return ClassicChestDisplayItem + + # Important to make sure we provide all types. + assert_never(type_id) + + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + """Return a string description and subs for the item. + + Will be translated on the client using the 'displayItemNames' + Lstr category. + + These decriptions are baked into the display-item wrapper and + should be accessed from there when available. This allows + clients to give descriptions even for newer display item types + they don't recognize. + """ + raise NotImplementedError() + + # Implement fallbacks so client can digest item lists even if they + # contain unrecognized stuff. The wrapper contains basic + # baked down info that they can still use in such cases. + @override + @classmethod + def get_unknown_type_fallback(cls) -> Item: + return Unknown() + + +@ioprepped +@dataclass +class Unknown(Item): + """Something we don't know how to display.""" + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + return ItemTypeID.UNKNOWN + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + import logging + + # Make noise but don't break. + logging.exception( + 'Unknown.get_description() should never be called.' + ' Always access descriptions on the display-item wrapper.' + ) + return 'Unknown', [] + + +@ioprepped +@dataclass +class Tickets(Item): + """Some amount of tickets.""" + + count: Annotated[int, IOAttrs('c')] + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + return ItemTypeID.TICKETS + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + return '${C} Tickets', [('${C}', str(self.count))] + + +@ioprepped +@dataclass +class PurpleTickets(Item): + """Some amount of purple tickets.""" + + count: Annotated[int, IOAttrs('c')] + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + return ItemTypeID.TICKETS_PURPLE + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + return '${C} Purple Tickets', [('${C}', str(self.count))] + + +@ioprepped +@dataclass +class Tokens(Item): + """Some amount of tokens.""" + + count: Annotated[int, IOAttrs('c')] + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + return ItemTypeID.TOKENS + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + return '${C} Tokens', [('${C}', str(self.count))] + + +@ioprepped +@dataclass +class Test(Item): + """Fills usable space for a display-item - good for calibration.""" + + @override + @classmethod + def get_type_id(cls) -> ItemTypeID: + return ItemTypeID.TEST + + @override + def get_description(self) -> tuple[str, list[tuple[str, str]]]: + return 'Test', [] + + +@ioprepped +@dataclass +class Wrapper: + """Wraps a display-item and some baked out info. + + This allows clients to at least give descriptions of new + display-item types they may not have locally. + """ + + item: Annotated[Item, IOAttrs('i')] + description: Annotated[str, IOAttrs('d')] + description_subs: Annotated[list[str] | None, IOAttrs('s')] + + @classmethod + def for_item(cls, item: Item) -> Wrapper: + """Convenience method to wrap a display-item.""" + desc, subs = item.get_description() + return Wrapper(item, desc, pairs_to_flat(subs)) diff --git a/dist/ba_data/python/bacommon/docui/__init__.py b/dist/ba_data/python/bacommon/docui/__init__.py new file mode 100644 index 0000000..9d72511 --- /dev/null +++ b/dist/ba_data/python/bacommon/docui/__init__.py @@ -0,0 +1,30 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Declarative UI system. + +A high level way to build UIs that lives as a layer on top of engine +apis such as :mod:`bauiv1`. UIs can easily be serialized to json data +and be provided by webservers or other local or remote sources. +""" + +from bacommon.docui._docui import ( + DocUIRequest, + DocUIRequestTypeID, + UnknownDocUIRequest, + DocUIResponse, + DocUIResponseTypeID, + UnknownDocUIResponse, + DocUIWebRequest, + DocUIWebResponse, +) + +__all__ = [ + 'DocUIRequest', + 'DocUIRequestTypeID', + 'UnknownDocUIRequest', + 'DocUIResponse', + 'DocUIResponseTypeID', + 'UnknownDocUIResponse', + 'DocUIWebRequest', + 'DocUIWebResponse', +] diff --git a/dist/ba_data/python/bacommon/docui/_docui.py b/dist/ba_data/python/bacommon/docui/_docui.py new file mode 100644 index 0000000..d7b8419 --- /dev/null +++ b/dist/ba_data/python/bacommon/docui/_docui.py @@ -0,0 +1,172 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Version 1 of our doc-ui system.""" + +from __future__ import annotations + +from enum import Enum +from dataclasses import dataclass +from typing import override, assert_never, TYPE_CHECKING, Annotated + +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType +from bacommon.locale import Locale + +if TYPE_CHECKING: + pass + + +class DocUIRequestTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + V1 = 'v1' + + +class DocUIRequest(IOMultiType[DocUIRequestTypeID]): + """A request for some UI.""" + + @override + @classmethod + def get_type_id(cls) -> DocUIRequestTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: DocUIRequestTypeID) -> type[DocUIRequest]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = DocUIRequestTypeID + if type_id is t.UNKNOWN: + return UnknownDocUIRequest + if type_id is t.V1: + from bacommon.docui.v1 import Request + + return Request + + # Make sure we cover all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> DocUIRequest: + # If we encounter some future type we don't know anything about, + # drop in a placeholder. + return UnknownDocUIRequest() + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + +@ioprepped +@dataclass +class UnknownDocUIRequest(DocUIRequest): + """Fallback type for unrecognized UI types. + + Will show the client a 'cannot display this UI' placeholder request. + """ + + @override + @classmethod + def get_type_id(cls) -> DocUIRequestTypeID: + return DocUIRequestTypeID.UNKNOWN + + +class DocUIResponseTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + V1 = 'v1' + + +class DocUIResponse(IOMultiType[DocUIResponseTypeID]): + """A UI provied in response to a :class:`DocUIRequest`.""" + + @override + @classmethod + def get_type_id(cls) -> DocUIResponseTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: DocUIResponseTypeID) -> type[DocUIResponse]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = DocUIResponseTypeID + if type_id is t.UNKNOWN: + return UnknownDocUIResponse + if type_id is t.V1: + from bacommon.docui.v1 import Response + + return Response + + # Make sure we cover all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> DocUIResponse: + # If we encounter some future type we don't know anything about, + # drop in a placeholder. + return UnknownDocUIResponse() + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + +@ioprepped +@dataclass +class UnknownDocUIResponse(DocUIResponse): + """Fallback type for unrecognized UI types. + + Will show the client a 'cannot display this UI' placeholder response. + """ + + @override + @classmethod + def get_type_id(cls) -> DocUIResponseTypeID: + return DocUIResponseTypeID.UNKNOWN + + +@ioprepped +@dataclass +class DocUIWebRequest: + """Complete data sent for doc-ui http requests.""" + + #: The wrapped doc-ui request. + doc_ui_request: Annotated[DocUIRequest, IOAttrs('r')] + + #: The current locale of the client. doc-ui generally deals in raw + #: strings and expects localization to happen on the server. + locale: Annotated[Locale, IOAttrs('l')] + + #: Engine build number. In some cases it may make sense to adjust + #: responses depending on available engine features. + engine_build_number: Annotated[int, IOAttrs('b')] + + +@ioprepped +@dataclass +class DocUIWebResponse: + """Complete data returned for doc-ui http requests.""" + + #: Human readable error string (if an error occurs). Either this or + #: doc_ui_response should be set; not both. + error: Annotated[str | None, IOAttrs('e', store_default=False)] = None + + #: doc-ui response. Either this or error should be set; not both. + doc_ui_response: Annotated[ + DocUIResponse | None, + IOAttrs('r', store_default=False), + ] = None diff --git a/dist/ba_data/python/bacommon/docui/v1.py b/dist/ba_data/python/bacommon/docui/v1.py new file mode 100644 index 0000000..91f8afc --- /dev/null +++ b/dist/ba_data/python/bacommon/docui/v1.py @@ -0,0 +1,783 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Version 1 doc-ui types.""" + +from __future__ import annotations + +from enum import Enum +from dataclasses import dataclass, field +from typing import Annotated, override, assert_never + +from efro.dataclassio import ioprepped, IOAttrs, IOMultiType + +import bacommon.displayitem as ditm +import bacommon.clienteffect as clfx +from bacommon.docui._docui import ( + DocUIRequest, + DocUIRequestTypeID, + DocUIResponse, + DocUIResponseTypeID, +) + + +class RequestMethod(Enum): + """Typeof of requests that can be made to doc-ui servers.""" + + #: An unknown request method. This can appear if a newer client is + #: requesting some method from an older server that is not known to + #: the server. + UNKNOWN = 'u' + + #: Fetch some resource. This can be retried and its results can + #: optionally be cached for some amount of time. + GET = 'g' + + #: Change some resource. This cannot be implicitly retried (at least + #: without deduplication), nor can it be cached. + POST = 'p' + + +@ioprepped +@dataclass +class Request(DocUIRequest): + """Full request to doc-ui.""" + + path: Annotated[str, IOAttrs('p')] + method: Annotated[ + RequestMethod, + IOAttrs('m', store_default=False, enum_fallback=RequestMethod.UNKNOWN), + ] = RequestMethod.GET + args: Annotated[dict, IOAttrs('r', store_default=False)] = field( + default_factory=dict + ) + + @override + @classmethod + def get_type_id(cls) -> DocUIRequestTypeID: + return DocUIRequestTypeID.V1 + + +class ActionTypeID(Enum): + """Type ID for each of our subclasses.""" + + BROWSE = 'b' + REPLACE = 'r' + LOCAL = 'l' + UNKNOWN = 'u' + + +class Action(IOMultiType[ActionTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> ActionTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: ActionTypeID) -> type[Action]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = ActionTypeID + if type_id is t.BROWSE: + return Browse + if type_id is t.REPLACE: + return Replace + if type_id is t.LOCAL: + return Local + if type_id is t.UNKNOWN: + return UnknownAction + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + @override + @classmethod + def get_unknown_type_fallback(cls) -> Action: + # If we encounter some future type we don't know anything about, + # drop in a placeholder. + return UnknownAction() + + +@ioprepped +@dataclass +class UnknownAction(Action): + """Action type we don't recognize.""" + + @override + @classmethod + def get_type_id(cls) -> ActionTypeID: + return ActionTypeID.UNKNOWN + + +@ioprepped +@dataclass +class Browse(Action): + """Browse to a new page in a new window.""" + + request: Annotated[Request, IOAttrs('r')] + + #: Plays a swish. + default_sound: Annotated[bool, IOAttrs('ds', store_default=False)] = True + + #: Client-effects to run immediately when the button is pressed. + #: + #: :meta private: + immediate_client_effects: Annotated[ + list[clfx.Effect], IOAttrs('fx', store_default=False) + ] = field(default_factory=list) + + #: Local action to run immediately when the button is pressed. Will + #: be handled by + #: :meth:`bauiv1lib.docui.DocUIController.local_action()`. + immediate_local_action: Annotated[ + str | None, IOAttrs('a', store_default=False) + ] = None + immediate_local_action_args: Annotated[ + dict | None, IOAttrs('aa', store_default=False) + ] = None + + @override + @classmethod + def get_type_id(cls) -> ActionTypeID: + return ActionTypeID.BROWSE + + +@ioprepped +@dataclass +class Replace(Action): + """Replace current page with a new one. + + Should be used to effectively 'modify' existing UIs by replacing + them with something slightly different. Things like scroll position + and selection will be carried across to the new layout when possible + to make for a seamless transition. + """ + + request: Annotated[Request, IOAttrs('r')] + + #: Plays a click if triggered by a button press. + default_sound: Annotated[bool, IOAttrs('ds', store_default=False)] = True + + #: Client-effects to run immediately when the button is pressed. + #: + #: :meta private: + immediate_client_effects: Annotated[ + list[clfx.Effect], IOAttrs('fx', store_default=False) + ] = field(default_factory=list) + + #: Local action to run immediately when the button is pressed. Will + #: be handled by + #: :meth:`bauiv1lib.docui.DocUIController.local_action()`. + immediate_local_action: Annotated[ + str | None, IOAttrs('a', store_default=False) + ] = None + immediate_local_action_args: Annotated[ + dict | None, IOAttrs('aa', store_default=False) + ] = None + + @override + @classmethod + def get_type_id(cls) -> ActionTypeID: + return ActionTypeID.REPLACE + + +@ioprepped +@dataclass +class Local(Action): + """Perform only local actions; no new requests or page changes.""" + + close_window: Annotated[bool, IOAttrs('c', store_default=False)] = False + + #: Plays a swish if closing the window or a click if triggered by a + #: button press. + default_sound: Annotated[bool, IOAttrs('ds', store_default=False)] = True + + #: Client-effects to run immediately when the button is pressed. + #: + #: :meta private: + immediate_client_effects: Annotated[ + list[clfx.Effect], IOAttrs('fx', store_default=False) + ] = field(default_factory=list) + + #: Local action to run immediately when the button is pressed. Will + #: be handled by + #: :meth:`bauiv1lib.docui.DocUIController.local_action()`. + immediate_local_action: Annotated[ + str | None, IOAttrs('a', store_default=False) + ] = None + immediate_local_action_args: Annotated[ + dict | None, IOAttrs('aa', store_default=False) + ] = None + + @override + @classmethod + def get_type_id(cls) -> ActionTypeID: + return ActionTypeID.LOCAL + + +class HAlign(Enum): + """Horizontal alignment.""" + + LEFT = 'l' + CENTER = 'c' + RIGHT = 'r' + + +class VAlign(Enum): + """Vertical alignment.""" + + TOP = 't' + CENTER = 'c' + BOTTOM = 'b' + + +class DecorationTypeID(Enum): + """Type ID for each of our subclasses.""" + + UNKNOWN = 'u' + TEXT = 't' + IMAGE = 'i' + DISPLAY_ITEM = 'd' + + +class Decoration(IOMultiType[DecorationTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> DecorationTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: DecorationTypeID) -> type[Decoration]: + # pylint: disable=cyclic-import + + t = DecorationTypeID + if type_id is t.UNKNOWN: + return UnknownDecoration + if type_id is t.TEXT: + return Text + if type_id is t.IMAGE: + return Image + if type_id is t.DISPLAY_ITEM: + return DisplayItem + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> Decoration: + # If we encounter some future type we don't know anything about, + # drop in a placeholder. + return UnknownDecoration() + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + +@ioprepped +@dataclass +class UnknownDecoration(Decoration): + """An unknown decoration. + + In practice these should never show up since the master-server + generates these on the fly for the client and so should not send + clients one they can't digest. + """ + + @override + @classmethod + def get_type_id(cls) -> DecorationTypeID: + return DecorationTypeID.UNKNOWN + + +@ioprepped +@dataclass +class Text(Decoration): + """Text decoration.""" + + #: Note that doc-ui accepts only raw :class:`str` values for text; + #: use :meth:`babase.Lstr.evaluate()` or whatnot for multi-language + #: support. + text: Annotated[str, IOAttrs('t')] + position: Annotated[tuple[float, float], IOAttrs('p')] + + #: Note that this effectively is max-width and max-height. + size: Annotated[tuple[float, float], IOAttrs('i')] + scale: Annotated[float, IOAttrs('s', store_default=False)] = 1.0 + h_align: Annotated[HAlign, IOAttrs('ha', store_default=False)] = ( + HAlign.CENTER + ) + v_align: Annotated[VAlign, IOAttrs('va', store_default=False)] = ( + VAlign.CENTER + ) + color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('c', store_default=False), + ] = None + flatness: Annotated[float | None, IOAttrs('f', store_default=False)] = None + shadow: Annotated[float | None, IOAttrs('sh', store_default=False)] = None + + is_lstr: Annotated[bool, IOAttrs('l', store_default=False)] = False + + highlight: Annotated[bool, IOAttrs('h', store_default=False)] = True + depth_range: Annotated[tuple[float, float] | None, IOAttrs('z')] = None + + #: Show max-width/height bounds; useful during development. + debug: Annotated[bool, IOAttrs('d', store_default=False)] = False + + @override + @classmethod + def get_type_id(cls) -> DecorationTypeID: + return DecorationTypeID.TEXT + + +@ioprepped +@dataclass +class Image(Decoration): + """Image decoration.""" + + texture: Annotated[str, IOAttrs('t')] + position: Annotated[tuple[float, float], IOAttrs('p')] + size: Annotated[tuple[float, float], IOAttrs('s')] + color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('c', store_default=False), + ] = None + h_align: Annotated[HAlign, IOAttrs('ha', store_default=False)] = ( + HAlign.CENTER + ) + v_align: Annotated[VAlign, IOAttrs('va', store_default=False)] = ( + VAlign.CENTER + ) + tint_texture: Annotated[str | None, IOAttrs('tt', store_default=False)] = ( + None + ) + tint_color: Annotated[ + tuple[float, float, float] | None, IOAttrs('tc1', store_default=False) + ] = None + tint2_color: Annotated[ + tuple[float, float, float] | None, IOAttrs('tc2', store_default=False) + ] = None + mask_texture: Annotated[str | None, IOAttrs('mt', store_default=False)] = ( + None + ) + mesh_opaque: Annotated[str | None, IOAttrs('mo', store_default=False)] = ( + None + ) + mesh_transparent: Annotated[ + str | None, IOAttrs('mn', store_default=False) + ] = None + highlight: Annotated[bool, IOAttrs('h', store_default=False)] = True + depth_range: Annotated[tuple[float, float] | None, IOAttrs('z')] = None + + @override + @classmethod + def get_type_id(cls) -> DecorationTypeID: + return DecorationTypeID.IMAGE + + +class DisplayItemStyle(Enum): + """Styles a display-item can be drawn in.""" + + #: Shows graphics and/or text fully conveying what the item is. Fits + #: in to a 4:3 box and works best with large-ish displays. + FULL = 'f' + + #: Graphics and/or text fully conveying what the item is, but + #: condensed to fit in a 2:1 box displayed at small sizes. + COMPACT = 'c' + + #: A graphics-only representation of the item (though text may be + #: used in fallback cases). Does not fully convey what the item is, + #: but instead is intended to be used alongside the item's textual + #: description. For example, some number of coins may simply display + #: a coin graphic here without the number. Draws in a 1:1 box and + #: works for large or small display. + ICON = 'i' + + +@ioprepped +@dataclass +class DisplayItem(Decoration): + """DisplayItem decoration.""" + + wrapper: Annotated[ditm.Wrapper, IOAttrs('w')] + position: Annotated[tuple[float, float], IOAttrs('p')] + size: Annotated[tuple[float, float], IOAttrs('s')] + style: Annotated[DisplayItemStyle, IOAttrs('t', store_default=False)] = ( + DisplayItemStyle.FULL + ) + text_color: Annotated[ + tuple[float, float, float] | None, IOAttrs('c', store_default=False) + ] = None + highlight: Annotated[bool, IOAttrs('h', store_default=False)] = True + depth_range: Annotated[tuple[float, float] | None, IOAttrs('z')] = None + debug: Annotated[bool, IOAttrs('d', store_default=False)] = False + + @override + @classmethod + def get_type_id(cls) -> DecorationTypeID: + return DecorationTypeID.DISPLAY_ITEM + + +class ButtonStyle(Enum): + """Styles a button can be.""" + + SQUARE = 'q' + TAB = 't' + SMALL = 's' + MEDIUM = 'm' + LARGE = 'l' + LARGER = 'xl' + BACK = 'b' + BACK_SMALL = 'bs' + SQUARE_WIDE = 'w' + + +@ioprepped +@dataclass +class Button: + """A button in our doc-ui. + + Note that size, padding, and all decorations are scaled consistently + with 'scale'. + """ + + #: Note that doc-ui accepts only raw :class:`str` values for text; + #: use :meth:`babase.Lstr.evaluate()` or whatnot for multi-language + #: support. + label: Annotated[str | None, IOAttrs('l', store_default=False)] = None + + action: Annotated[Action | None, IOAttrs('a', store_default=False)] = None + + size: Annotated[ + tuple[float, float] | None, IOAttrs('sz', store_default=False) + ] = None + color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('cl', store_default=False), + ] = None + label_color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('lc', store_default=False), + ] = None + label_flatness: Annotated[ + float | None, IOAttrs('lf', store_default=False) + ] = None + label_scale: Annotated[float | None, IOAttrs('ls', store_default=False)] = ( + None + ) + label_is_lstr: Annotated[bool, IOAttrs('ll', store_default=False)] = False + texture: Annotated[str | None, IOAttrs('tex', store_default=False)] = None + scale: Annotated[float, IOAttrs('sc', store_default=False)] = 1.0 + padding_left: Annotated[float, IOAttrs('pl', store_default=False)] = 0.0 + padding_top: Annotated[float, IOAttrs('pt', store_default=False)] = 0.0 + padding_right: Annotated[float, IOAttrs('pr', store_default=False)] = 0.0 + padding_bottom: Annotated[float, IOAttrs('pb', store_default=False)] = 0.0 + decorations: Annotated[ + list[Decoration] | None, IOAttrs('c', store_default=False) + ] = None + style: Annotated[ButtonStyle, IOAttrs('y', store_default=False)] = ( + ButtonStyle.SQUARE + ) + default: Annotated[bool, IOAttrs('df', store_default=False)] = False + selected: Annotated[bool, IOAttrs('sel', store_default=False)] = False + + icon: Annotated[str | None, IOAttrs('icn', store_default=False)] = None + icon_scale: Annotated[float | None, IOAttrs('is', store_default=False)] = ( + None + ) + icon_color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('ic', store_default=False), + ] = None + depth_range: Annotated[ + tuple[float, float] | None, IOAttrs('z', store_default=None) + ] = None + + #: Custom widget id. Will be prefixed with window id, but must be + #: unique within the window. + widget_id: Annotated[str | None, IOAttrs('i', store_default=False)] = None + + #: Draw bounds of the button. + debug: Annotated[bool, IOAttrs('d', store_default=False)] = False + + +class RowTypeID(Enum): + """Type ID for each of our subclasses.""" + + BUTTON_ROW = 'b' + UNKNOWN = 'u' + + +class Row(IOMultiType[RowTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> RowTypeID: + # Require child classes to supply this themselves. If we did a + # full type registry/lookup here it would require us to import + # everything and would prevent lazy loading. + raise NotImplementedError() + + @override + @classmethod + def get_type(cls, type_id: RowTypeID) -> type[Row]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + + t = RowTypeID + if type_id is t.UNKNOWN: + return UnknownRow + if type_id is t.BUTTON_ROW: + return ButtonRow + + # Important to make sure we provide all types. + assert_never(type_id) + + @override + @classmethod + def get_unknown_type_fallback(cls) -> Row: + # If we encounter some future type we don't know anything about, + # drop in a placeholder. + return UnknownRow() + + @override + @classmethod + def get_type_id_storage_name(cls) -> str: + return '_t' + + +@ioprepped +@dataclass +class UnknownRow(Row): + """A row type we don't have.""" + + @override + @classmethod + def get_type_id(cls) -> RowTypeID: + return RowTypeID.UNKNOWN + + +@ioprepped +@dataclass +class ButtonRow(Row): + """A row consisting of buttons.""" + + buttons: Annotated[list[Button], IOAttrs('b')] + + header_height: Annotated[float, IOAttrs('h', store_default=False)] = 0.0 + header_scale: Annotated[float, IOAttrs('hs', store_default=False)] = 1.0 + header_decorations_left: Annotated[ + list[Decoration] | None, IOAttrs('hdl', store_default=False) + ] = None + header_decorations_center: Annotated[ + list[Decoration] | None, IOAttrs('hdc', store_default=False) + ] = None + header_decorations_right: Annotated[ + list[Decoration] | None, IOAttrs('hdr', store_default=False) + ] = None + + #: Note that doc-ui accepts only raw :class:`str` values for text; + #: use :meth:`babase.Lstr.evaluate()` or whatnot for multi-language + #: support. + title: Annotated[str | None, IOAttrs('t', store_default=False)] = None + title_color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('tc', store_default=False), + ] = None + title_flatness: Annotated[ + float | None, IOAttrs('tf', store_default=False) + ] = None + title_shadow: Annotated[ + float | None, IOAttrs('ts', store_default=False) + ] = None + title_is_lstr: Annotated[bool, IOAttrs('tl', store_default=False)] = False + subtitle: Annotated[str | None, IOAttrs('s', store_default=False)] = None + subtitle_color: Annotated[ + tuple[float, float, float, float] | None, + IOAttrs('sc', store_default=False), + ] = None + subtitle_flatness: Annotated[ + float | None, IOAttrs('sf', store_default=False) + ] = None + subtitle_shadow: Annotated[ + float | None, IOAttrs('ss', store_default=False) + ] = None + subtitle_is_lstr: Annotated[bool, IOAttrs('sl', store_default=False)] = ( + False + ) + + #: Spacing between all buttons in the row. + button_spacing: Annotated[float, IOAttrs('bs', store_default=False)] = 15.0 + + #: Padding on the left of the row's horizonally-scrollable area. + padding_left: Annotated[float, IOAttrs('pl', store_default=False)] = 10.0 + #: Padding on the right of the row's horizonally-scrollable area. + padding_right: Annotated[float, IOAttrs('pr', store_default=False)] = 10.0 + #: Padding on the top of the row's horizonally-scrollable area. + padding_top: Annotated[float, IOAttrs('pt', store_default=False)] = 10.0 + #: Padding on the bottom of the row's horizonally-scrollable area. + padding_bottom: Annotated[float, IOAttrs('pb', store_default=False)] = 10.0 + + #: Extra space above the row's horizontally-scrollable area. + spacing_top: Annotated[float, IOAttrs('st', store_default=False)] = 0.0 + + #: Extra space below the row's horizontally-scrollable area. + spacing_bottom: Annotated[float, IOAttrs('sb', store_default=False)] = 0.0 + + center_content: Annotated[bool, IOAttrs('c', store_default=False)] = False + center_title: Annotated[bool, IOAttrs('ct', store_default=False)] = False + + #: If things disappear when scrolling left/right, turn this up. + simple_culling_h: Annotated[float, IOAttrs('sch', store_default=False)] = ( + 100.0 + ) + + #: Draw bounds of the overall row and individual button columns + #: (including padding). The UI will scroll to keep these areas + #: visible in their entirety when changing selection via directional + #: controls, so try to make sure all decorations for a button are + #: within these bounds. + debug: Annotated[bool, IOAttrs('d', store_default=False)] = False + + @override + @classmethod + def get_type_id(cls) -> RowTypeID: + return RowTypeID.BUTTON_ROW + + +@ioprepped +@dataclass +class Page: + """Doc-UI page version 1.""" + + #: Note that doc-ui accepts only raw :class:`str` values for text; + #: use :meth:`babase.Lstr.evaluate()` or whatnot for multi-language + #: support. + title: Annotated[str, IOAttrs('t')] + rows: Annotated[list[Row], IOAttrs('r')] + + #: If True, content smaller than the available height will be + #: centered vertically. This can look natural for certain types of + #: content such as confirmation dialogs. + center_vertically: Annotated[bool, IOAttrs('cv', store_default=False)] = ( + False + ) + + row_spacing: Annotated[float, IOAttrs('s', store_default=False)] = 10.0 + + #: If things disappear when scrolling up and down, turn this up. + simple_culling_v: Annotated[float, IOAttrs('scv', store_default=False)] = ( + 100.0 + ) + + #: Whether the title is a json dict representing an Lstr. Generally + #: doc-ui translation should be handled server-side, but this can + #: allow client-side translation. + title_is_lstr: Annotated[bool, IOAttrs('tl', store_default=False)] = False + + padding_bottom: Annotated[float, IOAttrs('pb', store_default=False)] = 0.0 + padding_left: Annotated[float, IOAttrs('pl', store_default=False)] = 0.0 + padding_top: Annotated[float, IOAttrs('pt', store_default=False)] = 0.0 + padding_right: Annotated[float, IOAttrs('pr', store_default=False)] = 0.0 + + +class ResponseStatus(Enum): + """The overall result of a request.""" + + SUCCESS = 0 + + #: Something went wrong. That's all we know. + UNKNOWN_ERROR = 1 + + #: Something went wrong talking to the server. A 'Retry' button may + #: be appropriate to show here (for GET requests at least). + COMMUNICATION_ERROR = 2 + + #: This requires the user to be signed in, and they aint. + NOT_SIGNED_IN_ERROR = 3 + + +@ioprepped +@dataclass +class Response(DocUIResponse): + """Full docui response.""" + + page: Annotated[Page, IOAttrs('p')] + status: Annotated[ResponseStatus, IOAttrs('s', store_default=False)] = ( + ResponseStatus.SUCCESS + ) + + #: Effects to run on the client when this response is initially + #: received. Note that these effects will not re-run if the page is + #: automatically refreshed later (due to window resizing, back + #: navigation, etc). + #: + #: :meta private: + client_effects: Annotated[ + list[clfx.Effect], IOAttrs('fx', store_default=False) + ] = field(default_factory=list) + + #: Local action to run after this response is initially received. + #: Will be handled by + #: :meth:`bauiv1lib.docui.DocUIController.local_action()`. Note that + #: these actions will not re-run if the page is automatically + #: refreshed later (due to window resizing, back navigation, etc). + local_action: Annotated[str | None, IOAttrs('a', store_default=False)] = ( + None + ) + local_action_args: Annotated[ + dict | None, IOAttrs('aa', store_default=False) + ] = None + + #: New overall action to have the client schedule after this + #: response is received. Useful for redirecting to other pages or + #: closing the doc-ui window. + timed_action: Annotated[ + Action | None, IOAttrs('ta', store_default=False) + ] = None + timed_action_delay: Annotated[ + float, IOAttrs('tad', store_default=False) + ] = 0.0 + + #: If provided, error on builds older than this (can be used to gate + #: functionality without bumping entire docui version). + minimum_engine_build: Annotated[ + int | None, IOAttrs('b', store_default=False) + ] = None + + #: The client maintains some persistent state (such as widget + #: selection) for all pages viewed. The default index for these + #: states is the path of the request. If a server returns a + #: significant variety of responses for a single path, however, + #: (based on args, etc) then it may make sense for the server to + #: provide explicit state ids for those different variations. + shared_state_id: Annotated[ + str | None, IOAttrs('t', store_default=False) + ] = None + + @override + @classmethod + def get_type_id(cls) -> DocUIResponseTypeID: + return DocUIResponseTypeID.V1 diff --git a/dist/ba_data/python/bacommon/locale.py b/dist/ba_data/python/bacommon/locale.py index e6d9bb3..5615f08 100644 --- a/dist/ba_data/python/bacommon/locale.py +++ b/dist/ba_data/python/bacommon/locale.py @@ -71,6 +71,7 @@ class Locale(Enum): VENETIAN = 'venetn' VIETNAMESE = 'viet' KAZAKH = 'kazk' + JAPANESE = 'jpn' # Note: We use if-statement chains here so we can use assert_never() # to ensure we cover all existing values. But we cache lookups so @@ -87,7 +88,7 @@ class Locale(Enum): # pylint: disable=too-many-branches # pylint: disable=too-many-return-statements - cls = type(self) + cls = Locale if self is cls.ENGLISH: return 'English' @@ -175,6 +176,8 @@ class Locale(Enum): return 'Vietnamese' if self is cls.KAZAKH: return 'Kazakh' + if self is cls.JAPANESE: + return 'Japanese' # Make sure we've covered all cases. assert_never(self) @@ -206,7 +209,7 @@ class Locale(Enum): # pylint: disable=too-many-branches # pylint: disable=too-many-return-statements - cls = type(self) + cls = Locale if self is cls.ENGLISH: return 'English' @@ -296,6 +299,8 @@ class Locale(Enum): return 'Vietnamese' if self is cls.KAZAKH: return 'Kazakh' + if self is cls.JAPANESE: + return 'Japanese' # Make sure we've covered all cases. assert_never(self) @@ -306,7 +311,7 @@ class Locale(Enum): # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches - cls = type(self) + cls = Locale R = LocaleResolved if self is cls.ENGLISH: @@ -389,6 +394,8 @@ class Locale(Enum): return R.VIETNAMESE if self is cls.KAZAKH: return R.KAZAKH + if self is cls.JAPANESE: + return R.JAPANESE # Make sure we're covering all cases. assert_never(self) @@ -444,6 +451,7 @@ class LocaleResolved(Enum): VENETIAN = 'venetn' VIETNAMESE = 'viet' KAZAKH = 'kazk' + JAPANESE = 'jpn' # Note: We use if-statement chains here so we can use assert_never() # to ensure we cover all existing values. But we cache lookups so @@ -464,7 +472,7 @@ class LocaleResolved(Enum): # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches - cls = type(self) + cls = LocaleResolved if self is cls.ENGLISH: return Locale.ENGLISH @@ -546,6 +554,8 @@ class LocaleResolved(Enum): return Locale.VIETNAMESE if self is cls.KAZAKH: return Locale.KAZAKH + if self is cls.JAPANESE: + return Locale.JAPANESE # Make sure we're covering all cases. assert_never(self) @@ -561,7 +571,7 @@ class LocaleResolved(Enum): """ # pylint: disable=too-many-branches # pylint: disable=too-many-statements - cls = type(self) + cls = LocaleResolved val: str | None = None @@ -647,6 +657,8 @@ class LocaleResolved(Enum): val = 'vi' elif self is cls.KAZAKH: val = 'kk' + elif self is cls.JAPANESE: + val = 'ja' else: # Make sure we cover all cases. assert_never(self) @@ -668,9 +680,9 @@ class LocaleResolved(Enum): return val - @classmethod + @staticmethod @lru_cache(maxsize=128) - def from_tag(cls, tag: str) -> LocaleResolved: + def from_tag(tag: str) -> LocaleResolved: """Return a locale for a given string tag. Tags can be provided in BCP 47 form ('en-US') or POSIX locale @@ -680,6 +692,8 @@ class LocaleResolved(Enum): # pylint: disable=too-many-statements # pylint: disable=too-many-return-statements + cls = LocaleResolved + # POSIX locale strings can contain a dot followed by an # encoding. Strip that off. tag2 = tag.split('.')[0] @@ -838,6 +852,8 @@ class LocaleResolved(Enum): return cls.VIETNAMESE if lang == 'kk': return cls.KAZAKH + if lang == 'ja': + return cls.JAPANESE # Make noise if we come across something unexpected so we can # add it. diff --git a/dist/ba_data/python/bacommon/loggercontrol.py b/dist/ba_data/python/bacommon/loggercontrol.py index e07e811..17c9b59 100644 --- a/dist/ba_data/python/bacommon/loggercontrol.py +++ b/dist/ba_data/python/bacommon/loggercontrol.py @@ -108,6 +108,11 @@ class LoggerControlConfig: for logname in existinglognames: logger = logging.getLogger(logname) if logger.getEffectiveLevel() != self.get_effective_level(logname): + + # Exceptions for ones that I don't care to look into. + if logname in {'pyasn1'}: + continue + logging.error( 'loggercontrol effective-level sanity check failed;' ' expected logger %s to have effective level %s' diff --git a/dist/ba_data/python/bacommon/logging.py b/dist/ba_data/python/bacommon/logging.py index 2b22fb0..f115fdd 100644 --- a/dist/ba_data/python/bacommon/logging.py +++ b/dist/ba_data/python/bacommon/logging.py @@ -48,7 +48,7 @@ class ClientLoggerName(Enum): """Return a short description for the logger.""" # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches - cls = type(self) + cls = ClientLoggerName if self is cls.BA: return 'top level Ballistica logger - use to adjust everything' if self is cls.ENV: diff --git a/dist/ba_data/python/bacommon/login.py b/dist/ba_data/python/bacommon/login.py index 7fc3729..d7efb01 100644 --- a/dist/ba_data/python/bacommon/login.py +++ b/dist/ba_data/python/bacommon/login.py @@ -32,7 +32,7 @@ class LoginType(Enum): @property def displayname(self) -> str: """A human readable name for this value.""" - cls = type(self) + cls = LoginType match self: case cls.EMAIL: return 'Email/Password' @@ -44,7 +44,7 @@ class LoginType(Enum): @property def displaynameshort(self) -> str: """A short human readable name for this value.""" - cls = type(self) + cls = LoginType match self: case cls.EMAIL: return 'Email' diff --git a/dist/ba_data/python/bacommon/net.py b/dist/ba_data/python/bacommon/net.py index 36596ed..8d60817 100644 --- a/dist/ba_data/python/bacommon/net.py +++ b/dist/ba_data/python/bacommon/net.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Network related data and functionality.""" +"""Network related data and functionality. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations diff --git a/dist/ba_data/python/bacommon/securedata.py b/dist/ba_data/python/bacommon/securedata.py index 2b4d740..4e29856 100644 --- a/dist/ba_data/python/bacommon/securedata.py +++ b/dist/ba_data/python/bacommon/securedata.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to verifying ballistica server generated data.""" +"""Functionality related to verifying server generated data. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" import datetime from dataclasses import dataclass diff --git a/dist/ba_data/python/bacommon/servermanager.py b/dist/ba_data/python/bacommon/servermanager.py index 9a0f8d9..1b464dc 100644 --- a/dist/ba_data/python/bacommon/servermanager.py +++ b/dist/ba_data/python/bacommon/servermanager.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to the server manager script.""" + from __future__ import annotations from enum import Enum diff --git a/dist/ba_data/python/bacommon/text.py b/dist/ba_data/python/bacommon/text.py new file mode 100644 index 0000000..84e86ef --- /dev/null +++ b/dist/ba_data/python/bacommon/text.py @@ -0,0 +1,121 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Text related bits.""" + +from __future__ import annotations +from enum import Enum + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + pass + + +class SpecialChar(Enum): + """Custom unicode characters the engine can display. + + Keep this in sync with babase._mgen.enums.SpecialChar. + """ + + LEFT_ARROW = '\ue001' + RIGHT_ARROW = '\ue002' + UP_ARROW = '\ue003' + DOWN_ARROW = '\ue004' + LEFT_BUTTON = '\ue005' + TOP_BUTTON = '\ue006' + RIGHT_BUTTON = '\ue007' + BOTTOM_BUTTON = '\ue008' + DELETE = '\ue009' + SHIFT = '\ue00a' + BACK = '\ue00b' + LOGO_FLAT = '\ue00c' + REWIND_BUTTON = '\ue00d' + PLAY_PAUSE_BUTTON = '\ue00e' + FAST_FORWARD_BUTTON = '\ue00f' + DPAD_CENTER_BUTTON = '\ue010' + PLAY_STATION_CROSS_BUTTON = '\ue011' + PLAY_STATION_CIRCLE_BUTTON = '\ue012' + PLAY_STATION_TRIANGLE_BUTTON = '\ue013' + PLAY_STATION_SQUARE_BUTTON = '\ue014' + PLAY_BUTTON = '\ue015' + PAUSE_BUTTON = '\ue016' + CLOSE = '\ue017' + OUYA_BUTTON_O = '\ue019' + OUYA_BUTTON_U = '\ue01a' + OUYA_BUTTON_Y = '\ue01b' + OUYA_BUTTON_A = '\ue01c' + TOKEN = '\ue01d' + LOGO = '\ue01e' + TICKET = '\ue01f' + GOOGLE_PLAY_GAMES_LOGO = '\ue020' + GAME_CENTER_LOGO = '\ue021' + DICE_BUTTON1 = '\ue022' + DICE_BUTTON2 = '\ue023' + DICE_BUTTON3 = '\ue024' + DICE_BUTTON4 = '\ue025' + GAME_CIRCLE_LOGO = '\ue026' + PARTY_ICON = '\ue027' + TEST_ACCOUNT = '\ue028' + TICKET_BACKING = '\ue029' + TROPHY1 = '\ue02a' + TROPHY2 = '\ue02b' + TROPHY3 = '\ue02c' + TROPHY0A = '\ue02d' + TROPHY0B = '\ue02e' + TROPHY4 = '\ue02f' + LOCAL_ACCOUNT = '\ue030' + EXPLODINARY_LOGO = '\ue031' + FLAG_UNITED_STATES = '\ue032' + FLAG_MEXICO = '\ue033' + FLAG_GERMANY = '\ue034' + FLAG_BRAZIL = '\ue035' + FLAG_RUSSIA = '\ue036' + FLAG_CHINA = '\ue037' + FLAG_UNITED_KINGDOM = '\ue038' + FLAG_CANADA = '\ue039' + FLAG_INDIA = '\ue03a' + FLAG_JAPAN = '\ue03b' + FLAG_FRANCE = '\ue03c' + FLAG_INDONESIA = '\ue03d' + FLAG_ITALY = '\ue03e' + FLAG_SOUTH_KOREA = '\ue03f' + FLAG_NETHERLANDS = '\ue040' + FEDORA = '\ue041' + HAL = '\ue042' + CROWN = '\ue043' + YIN_YANG = '\ue044' + EYE_BALL = '\ue045' + SKULL = '\ue046' + HEART = '\ue047' + DRAGON = '\ue048' + HELMET = '\ue049' + MUSHROOM = '\ue04a' + NINJA_STAR = '\ue04b' + VIKING_HELMET = '\ue04c' + MOON = '\ue04d' + SPIDER = '\ue04e' + FIREBALL = '\ue04f' + FLAG_UNITED_ARAB_EMIRATES = '\ue050' + FLAG_QATAR = '\ue051' + FLAG_EGYPT = '\ue052' + FLAG_KUWAIT = '\ue053' + FLAG_ALGERIA = '\ue054' + FLAG_SAUDI_ARABIA = '\ue055' + FLAG_MALAYSIA = '\ue056' + FLAG_CZECH_REPUBLIC = '\ue057' + FLAG_AUSTRALIA = '\ue058' + FLAG_SINGAPORE = '\ue059' + OCULUS_LOGO = '\ue05a' + STEAM_LOGO = '\ue05b' + NVIDIA_LOGO = '\ue05c' + FLAG_IRAN = '\ue05d' + FLAG_POLAND = '\ue05e' + FLAG_ARGENTINA = '\ue05f' + FLAG_PHILIPPINES = '\ue060' + FLAG_CHILE = '\ue061' + MIKIROG = '\ue062' + V2_LOGO = '\ue063' + SANTA_HAT = '\ue064' + POTATO = '\ue065' + PALM_TREE = '\ue066' + BOXING_GLOVE = '\ue067' diff --git a/dist/ba_data/python/bacommon/transfer.py b/dist/ba_data/python/bacommon/transfer.py index aa8d38d..67f1ac7 100644 --- a/dist/ba_data/python/bacommon/transfer.py +++ b/dist/ba_data/python/bacommon/transfer.py @@ -1,6 +1,12 @@ # Released under the MIT License. See LICENSE for details. # -"""Functionality related to transferring files/data.""" +"""Functionality related to transferring files/data. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" from __future__ import annotations diff --git a/dist/ba_data/python/bacommon/workspace/assetsv1.py b/dist/ba_data/python/bacommon/workspace/assetsv1.py index 83a058a..fa6f7ba 100644 --- a/dist/ba_data/python/bacommon/workspace/assetsv1.py +++ b/dist/ba_data/python/bacommon/workspace/assetsv1.py @@ -2,10 +2,10 @@ # """Public types for assets-v1 workspaces. -These types may only be used server-side, but they are exposed here -for reference when setting workspace config data by hand or for use -in client-side workspace modification tools. There may be advanced -settings that are not accessible through the UI/etc. +While this module is currently only used server-side, its source code +can be useful as reference when setting workspace config data by hand or +for use in client-side workspace modification tools. There may be +advanced settings that are not accessible through the UI/etc. """ from __future__ import annotations @@ -18,7 +18,6 @@ from typing import TYPE_CHECKING, Annotated, override, assert_never from efro.dataclassio import ioprepped, IOAttrs, IOMultiType from bacommon.locale import Locale - if TYPE_CHECKING: pass @@ -85,8 +84,8 @@ class AssetsV1StringFileV1(AssetsV1StringFile): NONE = 'none' TITLE = 'title' - INTENSE = 'intense' - SUBTLE = 'subtle' + LOUD = 'loud' + SOFT = 'soft' @override @classmethod @@ -121,7 +120,7 @@ class AssetsV1PathValsTypeID(Enum): """Types of vals we can store for paths.""" TEX_V1 = 'tex_v1' - # STR_V1 = 'str_v1' + STR_V1 = 'str_v1' class AssetsV1PathVals(IOMultiType[AssetsV1PathValsTypeID]): @@ -151,6 +150,9 @@ class AssetsV1PathVals(IOMultiType[AssetsV1PathValsTypeID]): if type_id is t.TEX_V1: return AssetsV1PathValsTexV1 + if type_id is t.STR_V1: + return AssetsV1PathValsStrV1 + # Important to make sure we provide all types. assert_never(type_id) @@ -176,3 +178,20 @@ class AssetsV1PathValsTexV1(AssetsV1PathVals): @classmethod def get_type_id(cls) -> AssetsV1PathValsTypeID: return AssetsV1PathValsTypeID.TEX_V1 + + +@ioprepped +@dataclass +class AssetsV1PathValsStrV1(AssetsV1PathVals): + """Path-specific values for an assets_v1 workspace path.""" + + #: Hash generated when all translations for this entry are complete. + #: Used as a fast-out for checking whether updates are needed. + up_to_date_state: Annotated[ + str | None, IOAttrs('up_to_date_state', store_default=False) + ] = None + + @override + @classmethod + def get_type_id(cls) -> AssetsV1PathValsTypeID: + return AssetsV1PathValsTypeID.STR_V1 diff --git a/dist/ba_data/python/baenv.py b/dist/ba_data/python/baenv.py index 84f0471..45e0309 100644 --- a/dist/ba_data/python/baenv.py +++ b/dist/ba_data/python/baenv.py @@ -14,6 +14,7 @@ Ballistica can be used without explicitly configuring the environment in order to integrate it in arbitrary Python environments, but this may cause some features to be disabled or behave differently than expected. """ + from __future__ import annotations import os @@ -56,8 +57,8 @@ logger = logging.getLogger('ba.env') # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 22584 -TARGET_BALLISTICA_VERSION = '1.7.53' +TARGET_BALLISTICA_BUILD = 22712 +TARGET_BALLISTICA_VERSION = '1.7.61' @dataclass @@ -95,7 +96,7 @@ class EnvConfig: #: stderr into the engine so they show up on in-app consoles, etc. log_handler: LogHandler | None - # Initial data from the ``config.json`` file in the config dir. + #: Initial data from the ``config.json`` file in the config dir. initial_app_config: Any #: Timestamp when we first started doing stuff. diff --git a/dist/ba_data/python/baplus/_ads.py b/dist/ba_data/python/baplus/_ads.py index f6aec55..4b77cbb 100644 --- a/dist/ba_data/python/baplus/_ads.py +++ b/dist/ba_data/python/baplus/_ads.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to ads.""" + from __future__ import annotations import time diff --git a/dist/ba_data/python/baplus/_appsubsystem.py b/dist/ba_data/python/baplus/_appsubsystem.py index 507d172..29862e2 100644 --- a/dist/ba_data/python/baplus/_appsubsystem.py +++ b/dist/ba_data/python/baplus/_appsubsystem.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides plus app subsystem.""" + from __future__ import annotations from typing import TYPE_CHECKING, override @@ -13,7 +14,7 @@ from baplus._ads import AdsSubsystem if TYPE_CHECKING: from typing import Callable, Any - import bacommon.bs + import bacommon.classic from babase import AccountV2Subsystem from baplus._cloud import CloudSubsystem @@ -142,14 +143,6 @@ class PlusAppSubsystem(AppSubsystem): """:meta private:""" return _baplus.get_v1_account_state_num() - # @staticmethod - # def get_v1_account_ticket_count() -> int: - # """Return the number of tickets for the current account. - - # :meta private: - # """ - # return _baplus.get_v1_account_ticket_count() - @staticmethod def get_v1_account_type() -> str: """:meta private:""" diff --git a/dist/ba_data/python/baplus/_cloud.py b/dist/ba_data/python/baplus/_cloud.py index f1f4097..83d527a 100644 --- a/dist/ba_data/python/baplus/_cloud.py +++ b/dist/ba_data/python/baplus/_cloud.py @@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, overload from efro.error import CommunicationError from efro.call import CallbackSet from efro.dataclassio import dataclass_from_dict, dataclass_to_dict -import bacommon.bs +import bacommon.classic import bacommon.cloud import babase @@ -19,7 +19,8 @@ if TYPE_CHECKING: from typing import Callable, Any from efro.message import Message, Response, BoolResponse - import bacommon.bs + import bacommon.classic + import bacommon.clouddialog as cdlg # TODO: Should make it possible to define a protocol in bacommon.cloud and @@ -36,6 +37,8 @@ class CloudSubsystem(babase.AppSubsystem): """ #: General engine config values provided by the cloud. + #: + #: :meta private: vals: bacommon.cloud.CloudVals def __init__(self) -> None: @@ -214,9 +217,9 @@ class CloudSubsystem(babase.AppSubsystem): @overload def send_message_cb( self, - msg: bacommon.bs.GetClassicPurchasesMessage, + msg: bacommon.classic.GetClassicPurchasesMessage, on_response: Callable[ - [bacommon.bs.GetClassicPurchasesResponse | Exception], None + [bacommon.classic.GetClassicPurchasesResponse | Exception], None ], ) -> None: ... @@ -232,61 +235,59 @@ class CloudSubsystem(babase.AppSubsystem): @overload def send_message_cb( self, - msg: bacommon.bs.PrivatePartyMessage, + msg: bacommon.classic.PrivatePartyMessage, on_response: Callable[ - [bacommon.bs.PrivatePartyResponse | Exception], None + [bacommon.classic.PrivatePartyResponse | Exception], None ], ) -> None: ... @overload def send_message_cb( self, - msg: bacommon.bs.InboxRequestMessage, + msg: bacommon.classic.InboxRequestMessage, on_response: Callable[ - [bacommon.bs.InboxRequestResponse | Exception], None + [bacommon.classic.InboxRequestResponse | Exception], None ], ) -> None: ... @overload def send_message_cb( self, - msg: bacommon.bs.CloudDialogActionMessage, + msg: cdlg.ActionMessage, + on_response: Callable[[cdlg.ActionResponse | Exception], None], + ) -> None: ... + + @overload + def send_message_cb( + self, + msg: bacommon.classic.ChestInfoMessage, on_response: Callable[ - [bacommon.bs.CloudDialogActionResponse | Exception], None + [bacommon.classic.ChestInfoResponse | Exception], None ], ) -> None: ... @overload def send_message_cb( self, - msg: bacommon.bs.ChestInfoMessage, + msg: bacommon.cloud.ChestActionMessage, on_response: Callable[ - [bacommon.bs.ChestInfoResponse | Exception], None + [bacommon.cloud.ChestActionResponse | Exception], None ], ) -> None: ... @overload def send_message_cb( self, - msg: bacommon.bs.ChestActionMessage, - on_response: Callable[ - [bacommon.bs.ChestActionResponse | Exception], None - ], - ) -> None: ... - - @overload - def send_message_cb( - self, - msg: bacommon.bs.GlobalProfileCheckMessage, + msg: bacommon.classic.GlobalProfileCheckMessage, on_response: Callable[[BoolResponse | Exception], None], ) -> None: ... @overload def send_message_cb( self, - msg: bacommon.bs.ScoreSubmitMessage, + msg: bacommon.classic.ScoreSubmitMessage, on_response: Callable[ - [bacommon.bs.ScoreSubmitResponse | Exception], None + [bacommon.classic.ScoreSubmitResponse | Exception], None ], ) -> None: ... @@ -308,6 +309,29 @@ class CloudSubsystem(babase.AppSubsystem): ], ) -> None: ... + @overload + def send_message_cb( + self, + msg: bacommon.classic.GetClassicLeaguePresidentButtonInfoMessage, + on_response: Callable[ + [ + bacommon.classic.GetClassicLeaguePresidentButtonInfoResponse + | Exception + ], + None, + ], + ) -> None: ... + + @overload + def send_message_cb( + self, + msg: bacommon.cloud.AnalyticsEventMessage, + on_response: Callable[ + [None | Exception], + None, + ], + ) -> None: ... + def send_message_cb( self, msg: Message, @@ -339,8 +363,13 @@ class CloudSubsystem(babase.AppSubsystem): @overload def send_message( - self, msg: bacommon.bs.LegacyRequest - ) -> bacommon.bs.LegacyResponse: ... + self, msg: bacommon.classic.LegacyRequest + ) -> bacommon.classic.LegacyResponse: ... + + @overload + def send_message( + self, msg: bacommon.cloud.FulfillDocUIRequest + ) -> bacommon.cloud.FulfillDocUIResponse: ... def send_message(self, msg: Message) -> Response | None: """Synchronously send a message to the cloud. @@ -353,8 +382,8 @@ class CloudSubsystem(babase.AppSubsystem): @overload async def send_message_async( - self, msg: bacommon.bs.SendInfoMessage - ) -> bacommon.bs.SendInfoResponse: ... + self, msg: bacommon.classic.SendInfoMessage + ) -> bacommon.classic.SendInfoResponse: ... @overload async def send_message_async( @@ -383,9 +412,14 @@ class CloudSubsystem(babase.AppSubsystem): def subscribe_classic_account_data( self, - updatecall: Callable[[bacommon.bs.ClassicAccountLiveData], None], + updatecall: Callable[ + [bacommon.classic.ClassicLiveAccountClientData], None + ], ) -> babase.CloudSubscription: - """Subscribe to classic account data.""" + """Subscribe to classic account data. + + :meta private: + """ raise NotImplementedError( 'Cloud functionality is not present in this build.' ) diff --git a/dist/ba_data/python/baplus/_hooks.py b/dist/ba_data/python/baplus/_hooks.py index 0348914..95b43fe 100644 --- a/dist/ba_data/python/baplus/_hooks.py +++ b/dist/ba_data/python/baplus/_hooks.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Snippets of code for use by the c++ layer.""" + # (most of these are self-explanatory) # pylint: disable=missing-function-docstring from __future__ import annotations diff --git a/dist/ba_data/python/bascenev1/__init__.py b/dist/ba_data/python/bascenev1/__init__.py index f739b07..aead594 100644 --- a/dist/ba_data/python/bascenev1/__init__.py +++ b/dist/ba_data/python/bascenev1/__init__.py @@ -16,7 +16,6 @@ import logging # other modules; the goal is to let most simple mods rely solely on this # module to keep things simple. -# from efro.util import set_canonical_module_names from babase import ( ActivityNotFoundError, add_clean_frame_callback, @@ -32,6 +31,8 @@ from babase import ( apptimer, AppTimer, Call, + CallPartial, + CallStrict, ContextError, ContextRef, displaytime, @@ -63,6 +64,8 @@ from babase import ( unlock_all_input, Vec3, WeakCall, + WeakCallPartial, + WeakCallStrict, ) from _bascenev1 import ( @@ -275,6 +278,8 @@ __all__ = [ 'BaseTimer', 'BoolSetting', 'Call', + 'CallPartial', + 'CallStrict', 'cameraflash', 'camerashake', 'Campaign', @@ -475,15 +480,11 @@ __all__ = [ 'unlock_all_input', 'Vec3', 'WeakCall', + 'WeakCallPartial', + 'WeakCallStrict', 'WinnerGroup', ] -# We want stuff here to show up as bascenev1.Foo instead of -# bascenev1._submodule.Foo. -# UPDATE: Trying without this for now. Seems like this might cause more -# harm than good. Can flip it back on if it is missed. -# set_canonical_module_names(globals()) - # Sanity check: we want to keep ballistica's dependencies and # bootstrapping order clearly defined; let's check a few particular # modules to make sure they never directly or indirectly import us diff --git a/dist/ba_data/python/bascenev1/_activity.py b/dist/ba_data/python/bascenev1/_activity.py index c78f1a6..57aaa12 100644 --- a/dist/ba_data/python/bascenev1/_activity.py +++ b/dist/ba_data/python/bascenev1/_activity.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Defines Activity class.""" + from __future__ import annotations import weakref @@ -12,9 +13,8 @@ import _bascenev1 from bascenev1._dependency import DependencyComponent from bascenev1._messages import UNHANDLED - if TYPE_CHECKING: - from typing import Any + from typing import Any, Self import bascenev1 @@ -192,7 +192,7 @@ class Activity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( session = self._session() if session is not None: babase.pushcall( - babase.Call( + babase.CallStrict( session.transitioning_out_activity_was_freed, self.can_show_ad_on_death, ) @@ -286,7 +286,7 @@ class Activity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( ref = weakref.ref(self) self._activity_death_check_timer = babase.AppTimer( 5.0, - babase.Call(self._check_activity_death, ref, [0]), + babase.CallStrict(self._check_activity_death, ref, [0]), repeat=True, ) @@ -722,7 +722,7 @@ class Activity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( @classmethod def _check_activity_death( - cls, activity_ref: weakref.ref[Activity], counter: list[int] + cls, activity_ref: weakref.ref[Self], counter: list[int] ) -> None: """Sanity check to make sure an Activity was destroyed properly. diff --git a/dist/ba_data/python/bascenev1/_activitytypes.py b/dist/ba_data/python/bascenev1/_activitytypes.py index c80941a..fe05362 100644 --- a/dist/ba_data/python/bascenev1/_activitytypes.py +++ b/dist/ba_data/python/bascenev1/_activitytypes.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Some handy base class and special purpose Activity types.""" + from __future__ import annotations from typing import TYPE_CHECKING, override @@ -14,7 +15,6 @@ from bascenev1._player import EmptyPlayer from bascenev1._team import EmptyTeam from bascenev1._music import MusicType, setmusic - if TYPE_CHECKING: import bascenev1 from bascenev1._lobby import JoinInfo @@ -54,7 +54,7 @@ class EndSessionActivity(Activity[EmptyPlayer, EmptyTeam]): babase.unlock_all_input() assert babase.app.plus is not None - call = babase.Call(_bascenev1.new_host_session, main_menu_session) + call = babase.CallStrict(_bascenev1.new_host_session, main_menu_session) if classic.can_show_interstitial(): plus.ads.call_after_ad(call) else: @@ -172,7 +172,7 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): # If we're still kicking at the end of our assign-delay, assign this # guy's input to trigger us. _bascenev1.timer( - time_till_assign, babase.WeakCall(self._safe_assign, player) + time_till_assign, babase.WeakCallStrict(self._safe_assign, player) ) @override diff --git a/dist/ba_data/python/bascenev1/_campaign.py b/dist/ba_data/python/bascenev1/_campaign.py index f45f8bc..10d0de0 100644 --- a/dist/ba_data/python/bascenev1/_campaign.py +++ b/dist/ba_data/python/bascenev1/_campaign.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to co-op campaigns.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/bascenev1/_collision.py b/dist/ba_data/python/bascenev1/_collision.py index 11877f6..5dc418f 100644 --- a/dist/ba_data/python/bascenev1/_collision.py +++ b/dist/ba_data/python/bascenev1/_collision.py @@ -19,7 +19,9 @@ class Collision: @property def position(self) -> bascenev1.Vec3: """The position of the current collision.""" - return babase.Vec3(_bascenev1.get_collision_info('position')) + out = babase.Vec3(_bascenev1.get_collision_info('position')) + assert isinstance(out, babase.Vec3) + return out @property def sourcenode(self) -> bascenev1.Node: @@ -30,7 +32,7 @@ class Collision: start of the collision callback). """ node = _bascenev1.get_collision_info('sourcenode') - assert isinstance(node, (_bascenev1.Node, type(None))) + assert isinstance(node, _bascenev1.Node | None) if not node: raise babase.NodeNotFoundError() return node @@ -45,7 +47,7 @@ class Collision: currently-colliding node. """ node = _bascenev1.get_collision_info('opposingnode') - assert isinstance(node, (_bascenev1.Node, type(None))) + assert isinstance(node, _bascenev1.Node | None) if not node: raise babase.NodeNotFoundError() return node diff --git a/dist/ba_data/python/bascenev1/_coopgame.py b/dist/ba_data/python/bascenev1/_coopgame.py index 56cfb12..7861a29 100644 --- a/dist/ba_data/python/bascenev1/_coopgame.py +++ b/dist/ba_data/python/bascenev1/_coopgame.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to co-op games.""" + from __future__ import annotations import logging @@ -64,11 +65,11 @@ class CoopGameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( if not arcade_or_demo: _bascenev1.timer( - 3.8, babase.WeakCall(self._show_remaining_achievements) + 3.8, babase.WeakCallStrict(self._show_remaining_achievements) ) # Preload achievement images in case we get some. - _bascenev1.timer(2.0, babase.WeakCall(self._preload_achievements)) + _bascenev1.timer(2.0, babase.WeakCallStrict(self._preload_achievements)) # FIXME: this is now redundant with activityutils.getscoreconfig(); # need to kill this. @@ -232,7 +233,7 @@ class CoopGameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( """Set up a beeping noise to play when any players are near death.""" self._life_warning_beep = None self._life_warning_beep_timer = _bascenev1.Timer( - 1.0, babase.WeakCall(self._update_life_warning), repeat=True + 1.0, babase.WeakCallStrict(self._update_life_warning), repeat=True ) def _update_life_warning(self) -> None: diff --git a/dist/ba_data/python/bascenev1/_coopsession.py b/dist/ba_data/python/bascenev1/_coopsession.py index c8b176b..d066115 100644 --- a/dist/ba_data/python/bascenev1/_coopsession.py +++ b/dist/ba_data/python/bascenev1/_coopsession.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to coop-mode sessions.""" + from __future__ import annotations from typing import TYPE_CHECKING, override @@ -185,7 +186,9 @@ class CoopSession(Session): def on_player_leave(self, sessionplayer: bascenev1.SessionPlayer) -> None: super().on_player_leave(sessionplayer) - _bascenev1.timer(2.0, babase.WeakCall(self._handle_empty_activity)) + _bascenev1.timer( + 2.0, babase.WeakCallStrict(self._handle_empty_activity) + ) def _handle_empty_activity(self) -> None: """Handle cases where all players have left the current activity.""" @@ -358,7 +361,7 @@ class CoopSession(Session): { 'label': babase.Lstr(resource='restartText'), 'resume_on_call': False, - 'call': babase.WeakCall( + 'call': babase.WeakCallPartial( self._on_tournament_restart_menu_press ), } @@ -367,7 +370,7 @@ class CoopSession(Session): self._custom_menu_ui = [ { 'label': babase.Lstr(resource='restartText'), - 'call': babase.WeakCall(self.restart), + 'call': babase.WeakCallStrict(self.restart), } ] diff --git a/dist/ba_data/python/bascenev1/_debug.py b/dist/ba_data/python/bascenev1/_debug.py index 768b42b..9348635 100644 --- a/dist/ba_data/python/bascenev1/_debug.py +++ b/dist/ba_data/python/bascenev1/_debug.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Debugging functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/bascenev1/_dualteamsession.py b/dist/ba_data/python/bascenev1/_dualteamsession.py index 7ea0a13..8b013b4 100644 --- a/dist/ba_data/python/bascenev1/_dualteamsession.py +++ b/dist/ba_data/python/bascenev1/_dualteamsession.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to teams sessions.""" + from __future__ import annotations from typing import TYPE_CHECKING, override diff --git a/dist/ba_data/python/bascenev1/_gameactivity.py b/dist/ba_data/python/bascenev1/_gameactivity.py index 698fec2..f5cd386 100644 --- a/dist/ba_data/python/bascenev1/_gameactivity.py +++ b/dist/ba_data/python/bascenev1/_gameactivity.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides GameActivity class.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -405,7 +406,9 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( 'tournamentIDs': [tournament_id], 'source': 'in-game time remaining query', }, - callback=babase.WeakCall(self._on_tournament_query_response), + callback=babase.WeakCallPartial( + self._on_tournament_query_response + ), ) def _on_tournament_query_response( @@ -805,7 +808,7 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( player.customdata['respawn_timer'] = _bascenev1.Timer( respawn_time, - babase.WeakCall(self.spawn_player_if_exists, player), + babase.WeakCallStrict(self.spawn_player_if_exists, player), ) player.customdata['respawn_icon'] = RespawnIcon( player, respawn_time @@ -902,7 +905,7 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( self._powerup_drop_timer = _bascenev1.Timer( DEFAULT_POWERUP_INTERVAL, - babase.WeakCall(self._standard_drop_powerups), + babase.WeakCallStrict(self._standard_drop_powerups), repeat=True, ) self._standard_drop_powerups() @@ -927,7 +930,7 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( points = self.map.powerup_spawn_points for i in range(len(points)): _bascenev1.timer( - i * 0.4, babase.WeakCall(self._standard_drop_powerup, i) + i * 0.4, babase.WeakCallStrict(self._standard_drop_powerup, i) ) def _setup_standard_tnt_drops(self) -> None: @@ -953,7 +956,9 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( return self._standard_time_limit_time = int(duration) self._standard_time_limit_timer = _bascenev1.Timer( - 1.0, babase.WeakCall(self._standard_time_limit_tick), repeat=True + 1.0, + babase.WeakCallStrict(self._standard_time_limit_tick), + repeat=True, ) self._standard_time_limit_text = NodeActor( _bascenev1.newnode( @@ -1043,7 +1048,9 @@ class GameActivity[PlayerT: bascenev1.Player, TeamT: bascenev1.Team]( # then we have to mess with contexts and whatnot since its currently # not available in activity contexts. :-/ self._tournament_time_limit_timer = _bascenev1.BaseTimer( - 1.0, babase.WeakCall(self._tournament_time_limit_tick), repeat=True + 1.0, + babase.WeakCallStrict(self._tournament_time_limit_tick), + repeat=True, ) self._tournament_time_limit_title_text = NodeActor( _bascenev1.newnode( diff --git a/dist/ba_data/python/bascenev1/_gameresults.py b/dist/ba_data/python/bascenev1/_gameresults.py index 795070c..61e5333 100644 --- a/dist/ba_data/python/bascenev1/_gameresults.py +++ b/dist/ba_data/python/bascenev1/_gameresults.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to game results.""" + from __future__ import annotations import copy diff --git a/dist/ba_data/python/bascenev1/_hooks.py b/dist/ba_data/python/bascenev1/_hooks.py index b88bfb6..cde61d8 100644 --- a/dist/ba_data/python/bascenev1/_hooks.py +++ b/dist/ba_data/python/bascenev1/_hooks.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Snippets of code for use by the c++ layer.""" + # (most of these are self-explanatory) # pylint: disable=missing-function-docstring from __future__ import annotations diff --git a/dist/ba_data/python/bascenev1/_level.py b/dist/ba_data/python/bascenev1/_level.py index 0f777dc..c26a0a1 100644 --- a/dist/ba_data/python/bascenev1/_level.py +++ b/dist/ba_data/python/bascenev1/_level.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to individual levels in a campaign.""" + from __future__ import annotations import copy @@ -118,10 +119,11 @@ class Level: def get_high_scores(self) -> dict: """Return the current high scores for this level.""" config = self._get_config_dict() - high_scores_key = 'High Scores' + self.get_score_version_string() - if high_scores_key not in config: - return {} - return copy.deepcopy(config[high_scores_key]) + high_scores_key = f'High Scores{self.get_score_version_string()}' + val = config.get(high_scores_key) + if isinstance(val, dict): + return copy.deepcopy(val) + return {} def set_high_scores(self, high_scores: dict) -> None: """Set high scores for this level.""" diff --git a/dist/ba_data/python/bascenev1/_lobby.py b/dist/ba_data/python/bascenev1/_lobby.py index 99f36c0..df73f3d 100644 --- a/dist/ba_data/python/bascenev1/_lobby.py +++ b/dist/ba_data/python/bascenev1/_lobby.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Implements lobby system for gathering before games, char select, etc.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -118,7 +119,7 @@ class JoinInfo: ) self._timer = _bascenev1.Timer( - 4.0, babase.WeakCall(self._update), repeat=True + 4.0, babase.WeakCallStrict(self._update), repeat=True ) def _update_for_keyboard(self, keyboard: bascenev1.InputDevice) -> None: @@ -609,25 +610,29 @@ class Chooser: if not ready: self._sessionplayer.assigninput( babase.InputType.LEFT_PRESS, - babase.Call(self.handlemessage, ChangeMessage('team', -1)), + babase.CallStrict( + self.handlemessage, ChangeMessage('team', -1) + ), ) self._sessionplayer.assigninput( babase.InputType.RIGHT_PRESS, - babase.Call(self.handlemessage, ChangeMessage('team', 1)), + babase.CallStrict(self.handlemessage, ChangeMessage('team', 1)), ) self._sessionplayer.assigninput( babase.InputType.BOMB_PRESS, - babase.Call(self.handlemessage, ChangeMessage('character', 1)), + babase.CallStrict( + self.handlemessage, ChangeMessage('character', 1) + ), ) self._sessionplayer.assigninput( babase.InputType.UP_PRESS, - babase.Call( + babase.CallStrict( self.handlemessage, ChangeMessage('profileindex', -1) ), ) self._sessionplayer.assigninput( babase.InputType.DOWN_PRESS, - babase.Call( + babase.CallStrict( self.handlemessage, ChangeMessage('profileindex', 1) ), ) @@ -637,7 +642,9 @@ class Chooser: babase.InputType.PICK_UP_PRESS, babase.InputType.PUNCH_PRESS, ), - babase.Call(self.handlemessage, ChangeMessage('ready', 1)), + babase.CallStrict( + self.handlemessage, ChangeMessage('ready', 1) + ), ) self._ready = False self._update_text() @@ -662,7 +669,9 @@ class Chooser: babase.InputType.PICK_UP_PRESS, babase.InputType.PUNCH_PRESS, ), - babase.Call(self.handlemessage, ChangeMessage('ready', 0)), + babase.CallStrict( + self.handlemessage, ChangeMessage('ready', 0) + ), ) # Store the last profile picked by this input for reuse. diff --git a/dist/ba_data/python/bascenev1/_map.py b/dist/ba_data/python/bascenev1/_map.py index 5718289..b6ae04f 100644 --- a/dist/ba_data/python/bascenev1/_map.py +++ b/dist/ba_data/python/bascenev1/_map.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Map related functionality.""" + from __future__ import annotations import random diff --git a/dist/ba_data/python/bascenev1/_messages.py b/dist/ba_data/python/bascenev1/_messages.py index 2c8166c..9518241 100644 --- a/dist/ba_data/python/bascenev1/_messages.py +++ b/dist/ba_data/python/bascenev1/_messages.py @@ -99,7 +99,7 @@ class PlayerDiedMessage: Pass the Player type being used by the current game. """ - assert isinstance(self._killerplayer, (playertype, type(None))) + assert isinstance(self._killerplayer, playertype | None) return self._killerplayer def getplayer[PlayerT: bascenev1.Player]( diff --git a/dist/ba_data/python/bascenev1/_multiteamsession.py b/dist/ba_data/python/bascenev1/_multiteamsession.py index 85b6799..3faa06c 100644 --- a/dist/ba_data/python/bascenev1/_multiteamsession.py +++ b/dist/ba_data/python/bascenev1/_multiteamsession.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to teams sessions.""" + from __future__ import annotations import copy diff --git a/dist/ba_data/python/bascenev1/_net.py b/dist/ba_data/python/bascenev1/_net.py index 279c329..2a649c8 100644 --- a/dist/ba_data/python/bascenev1/_net.py +++ b/dist/ba_data/python/bascenev1/_net.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to net play.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/bascenev1/_player.py b/dist/ba_data/python/bascenev1/_player.py index 53a056b..4c937f7 100644 --- a/dist/ba_data/python/bascenev1/_player.py +++ b/dist/ba_data/python/bascenev1/_player.py @@ -35,7 +35,8 @@ class StandLocation: angle: float | None = None -class Player[TeamT: bascenev1.Team]: +# class Player[TeamT: bascenev1.Team]: +class Player[TeamT]: """A player in a specific bascenev1.Activity. These correspond to bascenev1.SessionPlayer objects, but are associated @@ -315,5 +316,5 @@ def playercast_o[PlayerT: bascenev1.Player]( totype: type[PlayerT], player: bascenev1.Player | None ) -> PlayerT | None: """A variant of bascenev1.playercast() for optional Player values.""" - assert isinstance(player, (totype, type(None))) + assert isinstance(player, totype | None) return player diff --git a/dist/ba_data/python/bascenev1/_profile.py b/dist/ba_data/python/bascenev1/_profile.py index a097456..6883cf1 100644 --- a/dist/ba_data/python/bascenev1/_profile.py +++ b/dist/ba_data/python/bascenev1/_profile.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to player profiles.""" + from __future__ import annotations import random diff --git a/dist/ba_data/python/bascenev1/_session.py b/dist/ba_data/python/bascenev1/_session.py index ae1594e..b93bb50 100644 --- a/dist/ba_data/python/bascenev1/_session.py +++ b/dist/ba_data/python/bascenev1/_session.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Defines base session class.""" + from __future__ import annotations import math @@ -338,7 +339,9 @@ class Session: with babase.ContextRef.empty(): self._waitlist_timers[identifier] = babase.AppTimer( _g_player_rejoin_cooldown, - babase.Call(self._remove_player_from_waitlist, identifier), + babase.CallStrict( + self._remove_player_from_waitlist, identifier + ), ) if not sessionplayer.in_game: @@ -372,7 +375,7 @@ class Session: # Grab their activity-specific player instance. player = sessionplayer.activityplayer - assert isinstance(player, (Player, type(None))) + assert isinstance(player, Player | None) # Remove them from any current Activity. if player is not None and activity is not None: @@ -498,7 +501,9 @@ class Session: # Set a timer to set in motion this activity's demise. self._activity_end_timer = _bascenev1.BaseTimer( delay, - babase.Call(self._complete_end_activity, activity, results), + babase.CallStrict( + self._complete_end_activity, activity, results + ), ) def handlemessage(self, msg: Any) -> Any: diff --git a/dist/ba_data/python/bascenev1/_stats.py b/dist/ba_data/python/bascenev1/_stats.py index d5a2877..698a00c 100644 --- a/dist/ba_data/python/bascenev1/_stats.py +++ b/dist/ba_data/python/bascenev1/_stats.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to scores and statistics.""" + from __future__ import annotations import random @@ -13,7 +14,6 @@ import babase import _bascenev1 - if TYPE_CHECKING: from typing import Any, Sequence @@ -237,7 +237,7 @@ class PlayerRecord: if name is not None: _bascenev1.timer( 0.3 + delay, - babase.Call( + babase.CallStrict( _apply, name, score, showpoints, color, scale, sound ), ) diff --git a/dist/ba_data/python/bascenev1/_team.py b/dist/ba_data/python/bascenev1/_team.py index d9b99ad..fc6001e 100644 --- a/dist/ba_data/python/bascenev1/_team.py +++ b/dist/ba_data/python/bascenev1/_team.py @@ -65,7 +65,8 @@ class SessionTeam: self.customdata = {} -class Team[PlayerT: bascenev1.Player]: +# class Team[PlayerT: bascenev1.Player]: +class Team[PlayerT]: """A team in a specific :class:`~bascenev1.Activity`. These correspond to :class:`~bascenev1.SessionTeam` objects, but are diff --git a/dist/ba_data/python/bascenev1lib/activity/coopjoin.py b/dist/ba_data/python/bascenev1lib/activity/coopjoin.py index f8f7506..0b8a28d 100644 --- a/dist/ba_data/python/bascenev1lib/activity/coopjoin.py +++ b/dist/ba_data/python/bascenev1lib/activity/coopjoin.py @@ -63,10 +63,10 @@ class CoopJoinActivity(bs.JoinActivity): vpos = -140.0 # Now list our remaining achievements for this level. - assert self.session.campaign is not None assert isinstance(self.session, bs.CoopSession) + assert self.session.campaign is not None levelname = ( - self.session.campaign.name + ':' + self.session.campaign_level_name + f'{self.session.campaign.name}:{self.session.campaign_level_name}' ) ts_h_offs = 60 diff --git a/dist/ba_data/python/bascenev1lib/activity/coopscore.py b/dist/ba_data/python/bascenev1lib/activity/coopscore.py index bb832dd..85a5f93 100644 --- a/dist/ba_data/python/bascenev1lib/activity/coopscore.py +++ b/dist/ba_data/python/bascenev1lib/activity/coopscore.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides a score screen for coop games.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -10,7 +11,7 @@ import logging from typing import TYPE_CHECKING, override from efro.util import strict_partial -import bacommon.bs +import bacommon.classic from bacommon.login import LoginType import bascenev1 as bs import bauiv1 as bui @@ -133,10 +134,10 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): assert all(isinstance(i, bs.PlayerInfo) for i in self._playerinfos) self._score: int | None = settings['score'] - assert isinstance(self._score, (int, type(None))) + assert isinstance(self._score, int | None) self._fail_message: bs.Lstr | None = settings['fail_message'] - assert isinstance(self._fail_message, (bs.Lstr, type(None))) + assert isinstance(self._fail_message, bs.Lstr | None) self._begin_time: float | None = None @@ -205,7 +206,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): def _ui_menu(self) -> None: bui.containerwidget(edit=self._root_ui, transition='out_left') with self.context: - bs.timer(0.1, bs.Call(bs.WeakCall(self.session.end))) + bs.timer(0.1, bs.CallStrict(bs.WeakCallStrict(self.session.end))) def _ui_restart(self) -> None: from bauiv1lib.tournamententry import TournamentEntryWindow @@ -309,7 +310,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): bui.getsound('error').play() bs.timer( 2.0, - bs.WeakCall( + bs.WeakCallStrict( self._next_level_error.handlemessage, bs.DieMessage() ), ) @@ -332,7 +333,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): # main menu up, so instead we add a callback for when the menu # closes; if we're still alive, we'll come up then. # If there's no main menu this gets called immediately. - classic.add_main_menu_close_callback(bui.WeakCall(self.show_ui)) + classic.add_main_menu_close_callback(bui.WeakCallStrict(self.show_ui)) def show_ui(self) -> None: """Show the UI for restarting, playing the next Level, etc.""" @@ -345,7 +346,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): delay = 0.7 if (self._score is not None) else 0.0 # If there's no players left in the game, lets not show the UI - # (that would allow restarting the game with zero players, etc). + # (it would allow restarting the game with zero players, etc). if not self.players: return @@ -373,7 +374,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): position=(h_offs - 520, v_offs + 450 - 235 + 40), size=(300, 60), label=bui.Lstr(resource='achievementsText'), - on_activate_call=bui.WeakCall(self._ui_show_achievements), + on_activate_call=bui.WeakCallStrict(self._ui_show_achievements), transition_delay=delay + 1.5, icon=self._game_service_achievements_texture, icon_color=self._game_service_icon_color, @@ -397,7 +398,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ) ), autoselect=True, - on_activate_call=bui.WeakCall(self._ui_worlds_best), + on_activate_call=bui.WeakCallStrict(self._ui_worlds_best), transition_delay=delay + 1.9, selectable=can_select_extra_buttons, ) @@ -427,7 +428,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): size=(100, 50), label='', button_type='square', - on_activate_call=bui.WeakCall(self._ui_menu), + on_activate_call=bui.WeakCallStrict(self._ui_menu), ) bui.imagewidget( parent=rootc, @@ -444,7 +445,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): position=(h_offs - 130 - 60, v_offs), size=(110, 85), label='', - on_activate_call=bui.WeakCall(self._ui_menu), + on_activate_call=bui.WeakCallStrict(self._ui_menu), ) bui.imagewidget( parent=rootc, @@ -463,7 +464,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): size=(100, 50), label='', button_type='square', - on_activate_call=bui.WeakCall(self._ui_restart), + on_activate_call=bui.WeakCallStrict(self._ui_restart), ) bui.imagewidget( parent=rootc, @@ -480,7 +481,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): position=(h_offs - 60, v_offs), size=(110, 85), label='', - on_activate_call=bui.WeakCall(self._ui_restart), + on_activate_call=bui.WeakCallStrict(self._ui_restart), ) bui.imagewidget( parent=rootc, @@ -497,12 +498,12 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): # level yet and invisible if there is none. if show_next_button: if self._is_complete: - call = bui.WeakCall(self._ui_next) + call = bui.WeakCallStrict(self._ui_next) button_sound = True image_opacity = 0.8 color = None else: - call = bui.WeakCall(self._ui_error) + call = bui.WeakCallStrict(self._ui_error) button_sound = False image_opacity = 0.2 color = (0.3, 0.3, 0.3) @@ -615,7 +616,9 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): 0, self._birth_time + self._min_view_time - bs.time() ) - bs.timer(time_till_assign, bs.WeakCall(self._safe_assign, player)) + bs.timer( + time_till_assign, bs.WeakCallStrict(self._safe_assign, player) + ) @override def on_begin(self) -> None: @@ -661,7 +664,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): cfg.commit() self._campaign.set_selected_level(self._next_level_name) - bs.timer(1.0, bs.WeakCall(self.request_ui)) + bs.timer(1.0, bs.WeakCallStrict(self.request_ui)) variant = bs.app.env.variant vart = type(variant) @@ -793,9 +796,9 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): self._show_info = {} if self._score is not None: - bs.timer(0.8, bs.WeakCall(self._show_score_val, offs_x)) + bs.timer(0.8, bs.WeakCallStrict(self._show_score_val, offs_x)) else: - bs.pushcall(bs.WeakCall(self._show_fail)) + bs.pushcall(bs.WeakCallStrict(self._show_fail)) self._name_str = name_str = ', '.join( [p.name for p in self._playerinfos] @@ -814,7 +817,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ) if self._score is not None and self._submit_score: - bs.timer(0.4, bs.WeakCall(self._play_drumroll)) + bs.timer(0.4, bs.WeakCallStrict(self._play_drumroll)) # Add us to high scores, filter, and store. our_high_scores_all = self._campaign.getlevel( @@ -866,7 +869,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): # We expect this only in kiosk mode; complain otherwise. if not arcade_or_demo: logging.error('got not-signed-in at score-submit; unexpected') - bs.pushcall(bs.WeakCall(self._got_score_results, None)) + bs.pushcall(bs.WeakCallStrict(self._got_score_results, None)) else: assert self._game_name_str is not None assert self._game_config_str is not None @@ -875,7 +878,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): self._game_config_str, name_str, self._score, - bs.WeakCall(self._got_score_results), + bs.WeakCallPartial(self._got_score_results), order=self._score_order, tournament_id=self.session.tournament_id, score_type=self._score_type, @@ -1059,7 +1062,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): vval -= 55 tdelay += 0.250 - bs.timer(5.0, bs.WeakCall(self._show_tips)) + bs.timer(5.0, bs.WeakCallStrict(self._show_tips)) def _play_drumroll(self) -> None: bs.NodeActor( @@ -1209,14 +1212,14 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ).autoretain() def _on_v2_score_results( - self, response: bacommon.bs.ScoreSubmitResponse | Exception + self, response: bacommon.classic.ScoreSubmitResponse | Exception ) -> None: if isinstance(response, Exception): logging.debug('Got error score-submit response: %s', response) return - assert isinstance(response, bacommon.bs.ScoreSubmitResponse) + assert isinstance(response, bacommon.classic.ScoreSubmitResponse) # Aim to have these effects run shortly after the final rating # hit happens. @@ -1275,8 +1278,10 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ): with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.ScoreSubmitMessage(score_token), - on_response=bui.WeakCall(self._on_v2_score_results), + bacommon.classic.ScoreSubmitMessage(score_token), + on_response=bui.WeakCallPartial( + self._on_v2_score_results + ), ) self._score_link = results['link'] @@ -1297,7 +1302,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): self._tournament_time_remaining = secs_remaining self._tournament_time_remaining_text_timer = bs.BaseTimer( 1.0, - bs.WeakCall( + bs.WeakCallStrict( self._update_tournament_time_remaining_text ), repeat=True, @@ -1315,7 +1320,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): if self._score is not None: bs.basetimer( (1.5 + base_delay), - bs.WeakCall(self._show_world_rank, offs_x), + bs.WeakCallStrict(self._show_world_rank, offs_x), ) ts_h_offs = 280 ts_height = 300 @@ -1574,7 +1579,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): ] # pylint: disable=useless-suppression # pylint: disable=unbalanced-tuple-unpacking - (pr1, pv1, pr2, pv2, pr3, pv3) = ( + pr1, pv1, pr2, pv2, pr3, pv3 = ( bs.app.classic.get_tournament_prize_strings( tourney_info, include_tickets=False ) diff --git a/dist/ba_data/python/bascenev1lib/activity/dualteamscore.py b/dist/ba_data/python/bascenev1lib/activity/dualteamscore.py index 6929a10..ef5d70a 100644 --- a/dist/ba_data/python/bascenev1lib/activity/dualteamscore.py +++ b/dist/ba_data/python/bascenev1lib/activity/dualteamscore.py @@ -61,7 +61,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): for team in self.session.sessionteams: bs.timer( i * 0.15 + 0.15, - bs.WeakCall( + bs.WeakCallStrict( self._show_team_name, vval - i * height, team, @@ -76,7 +76,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): delay = 1.2 bs.timer( i * 0.150 + 0.2, - bs.WeakCall( + bs.WeakCallStrict( self._show_team_old_score, vval - i * height, team, @@ -87,7 +87,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): bs.timer( i * 0.150 + delay, - bs.WeakCall( + bs.WeakCallStrict( self._show_team_score, vval - i * height, team, diff --git a/dist/ba_data/python/bascenev1lib/activity/freeforallvictory.py b/dist/ba_data/python/bascenev1lib/activity/freeforallvictory.py index 3f88e3b..e05a643 100644 --- a/dist/ba_data/python/bascenev1lib/activity/freeforallvictory.py +++ b/dist/ba_data/python/bascenev1lib/activity/freeforallvictory.py @@ -132,7 +132,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, title.position_combine, 'input0', @@ -160,7 +160,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ).autoretain() bs.timer( tdelay + delay2, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, img.position_combine, 'input1', @@ -172,7 +172,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, img.position_combine, 'input0', @@ -198,7 +198,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ).autoretain() bs.timer( tdelay + delay2, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, txt.position_combine, 'input1', @@ -210,7 +210,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, txt.position_combine, 'input0', @@ -235,7 +235,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ).autoretain() bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, txt_num.position_combine, 'input0', @@ -256,7 +256,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay2, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, s_txt.position_combine, 'input1', @@ -268,7 +268,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, s_txt.position_combine, 'input0', @@ -297,7 +297,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay2, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, s_txt_2.position_combine, 'input1', @@ -309,7 +309,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) bs.timer( tdelay + delay3, - bs.WeakCall( + bs.WeakCallStrict( self._safe_animate, s_txt_2.position_combine, 'input0', @@ -328,12 +328,14 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): bs.timer( tdelay + delay1, - bs.Call(_safesetattr, s_txt.node, 'color', (1, 1, 1, 1)), + bs.CallStrict( + _safesetattr, s_txt.node, 'color', (1, 1, 1, 1) + ), ) for j in range(score_change): bs.timer( (tdelay + delay1 + 0.15 * j), - bs.Call( + bs.CallStrict( _safesetattr, s_txt.node, 'text', diff --git a/dist/ba_data/python/bascenev1lib/activity/multiteamscore.py b/dist/ba_data/python/bascenev1lib/activity/multiteamscore.py index 0bf4bd3..b8f6089 100644 --- a/dist/ba_data/python/bascenev1lib/activity/multiteamscore.py +++ b/dist/ba_data/python/bascenev1lib/activity/multiteamscore.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to teams mode score screen.""" + from __future__ import annotations from typing import override diff --git a/dist/ba_data/python/bascenev1lib/activity/multiteamvictory.py b/dist/ba_data/python/bascenev1lib/activity/multiteamvictory.py index 058ffd4..8052893 100644 --- a/dist/ba_data/python/bascenev1lib/activity/multiteamvictory.py +++ b/dist/ba_data/python/bascenev1lib/activity/multiteamvictory.py @@ -4,14 +4,14 @@ from __future__ import annotations -from typing import override, TYPE_CHECKING +from typing import override, TYPE_CHECKING, Any, cast import bascenev1 as bs from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity if TYPE_CHECKING: - from typing import Any + pass class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): @@ -54,9 +54,10 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): winning_sessionteam = self.settings_raw['winner'] # Pause a moment before playing victory music. - bs.timer(0.6, bs.WeakCall(self._play_victory_music)) + bs.timer(0.6, bs.WeakCallStrict(self._play_victory_music)) bs.timer( - 4.4, bs.WeakCall(self._show_winner, self.settings_raw['winner']) + 4.4, + bs.WeakCallStrict(self._show_winner, self.settings_raw['winner']), ) bs.timer(4.6, self._score_display_sound.play) @@ -76,9 +77,9 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): ) player_entries.sort(reverse=True, key=lambda x: x[0]) if len(player_entries) > 0: - # Store some info for the top ffa player so we can - # show winner info even if they leave. - self._ffa_top_player_info = list(player_entries[0]) + # Store some info for the top ffa player so we can show + # winner info even if they leave. + self._ffa_top_player_info = cast(Any, list(player_entries[0])) self._ffa_top_player_info[1] = self._ffa_top_player_info[ 2 ].getname() @@ -178,6 +179,7 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): transition_delay=t_incr * 4, ).autoretain() + assert isinstance(session, bs.MultiTeamSession) win_score = (session.get_series_length() - 1) // 2 + 1 lose_score = 0 for team in self.teams: @@ -421,7 +423,7 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): transition_delay=tdelay, ).autoretain() - bs.timer(15.0, bs.WeakCall(self._show_tips)) + bs.timer(15.0, bs.WeakCallStrict(self._show_tips)) def _show_tips(self) -> None: from bascenev1lib.actor.tipstext import TipsText diff --git a/dist/ba_data/python/bascenev1lib/actor/bomb.py b/dist/ba_data/python/bascenev1lib/actor/bomb.py index 04dc297..a4b92a3 100644 --- a/dist/ba_data/python/bascenev1lib/actor/bomb.py +++ b/dist/ba_data/python/bascenev1lib/actor/bomb.py @@ -864,10 +864,11 @@ class Bomb(bs.Actor): }, ) self.arm_timer = bs.Timer( - 0.2, bs.WeakCall(self.handlemessage, ArmMessage()) + 0.2, bs.WeakCallStrict(self.handlemessage, ArmMessage()) ) self.warn_timer = bs.Timer( - fuse_time - 1.7, bs.WeakCall(self.handlemessage, WarnMessage()) + fuse_time - 1.7, + bs.WeakCallStrict(self.handlemessage, WarnMessage()), ) else: @@ -918,7 +919,8 @@ class Bomb(bs.Actor): if self.bomb_type not in ('land_mine', 'tnt'): assert fuse_time is not None bs.timer( - fuse_time, bs.WeakCall(self.handlemessage, ExplodeMessage()) + fuse_time, + bs.WeakCallStrict(self.handlemessage, ExplodeMessage()), ) bs.animate( @@ -976,7 +978,7 @@ class Bomb(bs.Actor): def _handle_dropped(self) -> None: if self.bomb_type == 'land_mine': self.arm_timer = bs.Timer( - 1.25, bs.WeakCall(self.handlemessage, ArmMessage()) + 1.25, bs.WeakCallStrict(self.handlemessage, ArmMessage()) ) # Once we've thrown a sticky bomb we can stick to it. @@ -1028,7 +1030,7 @@ class Bomb(bs.Actor): # We blew up so we need to go away. # NOTE TO SELF: do we actually need this delay? - bs.timer(0.001, bs.WeakCall(self.handlemessage, bs.DieMessage())) + bs.timer(0.001, bs.WeakCallStrict(self.handlemessage, bs.DieMessage())) def _handle_warn(self) -> None: if self.texture_sequence and self.node: @@ -1064,7 +1066,7 @@ class Bomb(bs.Actor): # We now make it explodable. bs.timer( 0.25, - bs.WeakCall( + bs.WeakCallStrict( self._add_material, factory.land_mine_blast_material ), ) @@ -1081,7 +1083,7 @@ class Bomb(bs.Actor): ) bs.timer( 0.25, - bs.WeakCall( + bs.WeakCallStrict( self._add_material, factory.land_mine_blast_material ), ) @@ -1121,7 +1123,7 @@ class Bomb(bs.Actor): bs.timer( 0.1 + random.random() * 0.1, - bs.WeakCall(self.handlemessage, ExplodeMessage()), + bs.WeakCallStrict(self.handlemessage, ExplodeMessage()), ) assert self.node self.node.handlemessage( @@ -1190,7 +1192,7 @@ class TNTSpawner: # Go with slightly more than 1 second to avoid timer stacking. self._update_timer = bs.Timer( - 1.1, bs.WeakCall(self._update), repeat=True + 1.1, bs.WeakCallStrict(self._update), repeat=True ) def _update(self) -> None: diff --git a/dist/ba_data/python/bascenev1lib/actor/controlsguide.py b/dist/ba_data/python/bascenev1lib/actor/controlsguide.py index 40b3f18..966d41e 100644 --- a/dist/ba_data/python/bascenev1lib/actor/controlsguide.py +++ b/dist/ba_data/python/bascenev1lib/actor/controlsguide.py @@ -263,7 +263,7 @@ class ControlsGuide(bs.Actor): node.opacity = 0.0 # Don't do anything until our delay has passed. - bs.timer(delay, bs.WeakCall(self._start_updating)) + bs.timer(delay, bs.WeakCallStrict(self._start_updating)) @staticmethod def _meaningful_button_name( @@ -290,10 +290,12 @@ class ControlsGuide(bs.Actor): if self._lifespan is not None: self._cancel_timer = bs.Timer( self._lifespan, - bs.WeakCall(self.handlemessage, bs.DieMessage(immediate=True)), + bs.WeakCallStrict( + self.handlemessage, bs.DieMessage(immediate=True) + ), ) self._fade_in_timer = bs.Timer( - 1.0, bs.WeakCall(self._check_fade_in), repeat=True + 1.0, bs.WeakCallStrict(self._check_fade_in), repeat=True ) self._check_fade_in() # Do one check immediately. @@ -349,11 +351,12 @@ class ControlsGuide(bs.Actor): # If we were given a lifespan, transition out after it. if self._lifespan is not None: bs.timer( - self._lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage()) + self._lifespan, + bs.WeakCallStrict(self.handlemessage, bs.DieMessage()), ) self._update() self._update_timer = bs.Timer( - 1.0, bs.WeakCall(self._update), repeat=True + 1.0, bs.WeakCallStrict(self._update), repeat=True ) def _update(self) -> None: @@ -565,6 +568,6 @@ class ControlsGuide(bs.Actor): # die later. for node in self._nodes: bs.animate(node, 'opacity', {0: node.opacity, 3.0: 0.0}) - bs.timer(3.1, bs.WeakCall(self._die)) + bs.timer(3.1, bs.WeakCallStrict(self._die)) return None return super().handlemessage(msg) diff --git a/dist/ba_data/python/bascenev1lib/actor/flag.py b/dist/ba_data/python/bascenev1lib/actor/flag.py index 591c73b..3d42d02 100644 --- a/dist/ba_data/python/bascenev1lib/actor/flag.py +++ b/dist/ba_data/python/bascenev1lib/actor/flag.py @@ -211,7 +211,7 @@ class Flag(bs.Actor): if self._dropped_timeout is not None: self._count = self._dropped_timeout self._tick_timer = bs.Timer( - 1.0, call=bs.WeakCall(self._tick), repeat=True + 1.0, call=bs.WeakCallStrict(self._tick), repeat=True ) self._counter = bs.newnode( 'text', @@ -314,7 +314,7 @@ class Flag(bs.Actor): self._score_text.color = bs.safecolor(self.node.color) bs.animate(self._score_text, 'scale', {0: start_scale, 0.2: 0.02}) self._score_text_hide_timer = bs.Timer( - 1.0, bs.WeakCall(self._hide_score_text) + 1.0, bs.WeakCallStrict(self._hide_score_text) ) @override diff --git a/dist/ba_data/python/bascenev1lib/actor/image.py b/dist/ba_data/python/bascenev1lib/actor/image.py index 4e38f6b..bf84859 100644 --- a/dist/ba_data/python/bascenev1lib/actor/image.py +++ b/dist/ba_data/python/bascenev1lib/actor/image.py @@ -169,7 +169,7 @@ class Image(bs.Actor): if transition_out_delay is not None: bs.timer( transition_delay + transition_out_delay + 1.0, - bs.WeakCall(self.handlemessage, bs.DieMessage()), + bs.WeakCallStrict(self.handlemessage, bs.DieMessage()), ) @override diff --git a/dist/ba_data/python/bascenev1lib/actor/onscreentimer.py b/dist/ba_data/python/bascenev1lib/actor/onscreentimer.py index 196674e..8326aaf 100644 --- a/dist/ba_data/python/bascenev1lib/actor/onscreentimer.py +++ b/dist/ba_data/python/bascenev1lib/actor/onscreentimer.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Defines Actor(s).""" + from __future__ import annotations from typing import TYPE_CHECKING, override diff --git a/dist/ba_data/python/bascenev1lib/actor/popuptext.py b/dist/ba_data/python/bascenev1lib/actor/popuptext.py index 9c0d09c..e332954 100644 --- a/dist/ba_data/python/bascenev1lib/actor/popuptext.py +++ b/dist/ba_data/python/bascenev1lib/actor/popuptext.py @@ -116,7 +116,7 @@ class PopupText(bs.Actor): # kill ourself self._die_timer = bs.Timer( - lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage()) + lifespan, bs.WeakCallStrict(self.handlemessage, bs.DieMessage()) ) @override diff --git a/dist/ba_data/python/bascenev1lib/actor/powerupbox.py b/dist/ba_data/python/bascenev1lib/actor/powerupbox.py index dd19b54..cf3f866 100644 --- a/dist/ba_data/python/bascenev1lib/actor/powerupbox.py +++ b/dist/ba_data/python/bascenev1lib/actor/powerupbox.py @@ -265,11 +265,11 @@ class PowerupBox(bs.Actor): if expire: bs.timer( DEFAULT_POWERUP_INTERVAL - 2.5, - bs.WeakCall(self._start_flashing), + bs.WeakCallStrict(self._start_flashing), ) bs.timer( DEFAULT_POWERUP_INTERVAL - 1.0, - bs.WeakCall(self.handlemessage, bs.DieMessage()), + bs.WeakCallStrict(self.handlemessage, bs.DieMessage()), ) def _start_flashing(self) -> None: diff --git a/dist/ba_data/python/bascenev1lib/actor/respawnicon.py b/dist/ba_data/python/bascenev1lib/actor/respawnicon.py index 3e31350..b5b5b58 100644 --- a/dist/ba_data/python/bascenev1lib/actor/respawnicon.py +++ b/dist/ba_data/python/bascenev1lib/actor/respawnicon.py @@ -66,6 +66,7 @@ class RespawnIcon: ) ) + assert self._image assert self._image.node bs.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7}) @@ -89,6 +90,7 @@ class RespawnIcon: ) ) + assert self._name assert self._name.node bs.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5}) @@ -133,6 +135,7 @@ class RespawnIcon: ) ) + assert self._text assert self._text.node bs.animate(self._text.node, 'scale', {0: 0, 0.1: 0.9}) if self._dec_text: @@ -142,7 +145,7 @@ class RespawnIcon: self._dec_timer: bs.Timer | None = None self._update() self._timer: bs.Timer | None = bs.Timer( - 1.0, bs.WeakCall(self._update), repeat=True + 1.0, bs.WeakCallStrict(self._update), repeat=True ) @property @@ -211,7 +214,7 @@ class RespawnIcon: # Start the timer to tick down. self._dec_timer = bs.Timer( 0.25, - bs.WeakCall(self._dec_step, ['..', '.', '']), + bs.WeakCallStrict(self._dec_step, ['..', '.', '']), repeat=True, ) else: diff --git a/dist/ba_data/python/bascenev1lib/actor/scoreboard.py b/dist/ba_data/python/bascenev1lib/actor/scoreboard.py index 18ba89d..3c0940a 100644 --- a/dist/ba_data/python/bascenev1lib/actor/scoreboard.py +++ b/dist/ba_data/python/bascenev1lib/actor/scoreboard.py @@ -189,7 +189,7 @@ class _Entry: def flash(self, countdown: bool, extra_flash: bool) -> None: """Flash momentarily.""" self._flash_timer = bs.Timer( - 0.1, bs.WeakCall(self._do_flash), repeat=True + 0.1, bs.WeakCallStrict(self._do_flash), repeat=True ) if countdown: self._flash_counter = 10 @@ -358,7 +358,7 @@ class _EntryProxy: return try: - bs.pushcall(bs.Call(scoreboard.remove_team, self._team_id)) + bs.pushcall(bs.CallStrict(scoreboard.remove_team, self._team_id)) except bs.ContextError: # This happens if we fire after the activity expires. # In that case we don't need to do anything. diff --git a/dist/ba_data/python/bascenev1lib/actor/spaz.py b/dist/ba_data/python/bascenev1lib/actor/spaz.py index f5bfab0..dbeb5f9 100644 --- a/dist/ba_data/python/bascenev1lib/actor/spaz.py +++ b/dist/ba_data/python/bascenev1lib/actor/spaz.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Defines the spaz actor.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -172,7 +173,9 @@ class Spaz(bs.Actor): if node: setattr(node, attr, val) - bs.timer(1.0, bs.Call(_safesetattr, self.node, 'invincible', False)) + bs.timer( + 1.0, bs.CallStrict(_safesetattr, self.node, 'invincible', False) + ) self.hitpoints = self.default_hitpoints self.hitpoints_max = self.default_hitpoints self.shield_hitpoints: int | None = None @@ -376,7 +379,7 @@ class Spaz(bs.Actor): bs.animate(self._score_text, 'scale', {0.0: start_scale, 0.2: 0.02}) self._score_text_hide_timer = bs.Timer( - 1.0, bs.WeakCall(self._hide_score_text) + 1.0, bs.WeakCallStrict(self._hide_score_text) ) def on_jump_press(self) -> None: @@ -462,7 +465,7 @@ class Spaz(bs.Actor): if not self.node.hold_node: bs.timer( 0.1, - bs.WeakCall( + bs.WeakCallStrict( self._safe_play_sound, SpazFactory.get().swish_sound, 0.8, @@ -629,7 +632,9 @@ class Spaz(bs.Actor): ) self._curse_timer = bs.Timer( self.curse_time, - bs.WeakCall(self.handlemessage, CurseExplodeMessage()), + bs.WeakCallStrict( + self.handlemessage, CurseExplodeMessage() + ), ) def equip_boxing_gloves(self) -> None: @@ -671,7 +676,7 @@ class Spaz(bs.Actor): if self.shield_decay_rate > 0: self.shield_decay_timer = bs.Timer( - 0.5, bs.WeakCall(self.shield_decay), repeat=True + 0.5, bs.WeakCallStrict(self.shield_decay), repeat=True ) # So user can see the decay. self.shield.always_show_health_bar = True @@ -718,12 +723,12 @@ class Spaz(bs.Actor): # Eww; seems we have to do this in a timer or it wont work right. # (since we're getting called from within update() perhaps?..) # NOTE: should test to see if that's still the case. - bs.timer(0.001, bs.WeakCall(self.shatter)) + bs.timer(0.001, bs.WeakCallStrict(self.shatter)) elif isinstance(msg, bs.ImpactDamageMessage): # Eww; seems we have to do this in a timer or it wont work right. # (since we're getting called from within update() perhaps?..) - bs.timer(0.001, bs.WeakCall(self._hit_self, msg.intensity)) + bs.timer(0.001, bs.WeakCallStrict(self._hit_self, msg.intensity)) elif isinstance(msg, bs.PowerupMessage): if self._dead or not self.node: @@ -744,11 +749,11 @@ class Spaz(bs.Actor): ) self._multi_bomb_wear_off_flash_timer = bs.Timer( (POWERUP_WEAR_OFF_TIME - 2000) / 1000.0, - bs.WeakCall(self._multi_bomb_wear_off_flash), + bs.WeakCallStrict(self._multi_bomb_wear_off_flash), ) self._multi_bomb_wear_off_timer = bs.Timer( POWERUP_WEAR_OFF_TIME / 1000.0, - bs.WeakCall(self._multi_bomb_wear_off), + bs.WeakCallStrict(self._multi_bomb_wear_off), ) elif msg.poweruptype == 'land_mines': self.set_land_mine_count(min(self.land_mine_count + 3, 3)) @@ -766,11 +771,11 @@ class Spaz(bs.Actor): ) self._bomb_wear_off_flash_timer = bs.Timer( (POWERUP_WEAR_OFF_TIME - 2000) / 1000.0, - bs.WeakCall(self._bomb_wear_off_flash), + bs.WeakCallStrict(self._bomb_wear_off_flash), ) self._bomb_wear_off_timer = bs.Timer( POWERUP_WEAR_OFF_TIME / 1000.0, - bs.WeakCall(self._bomb_wear_off), + bs.WeakCallStrict(self._bomb_wear_off), ) elif msg.poweruptype == 'sticky_bombs': self.bomb_type = 'sticky' @@ -786,11 +791,11 @@ class Spaz(bs.Actor): ) self._bomb_wear_off_flash_timer = bs.Timer( (POWERUP_WEAR_OFF_TIME - 2000) / 1000.0, - bs.WeakCall(self._bomb_wear_off_flash), + bs.WeakCallStrict(self._bomb_wear_off_flash), ) self._bomb_wear_off_timer = bs.Timer( POWERUP_WEAR_OFF_TIME / 1000.0, - bs.WeakCall(self._bomb_wear_off), + bs.WeakCallStrict(self._bomb_wear_off), ) elif msg.poweruptype == 'punch': tex = PowerupBoxFactory.get().tex_punch @@ -807,11 +812,11 @@ class Spaz(bs.Actor): ) self._boxing_gloves_wear_off_flash_timer = bs.Timer( (POWERUP_WEAR_OFF_TIME - 2000) / 1000.0, - bs.WeakCall(self._gloves_wear_off_flash), + bs.WeakCallStrict(self._gloves_wear_off_flash), ) self._boxing_gloves_wear_off_timer = bs.Timer( POWERUP_WEAR_OFF_TIME / 1000.0, - bs.WeakCall(self._gloves_wear_off), + bs.WeakCallStrict(self._gloves_wear_off), ) elif msg.poweruptype == 'shield': factory = SpazFactory.get() @@ -834,11 +839,11 @@ class Spaz(bs.Actor): ) self._bomb_wear_off_flash_timer = bs.Timer( (POWERUP_WEAR_OFF_TIME - 2000) / 1000.0, - bs.WeakCall(self._bomb_wear_off_flash), + bs.WeakCallStrict(self._bomb_wear_off_flash), ) self._bomb_wear_off_timer = bs.Timer( POWERUP_WEAR_OFF_TIME / 1000.0, - bs.WeakCall(self._bomb_wear_off), + bs.WeakCallStrict(self._bomb_wear_off), ) elif msg.poweruptype == 'health': if self._cursed: @@ -885,7 +890,8 @@ class Spaz(bs.Actor): self.frozen = True self.node.frozen = True bs.timer( - msg.time, bs.WeakCall(self.handlemessage, bs.ThawMessage()) + msg.time, + bs.WeakCallStrict(self.handlemessage, bs.ThawMessage()), ) # Instantly shatter if we're already dead. # (otherwise its hard to tell we're dead). @@ -1165,7 +1171,7 @@ class Spaz(bs.Actor): if self._cursed and damage > 0: bs.timer( 0.05, - bs.WeakCall( + bs.WeakCallStrict( self.curse_explode, msg.get_source_player(bs.Player) ), ) @@ -1384,7 +1390,7 @@ class Spaz(bs.Actor): if dropping_bomb: self.bomb_count -= 1 bomb.node.add_death_action( - bs.WeakCall(self.handlemessage, BombDiedMessage()) + bs.WeakCallStrict(self.handlemessage, BombDiedMessage()) ) self._pick_up(bomb.node) diff --git a/dist/ba_data/python/bascenev1lib/actor/spazappearance.py b/dist/ba_data/python/bascenev1lib/actor/spazappearance.py index e7521c9..1432bfc 100644 --- a/dist/ba_data/python/bascenev1lib/actor/spazappearance.py +++ b/dist/ba_data/python/bascenev1lib/actor/spazappearance.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Appearance functionality for spazzes.""" + from __future__ import annotations import bascenev1 as bs @@ -818,9 +819,9 @@ def register_appearances() -> None: t.death_sounds = ['oldLadyDeath'] t.pickup_sounds = old_lady_sounds t.fall_sounds = ['oldLadyFall'] - t.style = 'spaz' - t.default_color = (0.3, 0.5, 0.8) - t.default_highlight = (1, 0, 0) + t.style = 'bones' + t.default_color = (0.2, 1.0, 1.0) + t.default_highlight = (0.5, 0.25, 1.0) # Gladiator ################################### t = Appearance('Gladiator') diff --git a/dist/ba_data/python/bascenev1lib/actor/spazbot.py b/dist/ba_data/python/bascenev1lib/actor/spazbot.py index 7cbbcc8..660fa66 100644 --- a/dist/ba_data/python/bascenev1lib/actor/spazbot.py +++ b/dist/ba_data/python/bascenev1lib/actor/spazbot.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Bot versions of Spaz.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -111,12 +112,14 @@ class SpazBot(Spaz): can_accept_powerups=False, ) + from bascenev1lib.mainmenu import MainMenuActivity + # 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: Callable[[SpazBot], Any] | None = None activity = self.activity - assert isinstance(activity, bs.GameActivity) + assert isinstance(activity, (bs.GameActivity, MainMenuActivity)) self._map = weakref.ref(activity.map) self.last_player_attacked_by: bs.Player | None = None self.last_attacked_time = 0.0 @@ -327,10 +330,10 @@ class SpazBot(Spaz): self.node.jump_pressed = False # Throws: - bs.timer(0.1, bs.Call(_safe_pickup, self.node)) + bs.timer(0.1, bs.CallStrict(_safe_pickup, self.node)) else: # Throws: - bs.timer(0.1, bs.Call(_safe_pickup, self.node)) + bs.timer(0.1, bs.CallStrict(_safe_pickup, self.node)) if self.static: if time_till_throw < 0.3: @@ -906,6 +909,67 @@ class ExplodeyBotShielded(ExplodeyBot): points_mult = 5 +class DemoBot(SpazBot): + """A bs.SpazBot who lacks many specific traits and is used for the "Bots + Free-for-All" easter egg. + + category: Bot Classes + """ + + run = True + + @classmethod + def randomize_traits(cls, appearance: str) -> None: + """Randomize the behavioral traits of the bot. Should be called + everytime before creating a new instance. + """ + + cls.color = (random.random(), random.random(), random.random()) + cls.highlight = (random.random(), random.random(), random.random()) + cls.character = appearance + cls.punchiness = random.uniform(0.5, 1.0) + cls.throwiness = random.uniform(0.5, 1.0) + cls.bouncy = appearance == 'Easter Bunny' + cls.throw_rate = random.uniform(0.5, 2.0) + cls.default_bomb_type = random.choice( + ('normal', 'sticky', 'ice', 'impact') + ) + cls.default_boxing_gloves = random.choice((True, False, False, False)) + + @override + def __init__(self) -> None: + super().__init__() + self._init_time = bs.time() + + @override + def handlemessage(self, msg: Any) -> Any: + if ( + isinstance(msg, bs.HitMessage) + and self.node + and bs.time() - self._init_time <= 1.0 + ): + assert msg.force_direction is not None + self.node.handlemessage( + 'impulse', + msg.pos[0], + msg.pos[1], + msg.pos[2], + msg.velocity[0], + msg.velocity[1], + msg.velocity[2], + msg.magnitude * self.impact_scale, + msg.velocity_magnitude * self.impact_scale, + msg.radius, + 0, + msg.force_direction[0], + msg.force_direction[1], + msg.force_direction[2], + ) + self.node.handlemessage('hurt_sound') + return None + return super().handlemessage(msg) + + class SpazBotSet: """A container/controller for one or more bs.SpazBots. @@ -945,7 +1009,7 @@ class SpazBotSet: pt=pos, spawn_time=spawn_time, send_spawn_message=False, - spawn_callback=bs.Call( + spawn_callback=bs.CallStrict( self._spawn_bot, bot_type, pos, on_spawn_call ), ) @@ -1040,7 +1104,7 @@ class SpazBotSet: def start_moving(self) -> None: """Start processing bot AI updates so they start doing their thing.""" self._bot_update_timer = bs.Timer( - 0.05, bs.WeakCall(self._update), repeat=True + 0.05, bs.WeakCallStrict(self._update), repeat=True ) def stop_moving(self) -> None: @@ -1083,7 +1147,7 @@ class SpazBotSet: bot.node.move_up_down = 0 bs.timer( 0.5 * random.random(), - bs.Call(bot.handlemessage, bs.CelebrateMessage()), + bs.CallStrict(bot.handlemessage, bs.CelebrateMessage()), ) jump_duration = random.randrange(400, 500) j = random.randrange(0, 200) @@ -1093,18 +1157,58 @@ class SpazBotSet: j += jump_duration bs.timer( random.uniform(0.0, 1.0), - bs.Call(bot.node.handlemessage, 'attack_sound'), + bs.CallStrict(bot.node.handlemessage, 'attack_sound'), ) bs.timer( random.uniform(1.0, 2.0), - bs.Call(bot.node.handlemessage, 'attack_sound'), + bs.CallStrict(bot.node.handlemessage, 'attack_sound'), ) bs.timer( random.uniform(2.0, 3.0), - bs.Call(bot.node.handlemessage, 'attack_sound'), + bs.CallStrict(bot.node.handlemessage, 'attack_sound'), ) def add_bot(self, bot: SpazBot) -> None: """Add a bs.SpazBot instance to the set.""" self._bot_lists[self._bot_add_list].append(bot) self._bot_add_list = (self._bot_add_list + 1) % self._bot_list_count + + +class DemoSpazBotSet(SpazBotSet): + """A bs.SpazBotSet that has its bs.SpazBots attack every other bs.Spaz + instead of only going after bs.Players. + + category: Bot Classes + """ + + @override + def _update(self) -> None: + # Update one of our bot lists each time through. + # First off, remove no-longer-existing bots from the list. + try: + bot_list = self._bot_lists[self._bot_update_list] = [ + b for b in self._bot_lists[self._bot_update_list] if b + ] + except Exception: + bot_list = [] + logging.exception( + 'Error updating bot list: %s', + self._bot_lists[self._bot_update_list], + ) + self._bot_update_list = ( + self._bot_update_list + 1 + ) % self._bot_list_count + + # Update our list of player points for the bots to use. + spaz_pts = [] + our_bots = self.get_living_bots() + for node in bs.getnodes(): + spaz = node.getdelegate(Spaz) + if spaz and spaz.is_alive() and spaz not in our_bots: + spaz_pts.append( + (bs.Vec3(node.position), bs.Vec3(node.velocity)) + ) + + for bot in bot_list: + bot.set_player_points(spaz_pts) + bot.update_ai() diff --git a/dist/ba_data/python/bascenev1lib/actor/text.py b/dist/ba_data/python/bascenev1lib/actor/text.py index 42611e8..6fbed08 100644 --- a/dist/ba_data/python/bascenev1lib/actor/text.py +++ b/dist/ba_data/python/bascenev1lib/actor/text.py @@ -219,7 +219,7 @@ class Text(bs.Actor): if transition_out_delay is not None: bs.timer( transition_delay + transition_out_delay + 1.0, - bs.WeakCall(self.handlemessage, bs.DieMessage()), + bs.WeakCallStrict(self.handlemessage, bs.DieMessage()), ) @override diff --git a/dist/ba_data/python/bascenev1lib/actor/tipstext.py b/dist/ba_data/python/bascenev1lib/actor/tipstext.py index 9c16168..371188f 100644 --- a/dist/ba_data/python/bascenev1lib/actor/tipstext.py +++ b/dist/ba_data/python/bascenev1lib/actor/tipstext.py @@ -53,7 +53,7 @@ class TipsText(bs.Actor): self._message_spacing = 3000 self._change_timer = bs.Timer( 0.001 * (self._message_duration + self._message_spacing), - bs.WeakCall(self.change_phrase), + bs.WeakCallStrict(self.change_phrase), repeat=True, ) self._combine = bs.newnode( diff --git a/dist/ba_data/python/bascenev1lib/actor/zoomtext.py b/dist/ba_data/python/bascenev1lib/actor/zoomtext.py index d65b728..6049db2 100644 --- a/dist/ba_data/python/bascenev1lib/actor/zoomtext.py +++ b/dist/ba_data/python/bascenev1lib/actor/zoomtext.py @@ -81,12 +81,14 @@ class ZoomText(bs.Actor): positionadjusted2 = (shiftposition[0], shiftposition[1] - 100) bs.timer( shiftdelay, - bs.WeakCall(self._shift, positionadjusted, positionadjusted2), + bs.WeakCallStrict( + self._shift, positionadjusted, positionadjusted2 + ), ) if jitter > 0.0: bs.timer( shiftdelay + 0.25, - bs.WeakCall( + bs.WeakCallStrict( self._jitter, positionadjusted2, jitter * scale ), ) @@ -155,7 +157,9 @@ class ZoomText(bs.Actor): # if they give us a lifespan, kill ourself down the line if lifespan is not None: - bs.timer(lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage())) + bs.timer( + lifespan, bs.WeakCallStrict(self.handlemessage, bs.DieMessage()) + ) @override def handlemessage(self, msg: Any) -> Any: diff --git a/dist/ba_data/python/bascenev1lib/game/assault.py b/dist/ba_data/python/bascenev1lib/game/assault.py index 1f0938c..e9bf756 100644 --- a/dist/ba_data/python/bascenev1lib/game/assault.py +++ b/dist/ba_data/python/bascenev1lib/game/assault.py @@ -149,7 +149,7 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): ( 'call', 'at_connect', - bs.Call(self._handle_base_collide, team), + bs.CallStrict(self._handle_base_collide, team), ), ), ) @@ -270,7 +270,7 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): self._teleport(player, new_pos, random_num) bs.timer( 0.01, - bs.Call( + bs.CallStrict( self._teleport, player, new_pos, random_num ), ) diff --git a/dist/ba_data/python/bascenev1lib/game/capturetheflag.py b/dist/ba_data/python/bascenev1lib/game/capturetheflag.py index e62820d..cbe397b 100644 --- a/dist/ba_data/python/bascenev1lib/game/capturetheflag.py +++ b/dist/ba_data/python/bascenev1lib/game/capturetheflag.py @@ -534,7 +534,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): if team.flag_return_touches == 1: team.touch_return_timer = bs.Timer( 0.1, - call=bs.Call(self._touch_return_update, team), + call=bs.CallStrict(self._touch_return_update, team), repeat=True, ) team.touch_return_timer_ticking = None @@ -646,7 +646,9 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): elif isinstance(msg, FlagDiedMessage): assert isinstance(msg.flag, CTFFlag) - bs.timer(0.1, bs.Call(self._spawn_flag_for_team, msg.flag.team)) + bs.timer( + 0.1, bs.CallStrict(self._spawn_flag_for_team, msg.flag.team) + ) elif isinstance(msg, FlagPickedUpMessage): # Store the last player to hold the flag for scoring purposes. diff --git a/dist/ba_data/python/bascenev1lib/game/chosenone.py b/dist/ba_data/python/bascenev1lib/game/chosenone.py index 983521d..73bd609 100644 --- a/dist/ba_data/python/bascenev1lib/game/chosenone.py +++ b/dist/ba_data/python/bascenev1lib/game/chosenone.py @@ -168,7 +168,11 @@ class ChosenOneGame(bs.TeamGameActivity[Player, Team]): actions=( ('modify_part_collision', 'collide', True), ('modify_part_collision', 'physical', False), - ('call', 'at_connect', bs.WeakCall(self._handle_reset_collide)), + ( + 'call', + 'at_connect', + bs.WeakCallStrict(self._handle_reset_collide), + ), ), ) diff --git a/dist/ba_data/python/bascenev1lib/game/conquest.py b/dist/ba_data/python/bascenev1lib/game/conquest.py index ee9c355..da22e76 100644 --- a/dist/ba_data/python/bascenev1lib/game/conquest.py +++ b/dist/ba_data/python/bascenev1lib/game/conquest.py @@ -50,7 +50,7 @@ class Player(bs.Player['Team']): def respawn_timer(self) -> bs.Timer | None: """Type safe access to standard respawn timer.""" val = self.customdata.get('respawn_timer', None) - assert isinstance(val, (bs.Timer, type(None))) + assert isinstance(val, bs.Timer | None) return val @respawn_timer.setter @@ -61,7 +61,7 @@ class Player(bs.Player['Team']): def respawn_icon(self) -> RespawnIcon | None: """Type safe access to standard respawn icon.""" val = self.customdata.get('respawn_icon', None) - assert isinstance(val, (RespawnIcon, type(None))) + assert isinstance(val, RespawnIcon | None) return val @respawn_icon.setter diff --git a/dist/ba_data/python/bascenev1lib/game/easteregghunt.py b/dist/ba_data/python/bascenev1lib/game/easteregghunt.py index 443c77b..3f98c76 100644 --- a/dist/ba_data/python/bascenev1lib/game/easteregghunt.py +++ b/dist/ba_data/python/bascenev1lib/game/easteregghunt.py @@ -213,7 +213,7 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = bs.Timer( - respawn_time, bs.Call(self.spawn_player_if_exists, player) + respawn_time, bs.CallStrict(self.spawn_player_if_exists, player) ) player.respawn_icon = RespawnIcon(player, respawn_time) diff --git a/dist/ba_data/python/bascenev1lib/game/elimination.py b/dist/ba_data/python/bascenev1lib/game/elimination.py index 34f1d4a..cb274fd 100644 --- a/dist/ba_data/python/bascenev1lib/game/elimination.py +++ b/dist/ba_data/python/bascenev1lib/game/elimination.py @@ -495,7 +495,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): """Spawn a player (override).""" actor = self.spawn_player_spaz(player, self._get_spawn_point(player)) if not self._solo_mode: - bs.timer(0.3, bs.Call(self._print_lives, player)) + bs.timer(0.3, bs.CallStrict(self._print_lives, player)) # If we have any icons, update their state. for icon in player.icons: @@ -582,8 +582,9 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): # In solo, put ourself at the back of the spawn order. if self._solo_mode: - player.team.spawn_order.remove(player) - player.team.spawn_order.append(player) + if player in player.team.spawn_order: + player.team.spawn_order.remove(player) + player.team.spawn_order.append(player) def _update(self) -> None: if self._solo_mode: diff --git a/dist/ba_data/python/bascenev1lib/game/football.py b/dist/ba_data/python/bascenev1lib/game/football.py index df0a9fc..563ce62 100644 --- a/dist/ba_data/python/bascenev1lib/game/football.py +++ b/dist/ba_data/python/bascenev1lib/game/football.py @@ -518,8 +518,9 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): @override def on_begin(self) -> None: - # FIXME: Split this up a bit. + # pylint: disable=too-many-locals # pylint: disable=too-many-statements + from bascenev1lib.actor import controlsguide super().on_begin() @@ -572,11 +573,10 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): ) abot = BrawlerBot if self._preset == 'pro' else BrawlerBotLite typed_bot_list: list[type[SpazBot]] = [] - self._bot_types_7 = ( - typed_bot_list - + [abot] - + [BomberBot] * (1 if len(self.initialplayerinfos) < 3 else 2) + bomberbots: list[type[SpazBot]] = [BomberBot] * ( + 1 if len(self.initialplayerinfos) < 3 else 2 ) + self._bot_types_7 = typed_bot_list + [abot] + bomberbots bbot = TriggerBotPro if self._preset == 'pro' else TriggerBot self._bot_types_14 = [bbot] * ( 1 if len(self.initialplayerinfos) < 3 else 2 @@ -587,11 +587,9 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): abot = BrawlerBotPro if self._preset == 'uber' else BrawlerBot bbot = TriggerBotPro if self._preset == 'uber' else TriggerBot typed_bot_list_2: list[type[SpazBot]] = [] - self._bot_types_initial = ( - typed_bot_list_2 - + [StickyBot] - + [abot] * len(self.initialplayerinfos) - ) + stickybots: list[type[SpazBot]] = [StickyBot] + abots: list[type[SpazBot]] = [abot] * len(self.initialplayerinfos) + self._bot_types_initial = typed_bot_list_2 + stickybots + abots self._bot_types_7 = [bbot] * ( 1 if len(self.initialplayerinfos) < 3 else 2 ) @@ -733,7 +731,8 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): spawnpoints = self.map.powerup_spawn_points for i, _point in enumerate(spawnpoints): bs.timer( - 1.0 + i * 0.5, bs.Call(self._drop_powerup, i, poweruptype) + 1.0 + i * 0.5, + bs.CallStrict(self._drop_powerup, i, poweruptype), ) else: point = ( @@ -837,7 +836,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): bs.setmusic(None) self._bots.final_celebrate() - bs.timer(0.001, bs.Call(self.do_end, 'defeat')) + bs.timer(0.001, bs.CallStrict(self.do_end, 'defeat')) def update_scores(self) -> None: """update scoreboard and check for winners""" @@ -940,13 +939,13 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = bs.Timer( - respawn_time, bs.Call(self.spawn_player_if_exists, player) + respawn_time, bs.CallStrict(self.spawn_player_if_exists, player) ) player.respawn_icon = RespawnIcon(player, respawn_time) elif isinstance(msg, SpazBotDiedMessage): # Every time a bad guy dies, spawn a new one. - bs.timer(3.0, bs.Call(self._spawn_bot, (type(msg.spazbot)))) + bs.timer(3.0, bs.CallStrict(self._spawn_bot, (type(msg.spazbot)))) elif isinstance(msg, SpazBotPunchedMessage): if self._preset in ['rookie', 'rookie_easy']: diff --git a/dist/ba_data/python/bascenev1lib/game/keepaway.py b/dist/ba_data/python/bascenev1lib/game/keepaway.py index 6fe75ec..d8a11da 100644 --- a/dist/ba_data/python/bascenev1lib/game/keepaway.py +++ b/dist/ba_data/python/bascenev1lib/game/keepaway.py @@ -215,7 +215,7 @@ class KeepAwayGame(bs.TeamGameActivity[Player, Team]): for player in self.players: holdingflag = False try: - assert isinstance(player.actor, (PlayerSpaz, type(None))) + assert isinstance(player.actor, PlayerSpaz | None) if ( player.actor and player.actor.node diff --git a/dist/ba_data/python/bascenev1lib/game/kingofthehill.py b/dist/ba_data/python/bascenev1lib/game/kingofthehill.py index f4375af..7ee2c25 100644 --- a/dist/ba_data/python/bascenev1lib/game/kingofthehill.py +++ b/dist/ba_data/python/bascenev1lib/game/kingofthehill.py @@ -133,12 +133,16 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): ( 'call', 'at_connect', - bs.Call(self._handle_player_flag_region_collide, True), + bs.CallStrict( + self._handle_player_flag_region_collide, True + ), ), ( 'call', 'at_disconnect', - bs.Call(self._handle_player_flag_region_collide, False), + bs.CallStrict( + self._handle_player_flag_region_collide, False + ), ), ), ) @@ -192,15 +196,33 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): ) # Flag region. flagmats = [self._flag_region_material, shared.region_material] - bs.newnode( - 'region', - attrs={ - 'position': self._flag_pos, - 'scale': (1.8, 1.8, 1.8), - 'type': 'sphere', - 'materials': flagmats, - }, - ) + if self.map.getname() == 'Happy Thoughts': + # Exclusive region for happy thoughts, to avoid + # marking points from the bottom of the platform. + bs.newnode( + 'region', + attrs={ + 'position': ( + self._flag_pos[0], + self._flag_pos[1] * 1.06, + self._flag_pos[2], + ), + 'scale': (3.4, 1.75, 0.8), + 'type': 'square', + 'materials': flagmats, + }, + ) + + else: + bs.newnode( + 'region', + attrs={ + 'position': self._flag_pos, + 'scale': (1.8, 1.8, 1.8), + 'type': 'sphere', + 'materials': flagmats, + }, + ) self._update_scoreboard() self._update_flag_state() diff --git a/dist/ba_data/python/bascenev1lib/game/meteorshower.py b/dist/ba_data/python/bascenev1lib/game/meteorshower.py index 187c558..de400a6 100644 --- a/dist/ba_data/python/bascenev1lib/game/meteorshower.py +++ b/dist/ba_data/python/bascenev1lib/game/meteorshower.py @@ -218,7 +218,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): random.uniform(-3.066, -4.12), 0, ) - bs.timer(delay, bs.Call(self._drop_bomb, pos, vel)) + bs.timer(delay, bs.CallStrict(self._drop_bomb, pos, vel)) delay += 0.1 self._set_meteor_timer() diff --git a/dist/ba_data/python/bascenev1lib/game/onslaught.py b/dist/ba_data/python/bascenev1lib/game/onslaught.py index 8cec75f..6221b2a 100644 --- a/dist/ba_data/python/bascenev1lib/game/onslaught.py +++ b/dist/ba_data/python/bascenev1lib/game/onslaught.py @@ -972,7 +972,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): def _start_powerup_drops(self) -> None: self._powerup_drop_timer = bs.Timer( - 3.0, bs.WeakCall(self._drop_powerups), repeat=True + 3.0, bs.WeakCallStrict(self._drop_powerups), repeat=True ) def _drop_powerups( @@ -984,7 +984,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): for i in range(len(points)): bs.timer( 1.0 + i * 0.5, - bs.WeakCall( + bs.WeakCallStrict( self._drop_powerup, i, poweruptype if i == 0 else None ), ) @@ -1070,7 +1070,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): bs.timer(0, self._cashregistersound.play) bs.timer( base_delay, - bs.WeakCall(self._award_time_bonus, self._time_bonus), + bs.WeakCallStrict(self._award_time_bonus, self._time_bonus), ) base_delay += 1.0 @@ -1082,7 +1082,9 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): have_flawless = True bs.timer( base_delay, - bs.WeakCall(self._award_flawless_bonus, player), + bs.WeakCallStrict( + self._award_flawless_bonus, player + ), ) player.has_been_hurt = False # reset if have_flawless: @@ -1094,7 +1096,9 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): ) self.celebrate(20.0) self._award_completion_achievements() - bs.timer(base_delay, bs.WeakCall(self._award_completion_bonus)) + bs.timer( + base_delay, bs.WeakCallStrict(self._award_completion_bonus) + ) base_delay += 0.85 self._winsound.play() bs.cameraflash() @@ -1104,7 +1108,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): # Can't just pass delay to do_end because our extra bonuses # haven't been added yet (once we call do_end the score # gets locked in). - bs.timer(base_delay, bs.WeakCall(self.do_end, 'victory')) + bs.timer(base_delay, bs.WeakCallStrict(self.do_end, 'victory')) return self._wavenum += 1 @@ -1112,7 +1116,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): # Short celebration after waves. if self._wavenum > 1: self.celebrate(0.5) - bs.timer(base_delay, bs.WeakCall(self._start_next_wave)) + bs.timer(base_delay, bs.WeakCallStrict(self._start_next_wave)) def _award_completion_bonus(self) -> None: self._cashregistersound.play() @@ -1166,7 +1170,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): def _start_time_bonus_timer(self) -> None: self._time_bonus_timer = bs.Timer( - 1.0, bs.WeakCall(self._update_time_bonus), repeat=True + 1.0, bs.WeakCallStrict(self._update_time_bonus), repeat=True ) def _update_player_spawn_info(self) -> None: @@ -1240,7 +1244,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): point = info.point if point is not None: assert bot_type_2 is not None - spcall = bs.WeakCall( + spcall = bs.WeakCallStrict( self.add_bot_at_point, point, bot_type_2, spawn_time ) bs.timer(tval, spcall) @@ -1249,7 +1253,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): spacing = info.spacing bot_angle += spacing * 0.5 if bot_type_2 is not None: - tcall = bs.WeakCall( + tcall = bs.WeakCallStrict( self.add_bot_at_angle, bot_angle, bot_type_2, spawn_time ) bs.timer(tval, tcall) @@ -1259,7 +1263,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): # We can end the wave after all the spawning happens. bs.timer( tval + spawn_time - dtime + 0.01, - bs.WeakCall(self._set_can_end_wave), + bs.WeakCallStrict(self._set_can_end_wave), ) def _start_next_wave(self) -> None: @@ -1318,7 +1322,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): ) ) - bs.timer(5.0, bs.WeakCall(self._start_time_bonus_timer)) + bs.timer(5.0, bs.WeakCallStrict(self._start_time_bonus_timer)) wtcolor = (1, 1, 1, 1) wttxt = bs.Lstr( value='${A} ${B}', @@ -1510,7 +1514,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): def _start_updating_waves(self) -> None: self._wave_update_timer = bs.Timer( - 2.0, bs.WeakCall(self._update_waves), repeat=True + 2.0, bs.WeakCallStrict(self._update_waves), repeat=True ) def _update_scores(self) -> None: @@ -1606,7 +1610,8 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): self._tnt_kills += 1 if self._tnt_kills >= 6: bs.timer( - 0.5, bs.WeakCall(self._award_achievement, 'TNT Terror') + 0.5, + bs.WeakCallStrict(self._award_achievement, 'TNT Terror'), ) def _handle_pro_kill_achievements(self, msg: SpazBotDiedMessage) -> None: @@ -1616,7 +1621,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): if self._tnt_kills >= 3: bs.timer( 0.5, - bs.WeakCall( + bs.WeakCallStrict( self._award_achievement, 'Boom Goes the Dynamite' ), ) diff --git a/dist/ba_data/python/bascenev1lib/game/race.py b/dist/ba_data/python/bascenev1lib/game/race.py index 41ff4f6..aa48c29 100644 --- a/dist/ba_data/python/bascenev1lib/game/race.py +++ b/dist/ba_data/python/bascenev1lib/game/race.py @@ -649,7 +649,8 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): pos[2] + random.uniform(*z_range), ) bs.timer( - random.uniform(0.0, 2.0), bs.WeakCall(self._spawn_bomb_at_pos, pos) + random.uniform(0.0, 2.0), + bs.WeakCallStrict(self._spawn_bomb_at_pos, pos), ) def _spawn_bomb_at_pos(self, pos: Sequence[float]) -> None: @@ -690,7 +691,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): assert rmine is not None if not rmine.mine: self._flash_mine(m_index) - bs.timer(0.95, bs.Call(self._make_mine, m_index)) + bs.timer(0.95, bs.CallStrict(self._make_mine, m_index)) @override def spawn_player(self, player: Player) -> bs.Actor: diff --git a/dist/ba_data/python/bascenev1lib/game/runaround.py b/dist/ba_data/python/bascenev1lib/game/runaround.py index ddb14d6..287f7c3 100644 --- a/dist/ba_data/python/bascenev1lib/game/runaround.py +++ b/dist/ba_data/python/bascenev1lib/game/runaround.py @@ -576,7 +576,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): for _i in range(4): bs.timer( delay, - bs.Call( + bs.CallStrict( _safesetattr, self._lives_text.node, 'color', @@ -587,12 +587,14 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): assert self._lives_bg.node bs.timer( delay, - bs.Call(_safesetattr, self._lives_bg.node, 'opacity', 0.5), + bs.CallStrict( + _safesetattr, self._lives_bg.node, 'opacity', 0.5 + ), ) delay += 0.125 bs.timer( delay, - bs.Call( + bs.CallStrict( _safesetattr, self._lives_text.node, 'color', @@ -601,12 +603,14 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): ) bs.timer( delay, - bs.Call(_safesetattr, self._lives_bg.node, 'opacity', 1.0), + bs.CallStrict( + _safesetattr, self._lives_bg.node, 'opacity', 1.0 + ), ) delay += 0.125 bs.timer( delay, - bs.Call( + bs.CallStrict( _safesetattr, self._lives_text.node, 'color', @@ -666,7 +670,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): for i in range(len(points)): bs.timer( 1.0 + i * 0.5, - bs.Call( + bs.CallStrict( self._drop_powerup, i, force_first if i == 0 else None ), ) @@ -697,7 +701,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): def end_game(self) -> None: # (Pylint Bug?) pylint: disable=missing-function-docstring - bs.pushcall(bs.Call(self.do_end, 'defeat')) + bs.pushcall(bs.CallStrict(self.do_end, 'defeat')) bs.setmusic(None) self._player_death_sound.play() @@ -754,7 +758,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): bs.timer(0, self._cashregistersound.play) bs.timer( base_delay, - bs.Call(self._award_time_bonus, self._time_bonus), + bs.CallStrict(self._award_time_bonus, self._time_bonus), ) base_delay += 1.0 @@ -800,7 +804,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): bs.cameraflash() bs.setmusic(bs.MusicType.VICTORY) self._game_over = True - bs.timer(base_delay, bs.Call(self.do_end, 'victory')) + bs.timer(base_delay, bs.CallStrict(self.do_end, 'victory')) return self._wavenum += 1 @@ -1102,7 +1106,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): delay = base_delay delay /= self._get_bot_speed(bot_type) t_sec += delay * 0.5 - tcall = bs.Call( + tcall = bs.CallStrict( self.add_bot_at_point, point, bot_type, @@ -1219,7 +1223,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): spaztype, pos=pos, spawn_time=spawn_time, - on_spawn_call=bs.Call(self._on_bot_spawn, path), + on_spawn_call=bs.CallPartial(self._on_bot_spawn, path), ) def _update_time_bonus(self) -> None: @@ -1347,7 +1351,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): assert self.initialplayerinfos is not None respawn_time = 2.0 + len(self.initialplayerinfos) * 1.0 player.respawn_timer = bs.Timer( - respawn_time, bs.Call(self.spawn_player_if_exists, player) + respawn_time, bs.CallStrict(self.spawn_player_if_exists, player) ) player.respawn_icon = RespawnIcon(player, respawn_time) diff --git a/dist/ba_data/python/bascenev1lib/game/targetpractice.py b/dist/ba_data/python/bascenev1lib/game/targetpractice.py index ae0b3c1..805f1f5 100644 --- a/dist/ba_data/python/bascenev1lib/game/targetpractice.py +++ b/dist/ba_data/python/bascenev1lib/game/targetpractice.py @@ -398,6 +398,6 @@ class Target(bs.Actor): 1, {0.9: self._nodes[2].size, 1.1: [0.0]}, ) - bs.timer(1.1, bs.Call(self.handlemessage, bs.DieMessage())) + bs.timer(1.1, bs.CallStrict(self.handlemessage, bs.DieMessage())) return bullseye diff --git a/dist/ba_data/python/bascenev1lib/game/thelaststand.py b/dist/ba_data/python/bascenev1lib/game/thelaststand.py index 7cca417..ce0d058 100644 --- a/dist/ba_data/python/bascenev1lib/game/thelaststand.py +++ b/dist/ba_data/python/bascenev1lib/game/thelaststand.py @@ -127,8 +127,8 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): # Spit out a few powerups and start dropping more shortly. self._drop_powerups(standard_points=True) - bs.timer(2.0, bs.WeakCall(self._start_powerup_drops)) - bs.timer(0.001, bs.WeakCall(self._start_bot_updates)) + bs.timer(2.0, bs.WeakCallStrict(self._start_powerup_drops)) + bs.timer(0.001, bs.WeakCallStrict(self._start_bot_updates)) self.setup_low_life_warning_sound() self._update_scores() self._tntspawner = TNTSpawner( @@ -155,7 +155,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): if len(self.players) > 3: self._update_bots() self._bot_update_timer = bs.Timer( - self._bot_update_interval, bs.WeakCall(self._update_bots) + self._bot_update_interval, bs.WeakCallStrict(self._update_bots) ) def _drop_powerup(self, index: int, poweruptype: str | None = None) -> None: @@ -170,7 +170,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): def _start_powerup_drops(self) -> None: self._powerup_drop_timer = bs.Timer( - 3.0, bs.WeakCall(self._drop_powerups), repeat=True + 3.0, bs.WeakCallStrict(self._drop_powerups), repeat=True ) def _drop_powerups( @@ -184,7 +184,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): for i in range(len(pts)): bs.timer( 1.0 + i * 0.5, - bs.WeakCall( + bs.WeakCallStrict( self._drop_powerup, i, force_first if i == 0 else None ), ) @@ -227,7 +227,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): assert self._bot_update_interval is not None self._bot_update_interval = max(0.5, self._bot_update_interval * 0.98) self._bot_update_timer = bs.Timer( - self._bot_update_interval, bs.WeakCall(self._update_bots) + self._bot_update_interval, bs.WeakCallStrict(self._update_bots) ) botspawnpts: list[Sequence[float]] = [ [-5.0, 5.5, -4.14], @@ -346,7 +346,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): # Tell our bots to celebrate just to rub it in. self._bots.final_celebrate() bs.setmusic(None) - bs.pushcall(bs.WeakCall(self.do_end, 'defeat')) + bs.pushcall(bs.WeakCallStrict(self.do_end, 'defeat')) def _checkroundover(self) -> None: """End the round if conditions are met.""" diff --git a/dist/ba_data/python/bascenev1lib/mainmenu.py b/dist/ba_data/python/bascenev1lib/mainmenu.py index 760da9a..35d25a5 100644 --- a/dist/ba_data/python/bascenev1lib/mainmenu.py +++ b/dist/ba_data/python/bascenev1lib/mainmenu.py @@ -16,7 +16,9 @@ import bauiv1 as bui if TYPE_CHECKING: from typing import Any - import bacommon.bs + import bacommon.classic + + from bascenev1lib.actor.spazbot import DemoSpazBotSet class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): @@ -36,12 +38,9 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): self.version: bs.NodeActor | None = None self.beta_info: bs.NodeActor | None = None self.beta_info_2: bs.NodeActor | None = None - self.bottom: bs.NodeActor | None = None - self.vr_bottom_fill: bs.NodeActor | None = None - self.vr_top_fill: bs.NodeActor | None = None - self.terrain: bs.NodeActor | None = None + self.map: bs.Map | None = None + self.bot_sets: list[DemoSpazBotSet] = [] self.trees: bs.NodeActor | None = None - self.bgterrain: bs.NodeActor | None = None self._ts = 0.86 self._language: str | None = None self._update_timer: bs.Timer | None = None @@ -51,8 +50,13 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): @override def on_transition_in(self) -> None: - # pylint: disable=too-many-locals super().on_transition_in() + + from bascenev1lib.maps import ThePad + + ThePad.preload() + self.map = ThePad(main_menu_style=True) + random.seed(123) app = bs.app env = app.env @@ -108,17 +112,8 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): assert self.beta_info.node bs.animate(self.beta_info.node, 'opacity', {1.3: 0, 1.8: 1.0}) - mesh = bs.getmesh('thePadLevel') trees_mesh = bs.getmesh('trees') - bottom_mesh = bs.getmesh('thePadLevelBottom') - color_texture = bs.gettexture('thePadLevelColor') trees_texture = bs.gettexture('treesColor') - bgtex = bs.gettexture('menuBG') - bgmesh = bs.getmesh('thePadBG') - - # Load these last since most platforms don't use them. - vr_bottom_fill_mesh = bs.getmesh('thePadVRFillBottom') - vr_top_fill_mesh = bs.getmesh('thePadVRFillTop') gnode = self.globalsnode gnode.camera_mode = 'rotate' @@ -129,51 +124,6 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): gnode.vignette_outer = (0.45, 0.55, 0.54) gnode.vignette_inner = (0.99, 0.98, 0.98) - self.bottom = bs.NodeActor( - bs.newnode( - 'terrain', - attrs={ - 'mesh': bottom_mesh, - 'lighting': False, - 'reflection': 'soft', - 'reflection_scale': [0.45], - 'color_texture': color_texture, - }, - ) - ) - self.vr_bottom_fill = bs.NodeActor( - bs.newnode( - 'terrain', - attrs={ - 'mesh': vr_bottom_fill_mesh, - 'lighting': False, - 'vr_only': True, - 'color_texture': color_texture, - }, - ) - ) - self.vr_top_fill = bs.NodeActor( - bs.newnode( - 'terrain', - attrs={ - 'mesh': vr_top_fill_mesh, - 'vr_only': True, - 'lighting': False, - 'color_texture': bgtex, - }, - ) - ) - self.terrain = bs.NodeActor( - bs.newnode( - 'terrain', - attrs={ - 'mesh': mesh, - 'color_texture': color_texture, - 'reflection': 'soft', - 'reflection_scale': [0.3], - }, - ) - ) self.trees = bs.NodeActor( bs.newnode( 'terrain', @@ -186,24 +136,12 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): }, ) ) - self.bgterrain = bs.NodeActor( - bs.newnode( - 'terrain', - attrs={ - 'mesh': bgmesh, - 'color': (0.92, 0.91, 0.9), - 'lighting': False, - 'background': True, - 'color_texture': bgtex, - }, - ) - ) self._update_timer = bs.Timer(0.1, self._update, repeat=True) self._update() # Hopefully this won't hitch but lets space these out anyway. - bs.add_clean_frame_callback(bs.WeakCall(self._start_preloads)) + bs.add_clean_frame_callback(bs.WeakCallStrict(self._start_preloads)) random.seed() @@ -721,7 +659,7 @@ class NewsDisplay: # If we're signed in, fetch news immediately. Otherwise wait # until we are signed in. self._fetch_timer: bs.Timer | None = bs.Timer( - 1.0, bs.WeakCall(self._try_fetching_news), repeat=True + 1.0, bs.WeakCallStrict(self._try_fetching_news), repeat=True ) self._try_fetching_news() @@ -835,7 +773,7 @@ class NewsDisplay: ] self._phrase_change_timer = bs.Timer( (self._message_duration + self._message_spacing), - bs.WeakCall(self._change_phrase), + bs.WeakCallStrict(self._change_phrase), repeat=True, ) diff --git a/dist/ba_data/python/bascenev1lib/maps.py b/dist/ba_data/python/bascenev1lib/maps.py index c6aa225..23fcc78 100644 --- a/dist/ba_data/python/bascenev1lib/maps.py +++ b/dist/ba_data/python/bascenev1lib/maps.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Standard maps.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -783,26 +784,47 @@ class ThePad(bs.Map): # fixme should chop this into vr/non-vr sections for efficiency return data - def __init__(self) -> None: + def __init__(self, main_menu_style: bool = False) -> None: super().__init__() shared = SharedObjects.get() self.node = bs.newnode( 'terrain', delegate=self, - attrs={ - 'collision_mesh': self.preloaddata['collision_mesh'], - 'mesh': self.preloaddata['mesh'], - 'color_texture': self.preloaddata['tex'], - 'materials': [shared.footing_material], - }, + attrs=( + { + 'collision_mesh': self.preloaddata['collision_mesh'], + 'mesh': self.preloaddata['mesh'], + 'color_texture': self.preloaddata['tex'], + 'materials': [shared.footing_material], + 'reflection': 'soft', + 'reflection_scale': [0.3], + } + if main_menu_style + else { + 'collision_mesh': self.preloaddata['collision_mesh'], + 'mesh': self.preloaddata['mesh'], + 'color_texture': self.preloaddata['tex'], + 'materials': [shared.footing_material], + } + ), ) self.bottom = bs.newnode( 'terrain', - attrs={ - 'mesh': self.preloaddata['bottom_mesh'], - 'lighting': False, - 'color_texture': self.preloaddata['tex'], - }, + attrs=( + { + 'mesh': self.preloaddata['bottom_mesh'], + 'lighting': False, + 'color_texture': self.preloaddata['tex'], + 'reflection': 'soft', + 'reflection_scale': [0.45], + } + if main_menu_style + else { + 'mesh': self.preloaddata['bottom_mesh'], + 'lighting': False, + 'color_texture': self.preloaddata['tex'], + } + ), ) self.background = bs.newnode( 'terrain', diff --git a/dist/ba_data/python/bascenev1lib/tutorial.py b/dist/ba_data/python/bascenev1lib/tutorial.py index 341ec59..2d09a58 100644 --- a/dist/ba_data/python/bascenev1lib/tutorial.py +++ b/dist/ba_data/python/bascenev1lib/tutorial.py @@ -71,8 +71,8 @@ class ButtonPress: img = a.pickup_image color = a.pickup_image_color elif self._button == 'run': - call = bs.Call(s.on_run, 1.0) - release_call = bs.Call(s.on_run, 0.0) + call = bs.CallStrict(s.on_run, 1.0) + release_call = bs.CallStrict(s.on_run, 0.0) img = None color = None else: @@ -97,11 +97,11 @@ class ButtonPress: if img is not None: bs.timer( self._delay / 1000.0, - bs.Call(_safesetattr, img, 'color', c_bright), + bs.CallStrict(_safesetattr, img, 'color', c_bright), ) bs.timer( self._delay / 1000.0, - bs.Call(_safesetattr, img, 'vr_depth', -30), + bs.CallStrict(_safesetattr, img, 'vr_depth', -30), ) if self._release: if self._delay == 0 and self._release_delay == 0: @@ -113,11 +113,11 @@ class ButtonPress: if img is not None: bs.timer( (self._delay + self._release_delay + 100) / 1000.0, - bs.Call(_safesetattr, img, 'color', color), + bs.CallStrict(_safesetattr, img, 'color', color), ) bs.timer( (self._delay + self._release_delay + 100) / 1000.0, - bs.Call(_safesetattr, img, 'vr_depth', -20), + bs.CallStrict(_safesetattr, img, 'vr_depth', -20), ) @@ -149,7 +149,7 @@ class ButtonRelease: img = a.pickup_image color = a.pickup_image_color elif self._button == 'run': - call = bs.Call(s.on_run, 0.0) + call = bs.CallStrict(s.on_run, 0.0) img = None color = None else: @@ -161,11 +161,11 @@ class ButtonRelease: if img is not None: bs.timer( (self._delay + 100) / 1000.0, - bs.Call(_safesetattr, img, 'color', color), + bs.CallStrict(_safesetattr, img, 'color', color), ) bs.timer( (self._delay + 100 / 1000.0), - bs.Call(_safesetattr, img, 'vr_depth', -20), + bs.CallStrict(_safesetattr, img, 'vr_depth', -20), ) @@ -2429,7 +2429,7 @@ class TutorialActivity(bs.Activity[Player, Team]): # Otherwise try again in a few seconds. else: self._read_entries_timer = bs.Timer( - 3.0, bs.WeakCall(self._read_entries) + 3.0, bs.WeakCallStrict(self._read_entries) ) def _run_next_entry(self) -> None: @@ -2445,13 +2445,13 @@ class TutorialActivity(bs.Activity[Player, Team]): # otherwise just keep going. if result is not None: self._entry_timer = bs.Timer( - result / 1000.0, bs.WeakCall(self._run_next_entry) + result / 1000.0, bs.WeakCallStrict(self._run_next_entry) ) return # Done with these entries.. start over soon. self._read_entries_timer = bs.Timer( - 1.0, bs.WeakCall(self._read_entries) + 1.0, bs.WeakCallStrict(self._read_entries) ) def _update_skip_votes(self) -> None: @@ -2502,15 +2502,17 @@ class TutorialActivity(bs.Activity[Player, Team]): for _i in range(6): bs.timer( t / 1000.0, - bs.Call(setattr, self._skip_text, 'color', (1, 0.5, 0.1)), + bs.CallStrict( + setattr, self._skip_text, 'color', (1, 0.5, 0.1) + ), ) t += incr bs.timer( t / 1000.0, - bs.Call(setattr, self._skip_text, 'color', (1, 1, 0)), + bs.CallStrict(setattr, self._skip_text, 'color', (1, 1, 0)), ) t += incr - bs.timer(6.0, bs.WeakCall(self._revert_confirm)) + bs.timer(6.0, bs.WeakCallStrict(self._revert_confirm)) return player.pressed = True @@ -2546,7 +2548,7 @@ class TutorialActivity(bs.Activity[Player, Team]): bs.InputType.BOMB_PRESS, bs.InputType.PICK_UP_PRESS, ), - bs.Call(self._player_pressed_button, player), + bs.CallStrict(self._player_pressed_button, player), ) @override diff --git a/dist/ba_data/python/batemplatefs/_appsubsystem.py b/dist/ba_data/python/batemplatefs/_appsubsystem.py index 74a6ebd..8ba09bd 100644 --- a/dist/ba_data/python/batemplatefs/_appsubsystem.py +++ b/dist/ba_data/python/batemplatefs/_appsubsystem.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides the TemplateFs App-Subsystem.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/dist/ba_data/python/bauiv1/__init__.py b/dist/ba_data/python/bauiv1/__init__.py index a75bd09..e3887c9 100644 --- a/dist/ba_data/python/bauiv1/__init__.py +++ b/dist/ba_data/python/bauiv1/__init__.py @@ -38,6 +38,8 @@ from babase import ( asset_loads_allowed, balog, Call, + CallPartial, + CallStrict, DevConsoleButtonDef, DevConsoleTab, DevConsoleTabEntry, @@ -117,6 +119,8 @@ from babase import ( unlock_all_input, utc_now_cloud, WeakCall, + WeakCallPartial, + WeakCallStrict, workspaces_in_use, ) @@ -139,7 +143,6 @@ from _bauiv1 import ( root_ui_resume_updates, rowwidget, scrollwidget, - set_party_window_open, spinnerwidget, Sound, Texture, @@ -149,11 +152,11 @@ from _bauiv1 import ( widget, widget_by_id, ) -from bauiv1._cloudui import show_cloud_ui_window from bauiv1._keyboard import Keyboard from bauiv1._uitypes import ( uicleanupcheck, RootUIUpdatePause, + UIOpenState, ) from bauiv1._appsubsystem import UIV1AppSubsystem from bauiv1._window import ( @@ -189,6 +192,8 @@ __all__ = [ 'BasicMainWindowState', 'buttonwidget', 'Call', + 'CallPartial', + 'CallStrict', 'DevConsoleButtonDef', 'DevConsoleTab', 'DevConsoleTabEntry', @@ -277,9 +282,7 @@ __all__ = [ 'scrollwidget', 'set_analytics_screen', 'set_low_level_config_value', - 'set_party_window_open', 'set_main_ui_input_device', - 'show_cloud_ui_window', 'shutdown_suppress_begin', 'shutdown_suppress_end', 'Sound', @@ -294,11 +297,14 @@ __all__ = [ 'uibounds', 'uicleanupcheck', 'uilog', + 'UIOpenState', 'UIScale', 'UIV1AppSubsystem', 'unlock_all_input', 'utc_now_cloud', 'WeakCall', + 'WeakCallPartial', + 'WeakCallStrict', 'widget', 'widget_by_id', 'Widget', diff --git a/dist/ba_data/python/bauiv1/_appsubsystem.py b/dist/ba_data/python/bauiv1/_appsubsystem.py index 72bc0dd..a34892e 100644 --- a/dist/ba_data/python/bauiv1/_appsubsystem.py +++ b/dist/ba_data/python/bauiv1/_appsubsystem.py @@ -157,6 +157,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): window: bauiv1.MainWindow, *, back_state: MainWindowState | None, + extra_type_id: str = '', from_window: bauiv1.MainWindow | None | bool = True, is_back: bool = False, is_top_level: bool = False, @@ -228,6 +229,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): back_state.is_top_level is None or back_state.is_auxiliary is None or back_state.window_type is None + or back_state.extra_type_id is None ): raise RuntimeError( 'Provided back_state is incomplete.' @@ -292,15 +294,18 @@ class UIV1AppSubsystem(babase.AppSubsystem): assert back_state.is_top_level is not None assert back_state.is_auxiliary is not None assert back_state.window_type is type(window) + assert back_state.extra_type_id is not None window.main_window_back_state = back_state.parent window.main_window_is_top_level = back_state.is_top_level window.main_window_is_auxiliary = back_state.is_auxiliary + window.main_window_extra_type_id = back_state.extra_type_id else: # Store if the window is top-level so we won't complain # later if we go back from it and there's nowhere to go to. window.main_window_is_top_level = is_top_level window.main_window_is_auxiliary = is_auxiliary + window.main_window_extra_type_id = extra_type_id # When navigating forward, generate a back-window-state from # the outgoing window. @@ -354,19 +359,19 @@ class UIV1AppSubsystem(babase.AppSubsystem): winstate.is_top_level = window.main_window_is_top_level winstate.is_auxiliary = window.main_window_is_auxiliary winstate.window_type = type(window) + winstate.extra_type_id = window.main_window_extra_type_id return winstate def save_current_main_window_state(self) -> MainWindowState | None: """Save state for the current window, if any.""" - # Calc a back-state from the current window. + # Calc a state from the current window. current_main_win = self._main_window() if current_main_win is None: - # We currenty only hold weak refs to windows so that - # they are free to die on their own, but we expect - # the main menu window to keep itself alive as long - # as its the main one. Holler if that seems to not - # be happening. + # We currenty only hold weak refs to windows so that they + # are free to die on their own, but we expect the main menu + # window to keep itself alive as long as its the main one. + # Holler if that seems to not be happening. babase.uilog.warning( 'save_current_main_window_state: No old MainWindow found;' ' this should not happen.' @@ -384,6 +389,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): assert state.is_top_level is not None assert state.is_auxiliary is not None assert state.window_type is not None + assert state.extra_type_id is not None win = state.create_window(transition=None) self.set_main_window( @@ -393,6 +399,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): is_auxiliary=state.is_auxiliary, back_state=state.parent, suppress_warning=True, + extra_type_id=state.extra_type_id, ) def should_suppress_window_recreates(self) -> bool: @@ -466,6 +473,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): self, win_type: type[bauiv1.MainWindow], win_create_call: Callable[[], bauiv1.MainWindow], + win_extra_type_id: str = '', ) -> None: """Navigate to or away from an Auxiliary window. @@ -474,12 +482,12 @@ class UIV1AppSubsystem(babase.AppSubsystem): ranking windows that the user might want to visit without losing their place in the regular hierarchy. - Calling this method with a MainWindow of the provided type - already in the stack will back out past it (effectively toggling - the 'side quest' back off). + If an auxiliary window matching the provided type and + extra-type-id exists in the stack, this call will back out past + it (think of it as toggling the side-quest back off). - Calling this method with a *different* auxiliary window in the - stack will back out past that and replace it with this + If a non-matching auxiliary window exists in the stack, this + call will back out past that and replace it with this (effectively ending the old side-quest and starting a new one). """ # pylint: disable=unidiomatic-typecheck @@ -499,8 +507,12 @@ class UIV1AppSubsystem(babase.AppSubsystem): state = current_main_window.main_window_back_state while state is not None: assert state.window_type is not None + assert state.extra_type_id is not None if state.is_auxiliary: - if state.window_type is win_type: + if ( + state.window_type is win_type + and state.extra_type_id == win_extra_type_id + ): aux_matching_state = state else: aux_state = state @@ -518,7 +530,7 @@ class UIV1AppSubsystem(babase.AppSubsystem): current_main_window.main_window_back() return - # If there's an ancestory auxiliary state *not* matching our + # If there's an ancestor auxiliary state *not* matching our # type, crop the state and swap in our new auxiliary UI # (example: poking settings, then poking account, then poking # back should end up where things were before the settings @@ -532,19 +544,22 @@ class UIV1AppSubsystem(babase.AppSubsystem): back_state=aux_state.parent, suppress_warning=True, is_auxiliary=True, + extra_type_id=win_extra_type_id, ) return # Ok, no auxiliary states found. Now if current window is - # auxiliary and the type matches, simply do a back. + # auxiliary and the type/extra-id matches, simply do a back. if ( current_main_window.main_window_is_auxiliary and type(current_main_window) is win_type + and current_main_window.main_window_extra_type_id + == win_extra_type_id ): current_main_window.main_window_back() return - # If current window is auxiliary but type doesn't match, + # If current window is auxiliary but type/extra-id doesn't match, # swap it out for our new auxiliary UI. if current_main_window.main_window_is_auxiliary: self.clear_main_window() @@ -554,15 +569,25 @@ class UIV1AppSubsystem(babase.AppSubsystem): back_state=current_main_window.main_window_back_state, suppress_warning=True, is_auxiliary=True, + extra_type_id=win_extra_type_id, ) return # Ok, no existing auxiliary stuff was found period. Just # navigate forward to this UI. - current_main_window.main_window_replace( - win_create_call, is_auxiliary=True + new_main_win = current_main_window.main_window_replace( + win_create_call, + is_auxiliary=True, + extra_type_id=win_extra_type_id, ) + # We should always be allowed to replace the main win in this + # case. + assert new_main_win is not None + + # Make sure what got made exactly matches the type we were passed. + assert type(new_main_win) is win_type + def _schedule_main_win_recreate(self) -> None: # If there is a timer set already, do nothing. diff --git a/dist/ba_data/python/bauiv1/_hooks.py b/dist/ba_data/python/bauiv1/_hooks.py index 872f872..642b5e7 100644 --- a/dist/ba_data/python/bauiv1/_hooks.py +++ b/dist/ba_data/python/bauiv1/_hooks.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Snippets of code for use by the c++ layer.""" + # (most of these are self-explanatory) # pylint: disable=missing-function-docstring from __future__ import annotations diff --git a/dist/ba_data/python/bauiv1/_uitypes.py b/dist/ba_data/python/bauiv1/_uitypes.py index 3184da7..ffb7698 100644 --- a/dist/ba_data/python/bauiv1/_uitypes.py +++ b/dist/ba_data/python/bauiv1/_uitypes.py @@ -75,3 +75,23 @@ class RootUIUpdatePause: def __del__(self) -> None: _bauiv1.root_ui_resume_updates() + + +class UIOpenState: + """Keeps ui informed that something is open. + + Generally instances of this are assigned as a class member of some + UI class, which will then keep the UI informed upon its death. + + It is valid to have multiple states for one tag; the UI will keep a + tally. + """ + + __slots__ = ['stateid'] + + def __init__(self, stateid: str) -> None: + self.stateid = stateid + _bauiv1.ui_open_state_change(self.stateid, 1) + + def __del__(self) -> None: + _bauiv1.ui_open_state_change(self.stateid, -1) diff --git a/dist/ba_data/python/bauiv1/_window.py b/dist/ba_data/python/bauiv1/_window.py index 7c65a90..0827777 100644 --- a/dist/ba_data/python/bauiv1/_window.py +++ b/dist/ba_data/python/bauiv1/_window.py @@ -100,6 +100,8 @@ class MainWindow(Window): # old ones as back targets. self.main_window_is_auxiliary: bool = False + self.main_window_extra_type_id = '' + self._main_window_transition = transition self._main_window_origin_widget = origin_widget super().__init__( @@ -348,6 +350,7 @@ class MainWindow(Window): assert back_state.is_top_level is not None assert back_state.is_auxiliary is not None assert back_state.window_type is not None + assert back_state.extra_type_id is not None # When leaving an auxiliary window, scale the destination # window in instead of sliding to convey that its more of a @@ -364,6 +367,7 @@ class MainWindow(Window): is_back=True, back_state=back_state, suppress_warning=True, + extra_type_id=back_state.extra_type_id, ) def main_window_replace( @@ -371,6 +375,7 @@ class MainWindow(Window): new_window: MainWindow | Callable[[], MainWindow], back_state: MainWindowState | None = None, is_auxiliary: bool = False, + extra_type_id: str = '', ) -> MainWindow | None: """Replace ourself with a new MainWindow. @@ -449,6 +454,7 @@ class MainWindow(Window): from_window=self, back_state=back_state, is_auxiliary=is_auxiliary, + extra_type_id=extra_type_id, suppress_warning=True, ) return new_window @@ -542,6 +548,7 @@ class MainWindowState: self.is_top_level: bool | None = None self.is_auxiliary: bool | None = None self.window_type: type[MainWindow] | None = None + self.extra_type_id: str | None = None def create_window( self, @@ -572,10 +579,15 @@ class BasicMainWindowState(MainWindowState): ], bauiv1.MainWindow, ], + uiopenstate: bauiv1.UIOpenState | None = None, ) -> None: super().__init__() self.create_call = create_call + # We simply need to hold on to this to keep the ui-open-state + # alive. + self.uiopenstate = uiopenstate + @override def create_window( self, diff --git a/dist/ba_data/python/bauiv1/onscreenkeyboard.py b/dist/ba_data/python/bauiv1/onscreenkeyboard.py index c9f775c..bbb3018 100644 --- a/dist/ba_data/python/bauiv1/onscreenkeyboard.py +++ b/dist/ba_data/python/bauiv1/onscreenkeyboard.py @@ -245,7 +245,9 @@ class OnScreenKeyboardWindow(Window): textcolor=key_textcolor, color=key_color_dark, label=babase.Lstr(resource='spaceKeyText'), - on_activate_call=babase.Call(self._type_char, ' '), + on_activate_call=babase.CallStrict( + self._type_char, ' ' + ), ) # Show change instructions only if we have more than one @@ -359,7 +361,7 @@ class OnScreenKeyboardWindow(Window): _bauiv1.buttonwidget( edit=btn, label=chars[i] if have_char else ' ', - on_activate_call=babase.Call( + on_activate_call=babase.CallStrict( self._type_char, chars[i] if have_char else ' ' ), ) diff --git a/dist/ba_data/python/bauiv1lib/account/settings.py b/dist/ba_data/python/bauiv1lib/account/settings.py index 900072c..ba3dae7 100644 --- a/dist/ba_data/python/bauiv1lib/account/settings.py +++ b/dist/ba_data/python/bauiv1lib/account/settings.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides UI for account functionality.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -33,6 +34,8 @@ class AccountSettingsWindow(bui.MainWindow): plus = bui.app.plus assert plus is not None + self._uiopenstate = bui.UIOpenState('accountsettings') + self._sign_in_v2_proxy_button: bui.Widget | None = None self._sign_in_device_button: bui.Widget | None = None @@ -49,7 +52,7 @@ class AccountSettingsWindow(bui.MainWindow): self._v1_signed_in = plus.get_v1_account_state() == 'signed_in' self._v1_account_state_num = plus.get_v1_account_state_num() self._check_sign_in_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._can_reset_achievements = False @@ -863,7 +866,9 @@ class AccountSettingsWindow(bui.MainWindow): color=(0.55, 0.5, 0.6), icon=bui.gettexture('settingsIcon'), textcolor=(0.75, 0.7, 0.8), - on_activate_call=bui.WeakCall(self._on_manage_account_press), + on_activate_call=bui.WeakCallStrict( + self._on_manage_account_press + ), ) if first_selectable is None: first_selectable = btn @@ -884,7 +889,9 @@ class AccountSettingsWindow(bui.MainWindow): label=bui.Lstr(resource=f'{self._r}.createAnAccountText'), color=(0.55, 0.5, 0.6), textcolor=(0.75, 0.7, 0.8), - on_activate_call=bui.WeakCall(self._on_create_account_press), + on_activate_call=bui.WeakCallStrict( + self._on_create_account_press + ), ) if first_selectable is None: first_selectable = btn @@ -1100,7 +1107,9 @@ class AccountSettingsWindow(bui.MainWindow): if bui.app.plus is not None: bui.apptimer( 0.15, - bui.Call(bui.app.plus.show_game_service_ui, 'achievements'), + bui.CallStrict( + bui.app.plus.show_game_service_ui, 'achievements' + ), ) else: logging.warning('show_game_service_ui requires plus feature-set.') @@ -1138,7 +1147,9 @@ class AccountSettingsWindow(bui.MainWindow): with plus.accounts.primary: plus.cloud.send_message_cb( bacommon.cloud.ManageAccountMessage(weblocation=weblocation), - on_response=bui.WeakCall(self._on_manage_account_response), + on_response=bui.WeakCallPartial( + self._on_manage_account_response + ), ) def _on_manage_account_response( @@ -1158,7 +1169,9 @@ class AccountSettingsWindow(bui.MainWindow): if bui.app.plus is not None: bui.apptimer( 0.15, - bui.Call(bui.app.plus.show_game_service_ui, 'leaderboards'), + bui.CallStrict( + bui.app.plus.show_game_service_ui, 'leaderboards' + ), ) else: logging.warning('show_game_service_ui requires classic') @@ -1245,7 +1258,7 @@ class AccountSettingsWindow(bui.MainWindow): self._needs_refresh = True # Speed UI updates along. - bui.apptimer(0.1, bui.WeakCall(self._update)) + bui.apptimer(0.1, bui.WeakCallStrict(self._update)) def _sign_out_press(self) -> None: plus = bui.app.plus @@ -1273,7 +1286,7 @@ class AccountSettingsWindow(bui.MainWindow): ) # Speed UI updates along. - bui.apptimer(0.1, bui.WeakCall(self._update)) + bui.apptimer(0.1, bui.WeakCallStrict(self._update)) def _sign_in_press(self, login_type: str | LoginType) -> None: @@ -1305,7 +1318,7 @@ class AccountSettingsWindow(bui.MainWindow): cfg['Auto Account State'] = login_type cfg.commit() self._needs_refresh = True - bui.apptimer(0.1, bui.WeakCall(self._update)) + bui.apptimer(0.1, bui.WeakCallStrict(self._update)) return # V2 login sign-in buttons generally go through adapters. @@ -1313,12 +1326,12 @@ class AccountSettingsWindow(bui.MainWindow): if adapter is not None: self._signing_in_adapter = adapter adapter.sign_in( - result_cb=bui.WeakCall(self._on_adapter_sign_in_result), + result_cb=bui.WeakCallPartial(self._on_adapter_sign_in_result), description='account settings button', ) # Will get 'Signing in...' to show. self._needs_refresh = True - bui.apptimer(0.1, bui.WeakCall(self._update)) + bui.apptimer(0.1, bui.WeakCallStrict(self._update)) else: bui.screenmessage(f'Unsupported login_type: {login_type.name}') @@ -1365,7 +1378,7 @@ class AccountSettingsWindow(bui.MainWindow): # credentials go through and the account name shows up. bui.apptimer( 1.5, - bui.Call( + bui.CallStrict( bui.screenmessage, bui.Lstr( resource=self._r @@ -1376,7 +1389,7 @@ class AccountSettingsWindow(bui.MainWindow): # Speed any UI updates along. self._needs_refresh = True - bui.apptimer(0.1, bui.WeakCall(self._update)) + bui.apptimer(0.1, bui.WeakCallStrict(self._update)) def _v2_proxy_sign_in_press(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/account/signin.py b/dist/ba_data/python/bauiv1lib/account/signin.py index 4cdf885..eaddc8a 100644 --- a/dist/ba_data/python/bauiv1lib/account/signin.py +++ b/dist/ba_data/python/bauiv1lib/account/signin.py @@ -7,7 +7,7 @@ from __future__ import annotations import bauiv1 as bui -def show_sign_in_prompt() -> None: +def show_sign_in_prompt(origin_widget: bui.Widget | None = None) -> None: """Bring up a prompt telling the user they must sign in.""" from bauiv1lib.confirm import ConfirmWindow @@ -17,6 +17,7 @@ def show_sign_in_prompt() -> None: ok_text=bui.Lstr(resource='accountSettingsWindow.signInText'), width=460, height=130, + origin_widget=origin_widget, ) @@ -47,6 +48,7 @@ def _show_account_settings() -> None: from_window=False, # Don't check where we're coming from. is_auxiliary=True, suppress_warning=True, + extra_type_id='', ) # Transition out any previous main window. diff --git a/dist/ba_data/python/bauiv1lib/account/v2proxy.py b/dist/ba_data/python/bauiv1lib/account/v2proxy.py index 2ddf981..81b25f5 100644 --- a/dist/ba_data/python/bauiv1lib/account/v2proxy.py +++ b/dist/ba_data/python/bauiv1lib/account/v2proxy.py @@ -103,9 +103,9 @@ class V2ProxySignInWindow(bui.Window): self._connection_wait_timeout_time = time.monotonic() + 10.0 self._update_timer = bui.AppTimer( - 0.371, bui.WeakCall(self._update), repeat=True + 0.371, bui.WeakCallStrict(self._update), repeat=True ) - bui.pushcall(bui.WeakCall(self._update)) + bui.pushcall(bui.WeakCallStrict(self._update)) def _update(self) -> None: @@ -135,7 +135,7 @@ class V2ProxySignInWindow(bui.Window): plus.cloud.send_message_cb( bacommon.cloud.LoginProxyRequestMessage(), - on_response=bui.WeakCall(self._on_proxy_request_response), + on_response=bui.WeakCallPartial(self._on_proxy_request_response), ) self._message_in_flight = True @@ -221,7 +221,8 @@ class V2ProxySignInWindow(bui.Window): self._proxyid = response.proxyid self._proxykey = response.proxykey bui.apptimer( - STATUS_CHECK_INTERVAL_SECONDS, bui.WeakCall(self._ask_for_status) + STATUS_CHECK_INTERVAL_SECONDS, + bui.WeakCallStrict(self._ask_for_status), ) def _show_overlay_sign_in_ui( @@ -282,7 +283,9 @@ class V2ProxySignInWindow(bui.Window): h_align='center', v_align='center', autoselect=True, - on_activate_call=bui.Call(self._copy_link, address_pretty), + on_activate_call=bui.CallStrict( + self._copy_link, address_pretty + ), selectable=True, ) qroffs = 20.0 @@ -306,7 +309,7 @@ class V2ProxySignInWindow(bui.Window): bacommon.cloud.LoginProxyStateQueryMessage( proxyid=self._proxyid, proxykey=self._proxykey ), - on_response=bui.WeakCall(self._got_status), + on_response=bui.WeakCallPartial(self._got_status), ) def _got_status( @@ -340,7 +343,9 @@ class V2ProxySignInWindow(bui.Window): bacommon.cloud.LoginProxyCompleteMessage( proxyid=self._proxyid ), - on_response=bui.WeakCall(self._proxy_complete_response), + on_response=bui.WeakCallPartial( + self._proxy_complete_response + ), ) except CommunicationError: pass @@ -360,7 +365,7 @@ class V2ProxySignInWindow(bui.Window): ): bui.apptimer( STATUS_CHECK_INTERVAL_SECONDS, - bui.WeakCall(self._ask_for_status), + bui.WeakCallStrict(self._ask_for_status), ) def _proxy_complete_response(self, response: None | Exception) -> None: diff --git a/dist/ba_data/python/bauiv1lib/account/viewer.py b/dist/ba_data/python/bauiv1lib/account/viewer.py index 2bf33d7..3e3faec 100644 --- a/dist/ba_data/python/bauiv1lib/account/viewer.py +++ b/dist/ba_data/python/bauiv1lib/account/viewer.py @@ -148,7 +148,7 @@ class AccountViewerWindow(PopupWindow): 'accountID': self._account_id, 'profileID': self._profile_id, }, - callback=bui.WeakCall(self._on_query_response), + callback=bui.WeakCallPartial(self._on_query_response), ) def popup_menu_selected_choice( diff --git a/dist/ba_data/python/bauiv1lib/achievements.py b/dist/ba_data/python/bauiv1lib/achievements.py index 3272a4f..c949aff 100644 --- a/dist/ba_data/python/bauiv1lib/achievements.py +++ b/dist/ba_data/python/bauiv1lib/achievements.py @@ -30,6 +30,8 @@ class AchievementsWindow(bui.MainWindow): assert bui.app.classic is not None uiscale = bui.app.ui_v1.uiscale + self._uiopenstate = bui.UIOpenState('classicachievements') + self._width = 800 if uiscale is bui.UIScale.SMALL else 550 self._height = ( 450 diff --git a/dist/ba_data/python/bauiv1lib/appinvite.py b/dist/ba_data/python/bauiv1lib/appinvite.py index a4f503d..7f3c050 100644 --- a/dist/ba_data/python/bauiv1lib/appinvite.py +++ b/dist/ba_data/python/bauiv1lib/appinvite.py @@ -150,7 +150,7 @@ class ShowFriendCodeWindow(bui.Window): position=(self._width * 0.5 - 100 + xoffs, 39), autoselect=True, label=bui.Lstr(resource='gatherWindow.emailItText'), - on_activate_call=bui.WeakCall(self._email), + on_activate_call=bui.WeakCallStrict(self._email), ) def _email(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/characterpicker.py b/dist/ba_data/python/bauiv1lib/characterpicker.py index 835f3f0..f9ecc8c 100644 --- a/dist/ba_data/python/bauiv1lib/characterpicker.py +++ b/dist/ba_data/python/bauiv1lib/characterpicker.py @@ -147,7 +147,7 @@ class CharacterPicker(PopupWindow): color=(1, 1, 1), tint_color=tint_color, tint2_color=tint2_color, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._select_character, self._spazzes[index] ), position=pos, @@ -198,8 +198,9 @@ class CharacterPicker(PopupWindow): plus = bui.app.plus assert plus is not None - if plus.get_v1_account_state() != 'signed_in': + if plus.accounts.primary is None: show_sign_in_prompt() + self._transition_out() return if self._delegate is not None: diff --git a/dist/ba_data/python/bauiv1lib/chest.py b/dist/ba_data/python/bauiv1lib/chest.py index 047207d..de42593 100644 --- a/dist/ba_data/python/bauiv1lib/chest.py +++ b/dist/ba_data/python/bauiv1lib/chest.py @@ -10,7 +10,8 @@ import random from typing import override, TYPE_CHECKING from efro.util import strict_partial -import bacommon.bs +import bacommon.classic +import bacommon.displayitem as ditm import bauiv1 as bui if TYPE_CHECKING: @@ -38,6 +39,8 @@ class ChestWindow(bui.MainWindow): # pylint: disable=too-many-statements self._index = index + self._uiopenstate = bui.UIOpenState(f'classicchest{index}') + # Get this loading before we need it. self._quote_bubble_tex = bui.gettexture('quoteBubble') @@ -56,7 +59,9 @@ class ChestWindow(bui.MainWindow): self._time_string_timer: bui.AppTimer | None = None self._time_string_text: bui.Widget | None = None self._open_me_flash_timer: bui.AppTimer | None = None - self._prizesets: list[bacommon.bs.ChestInfoResponse.Chest.PrizeSet] = [] + self._prizesets: list[ + bacommon.classic.ChestInfoResponse.Chest.PrizeSet + ] = [] self._prizeindex = -1 self._prizesettxts: dict[int, list[bui.Widget]] = {} self._prizesetimgs: dict[int, list[bui.Widget]] = {} @@ -199,8 +204,8 @@ class ChestWindow(bui.MainWindow): self._action_in_flight = True with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.ChestInfoMessage(chest_id=str(self._index)), - on_response=bui.WeakCall(self._on_chest_info_response), + bacommon.classic.ChestInfoMessage(chest_id=str(self._index)), + on_response=bui.WeakCallPartial(self._on_chest_info_response), ) @override @@ -222,7 +227,7 @@ class ChestWindow(bui.MainWindow): def main_window_should_preserve_selection(self) -> bool: # This doesn't really benefit us since we do lots of widget # creates/destroys throughout our lifetime and also we're an - # auxliary window so should never need to restore toolbar + # auxiliary window so should never need to restore toolbar # selections. return False @@ -241,7 +246,7 @@ class ChestWindow(bui.MainWindow): bui.textwidget(edit=self._time_string_text, text=tstr) def _on_chest_info_response( - self, response: bacommon.bs.ChestInfoResponse | Exception + self, response: bacommon.classic.ChestInfoResponse | Exception ) -> None: assert self._action_in_flight # Should be us. self._action_in_flight = False @@ -261,7 +266,7 @@ class ChestWindow(bui.MainWindow): self._show_chest_actions(response.user_tokens, response.chest) def _on_chest_action_response( - self, response: bacommon.bs.ChestActionResponse | Exception + self, response: bacommon.cloud.ChestActionResponse | Exception ) -> None: assert self._action_in_flight # Should be us. self._action_in_flight = False @@ -296,7 +301,7 @@ class ChestWindow(bui.MainWindow): bui.app.classic.run_bs_client_effects(response.effects, delay=toffs) def _show_chest_actions( - self, user_tokens: int, chest: bacommon.bs.ChestInfoResponse.Chest + self, user_tokens: int, chest: bacommon.classic.ChestInfoResponse.Chest ) -> None: """Show state for our chest.""" # pylint: disable=too-many-statements @@ -342,11 +347,7 @@ class ChestWindow(bui.MainWindow): tint2_color=self._chestdisplayinfo.tint2, ) - # Store the prize-sets so we can display odds/etc. Sort them - # with smallest weights first (higher visually == better). - # self._prizesets = sorted( - # chest.prizesets, key=lambda s: s.weight, reverse=True - # ) + # Store the prize-sets so we can display odds/etc. self._prizesets = chest.prizesets if chest.unlock_tokens > 0: @@ -391,7 +392,9 @@ class ChestWindow(bui.MainWindow): self._time_string_timer = bui.AppTimer( 1.0, repeat=True, - call=bui.WeakCall(self._update_time_display, chest.unlock_time), + call=bui.WeakCallStrict( + self._update_time_display, chest.unlock_time + ), ) # Allow watching an ad IF the server tells us we can AND we have @@ -418,7 +421,7 @@ class ChestWindow(bui.MainWindow): label='', button_type='square', autoselect=True, - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._open_press, user_tokens, chest.unlock_tokens ), enable_sound=False, @@ -465,38 +468,41 @@ class ChestWindow(bui.MainWindow): v_align='center', ) ) - self._open_now_images.append( - bui.imagewidget( - parent=self._root_widget, - size=(iconsize, iconsize), - position=( - self._width * 0.5 - iconsize * 0.5 + boffsx, - self._yoffs + bposy + bheight * 0.35, - ), - draw_controller=self._open_now_button, - texture=bui.gettexture('coin'), + if bool(False): + pass + else: + self._open_now_images.append( + bui.imagewidget( + parent=self._root_widget, + size=(iconsize, iconsize), + position=( + self._width * 0.5 - iconsize * 0.5 + boffsx, + self._yoffs + bposy + bheight * 0.35, + ), + draw_controller=self._open_now_button, + texture=bui.gettexture('coin'), + ) ) - ) - self._open_now_texts.append( - bui.textwidget( - parent=self._root_widget, - text=bui.Lstr( - resource='tokens.numTokensText', - subs=[('${COUNT}', str(chest.unlock_tokens))], - ), - position=( - self._width * 0.5 + boffsx, - self._yoffs + bposy + bheight * 0.25, - ), - scale=0.65, - color=(0, 1, 0), - draw_controller=self._open_now_button, - maxwidth=bwidth * 0.8, - size=(0, 0), - h_align='center', - v_align='center', + self._open_now_texts.append( + bui.textwidget( + parent=self._root_widget, + text=bui.Lstr( + resource='tokens.numTokensText', + subs=[('${COUNT}', str(chest.unlock_tokens))], + ), + position=( + self._width * 0.5 + boffsx, + self._yoffs + bposy + bheight * 0.25, + ), + scale=0.65, + color=(0, 1, 0), + draw_controller=self._open_now_button, + maxwidth=bwidth * 0.8, + size=(0, 0), + h_align='center', + v_align='center', + ) ) - ) self._open_now_spinner = bui.spinnerwidget( parent=self._root_widget, position=( @@ -531,7 +537,7 @@ class ChestWindow(bui.MainWindow): label='', button_type='square', autoselect=True, - on_activate_call=bui.WeakCall(self._watch_ad_press), + on_activate_call=bui.WeakCallStrict(self._watch_ad_press), enable_sound=False, ) bui.imagewidget( @@ -595,7 +601,7 @@ class ChestWindow(bui.MainWindow): self._open_me_flash_timer = bui.AppTimer( 0.05, repeat=True, - call=bui.WeakCall(self._open_me_backing_update), + call=bui.WeakCallStrict(self._open_me_backing_update), ) self._open_me_widgets.clear() self._open_me_widgets.append(self._open_me_backing) @@ -608,7 +614,6 @@ class ChestWindow(bui.MainWindow): value='*${A}', subs=[('${A}', bui.Lstr(resource='openMeText'))], ), - # text=bui.Lstr(resource='openMeText'), maxwidth=175, scale=0.7, color=(0, 1.0, 0.7, 1), @@ -644,7 +649,9 @@ class ChestWindow(bui.MainWindow): color=(0.0, 0.8, 0.5), autoselect=True, text_flatness=1.0, - on_activate_call=bui.WeakCall(self._stop_showing_open_me_press), + on_activate_call=bui.WeakCallStrict( + self._stop_showing_open_me_press + ), ) # Avoid depth issues with the quote-bubble image. bui.widget(edit=btn, depth_range=(0.1, 1.0)) @@ -794,10 +801,13 @@ class ChestWindow(bui.MainWindow): for item in p.contents: x += 5.0 - if isinstance(item.item, bacommon.bs.TicketsDisplayItem): + if isinstance(item.item, ditm.Tickets): _mktxt(str(item.item.count)) _mkicon('tickets') - elif isinstance(item.item, bacommon.bs.TokensDisplayItem): + elif isinstance(item.item, ditm.PurpleTickets): + _mktxt(str(item.item.count)) + _mkicon('ticketsPurple') + elif isinstance(item.item, ditm.Tokens): _mktxt(str(item.item.count)) _mkicon('coin') else: @@ -807,7 +817,7 @@ class ChestWindow(bui.MainWindow): descfin = bui.Lstr( translate=('serverResponses', item.description) ).evaluate() - subs = ( + subs: list[str] = ( [] if item.description_subs is None else item.description_subs @@ -845,7 +855,7 @@ class ChestWindow(bui.MainWindow): # Hack: We disable normal swish for the open button and it # seems weird without a swish here, so explicitly do one. bui.getsound('swish').play() - show_get_tokens_prompt() + show_get_tokens_prompt(origin_widget=self._open_now_button) return self._action_in_flight = True @@ -857,12 +867,12 @@ class ChestWindow(bui.MainWindow): with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.ChestActionMessage( + bacommon.cloud.ChestActionMessage( chest_id=str(self._index), - action=bacommon.bs.ChestActionMessage.Action.UNLOCK, + action=bacommon.cloud.ChestActionMessage.Action.UNLOCK, token_payment=token_payment, ), - on_response=bui.WeakCall(self._on_chest_action_response), + on_response=bui.WeakCallPartial(self._on_chest_action_response), ) # Convey that something is in progress. @@ -898,7 +908,7 @@ class ChestWindow(bui.MainWindow): self._action_in_flight = True bui.app.plus.ads.show_ad_2( 'reduce_chest_wait', - on_completion_call=bui.WeakCall(self._watch_ad_complete), + on_completion_call=bui.WeakCallPartial(self._watch_ad_complete), ) # Convey that something is in progress. @@ -937,12 +947,12 @@ class ChestWindow(bui.MainWindow): with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.ChestActionMessage( + bacommon.cloud.ChestActionMessage( chest_id=str(self._index), - action=bacommon.bs.ChestActionMessage.Action.AD, + action=bacommon.cloud.ChestActionMessage.Action.AD, token_payment=0, ), - on_response=bui.WeakCall(self._on_chest_action_response), + on_response=bui.WeakCallPartial(self._on_chest_action_response), ) def _reset(self) -> None: @@ -972,9 +982,14 @@ class ChestWindow(bui.MainWindow): text=bui.Lstr(resource='chests.slotDescriptionText'), color=(1, 1, 1), ) + # This is somewhat redundant with the close button, but we need + # to have *something* selectable in our window for SMALL ui-mode + # (when we don't have our own close button) otherwise we can be + # left unable to select anything. + self._show_done_button(use_ok_label=True) def _show_chest_contents( - self, response: bacommon.bs.ChestActionResponse + self, response: bacommon.cloud.ChestActionResponse ) -> float: # pylint: disable=too-many-locals # pylint: disable=too-many-statements @@ -989,11 +1004,7 @@ class ChestWindow(bui.MainWindow): # Insert test items for testing. if bool(False): - response.contents += [ - bacommon.bs.DisplayItemWrapper.for_display_item( - bacommon.bs.TestDisplayItem() - ) - ] + response.contents += [ditm.Wrapper.for_item(ditm.Test())] tincr = 0.4 tendoffs = tincr * 4.0 @@ -1035,7 +1046,7 @@ class ChestWindow(bui.MainWindow): sign = -sign bui.apptimer( toffs, - bui.Call( + bui.CallStrict( _set_img, x=( 20.0 @@ -1082,7 +1093,7 @@ class ChestWindow(bui.MainWindow): ) toffsopen = toffs - bui.apptimer(toffs, bui.WeakCall(self._show_chest_opening)) + bui.apptimer(toffs, bui.WeakCallStrict(self._show_chest_opening)) toffs += tincr * 1.0 width = xspacing * 0.95 @@ -1102,11 +1113,12 @@ class ChestWindow(bui.MainWindow): self._yoffs - 250.0, ), width=width, + debug=False, ), ) xoffs += xspacing toffs += tincr - bui.apptimer(toffs, bui.WeakCall(self._show_done_button)) + bui.apptimer(toffs, bui.WeakCallStrict(self._show_done_button)) self._show_odds(initial_highlighted_row=-1) @@ -1126,7 +1138,7 @@ class ChestWindow(bui.MainWindow): while toffs2 > 0.0: bui.apptimer( toffs2, - bui.WeakCall(self._highlight_odds_row, i), + bui.WeakCallStrict(self._highlight_odds_row, i), ) toffs2 -= amt if ease_out: @@ -1184,7 +1196,7 @@ class ChestWindow(bui.MainWindow): # comes to rest before scale. bui.apptimer( toffs, - bui.Call( + bui.CallStrict( _set_img, x=( 1.0 @@ -1204,7 +1216,7 @@ class ChestWindow(bui.MainWindow): initial_highlighted_extra=True, ) - def _show_done_button(self) -> None: + def _show_done_button(self, use_ok_label: bool = False) -> None: # No-op if our ui is dead. if not self._root_widget: return @@ -1219,33 +1231,10 @@ class ChestWindow(bui.MainWindow): self._yoffs - 350, ), size=(bwidth, bheight), - label=bui.Lstr(resource='doneText'), + label=bui.Lstr(resource='okText' if use_ok_label else 'doneText'), autoselect=True, on_activate_call=self.main_window_back, ) bui.containerwidget( edit=self._root_widget, selected_child=btn, start_button=btn ) - - -# Slight hack: we define window different classes for our different -# chest slots so that the default UI behavior is to replace each other -# when different ones are pressed. If they are all the same window class -# then the default behavior for such presses is to toggle the existing -# one back off. - - -class ChestWindow0(ChestWindow): - """Child class of ChestWindow for slighty hackish reasons.""" - - -class ChestWindow1(ChestWindow): - """Child class of ChestWindow for slighty hackish reasons.""" - - -class ChestWindow2(ChestWindow): - """Child class of ChestWindow for slighty hackish reasons.""" - - -class ChestWindow3(ChestWindow): - """Child class of ChestWindow for slighty hackish reasons.""" diff --git a/dist/ba_data/python/bauiv1lib/colorpicker.py b/dist/ba_data/python/bauiv1lib/colorpicker.py index 476e059..b557def 100644 --- a/dist/ba_data/python/bauiv1lib/colorpicker.py +++ b/dist/ba_data/python/bauiv1lib/colorpicker.py @@ -12,8 +12,6 @@ import bauiv1 as bui if TYPE_CHECKING: from typing import Any, Sequence -REQUIRE_PRO = False - class ColorPicker(PopupWindow): """A popup UI to select from a set of colors. @@ -87,7 +85,7 @@ class ColorPicker(PopupWindow): size=(35, 40), label='', button_type='square', - on_activate_call=bui.WeakCall(self._select, x, y), + on_activate_call=bui.WeakCallStrict(self._select, x, y), autoselect=True, color=color, extra_touch_border_scale=0.0, @@ -105,19 +103,9 @@ class ColorPicker(PopupWindow): fallback_resource='coopSelectWindow.customText', ), autoselect=True, - on_activate_call=bui.WeakCall(self._select_other), + on_activate_call=bui.WeakCallStrict(self._select_other), ) - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro(): - bui.imagewidget( - parent=self.root_widget, - position=(50, 12), - size=(30, 30), - texture=bui.gettexture('lock'), - draw_controller=other_button, - ) - # If their color is close to one of our swatches, select it. # Otherwise select 'other'. if closest_dist < 0.03: @@ -135,14 +123,6 @@ class ColorPicker(PopupWindow): return self._tag def _select_other(self) -> None: - from bauiv1lib import purchase - - # Requires pro. - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro(): - purchase.PurchaseWindow(items=['pro']) - self._transition_out() - return ColorPickerExact( parent=self._parent, position=self._position, @@ -282,7 +262,7 @@ class ColorPickerExact(PopupWindow): label=b_label, autoselect=True, enable_sound=False, - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._color_change_press, color_name, binc ), ) @@ -296,7 +276,7 @@ class ColorPickerExact(PopupWindow): color=(0.6, 0.6, 0.6), textcolor=(0.7, 0.7, 0.7), label=bui.Lstr(resource='doneText'), - on_activate_call=bui.WeakCall(self._transition_out), + on_activate_call=bui.WeakCallStrict(self._transition_out), autoselect=True, ) bui.containerwidget(edit=self.root_widget, start_button=btn) diff --git a/dist/ba_data/python/bauiv1lib/config.py b/dist/ba_data/python/bauiv1lib/config.py index cd28fba..3dde744 100644 --- a/dist/ba_data/python/bauiv1lib/config.py +++ b/dist/ba_data/python/bauiv1lib/config.py @@ -152,7 +152,7 @@ class ConfigNumberEdit: size=(28, 28), label='-', autoselect=True, - on_activate_call=bui.Call(self._down), + on_activate_call=bui.CallStrict(self._down), repeat=True, enable_sound=changesound, ) @@ -163,7 +163,7 @@ class ConfigNumberEdit: size=(28, 28), label='+', autoselect=True, - on_activate_call=bui.Call(self._up), + on_activate_call=bui.CallStrict(self._up), repeat=True, enable_sound=changesound, ) diff --git a/dist/ba_data/python/bauiv1lib/connect.py b/dist/ba_data/python/bauiv1lib/connect.py index 099d698..695e7a1 100644 --- a/dist/ba_data/python/bauiv1lib/connect.py +++ b/dist/ba_data/python/bauiv1lib/connect.py @@ -74,7 +74,7 @@ class ConnectWindow(bui.Window): ) bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button) self._update_timer = bui.AppTimer( - 0.113, bui.WeakCall(self._update), repeat=True + 0.113, bui.WeakCallStrict(self._update), repeat=True ) def _update(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/connectivity.py b/dist/ba_data/python/bauiv1lib/connectivity.py index 4b801d5..a48a702 100644 --- a/dist/ba_data/python/bauiv1lib/connectivity.py +++ b/dist/ba_data/python/bauiv1lib/connectivity.py @@ -100,7 +100,7 @@ class WaitForConnectivityWindow(bui.Window): ) bui.containerwidget(edit=self._root_widget, cancel_button=cancel_button) self._update_timer = bui.AppTimer( - 0.113, bui.WeakCall(self._update), repeat=True + 0.113, bui.WeakCallStrict(self._update), repeat=True ) def _update(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/coop/browser.py b/dist/ba_data/python/bauiv1lib/coop/browser.py index 5ebfe91..1acaac0 100644 --- a/dist/ba_data/python/bauiv1lib/coop/browser.py +++ b/dist/ba_data/python/bauiv1lib/coop/browser.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """UI for browsing available co-op levels/games/etc.""" + # FIXME: Break this up. # pylint: disable=too-many-lines @@ -9,9 +10,11 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING, override - +from bacommon.analytics import ClassicAnalyticsEvent import bauiv1 as bui + from bauiv1lib.utils import scroll_fade_top, scroll_fade_bottom +from bauiv1lib.connectivity import wait_for_connectivity if TYPE_CHECKING: from typing import Any @@ -59,8 +62,8 @@ class CoopBrowserWindow(bui.MainWindow): ), ) - # Try to recreate the same number of buttons we had last time so our - # re-selection code works. + # Try to recreate the same number of buttons we had last time so + # our re-selection code works. self._tournament_button_count = app.config.get('Tournament Rows', 0) assert isinstance(self._tournament_button_count, int) @@ -256,7 +259,8 @@ class CoopBrowserWindow(bui.MainWindow): self._subcontainer: bui.Widget | None = None - # Take note of our account state; we'll refresh later if this changes. + # Take note of our account state; we'll refresh later if this + # changes. self._account_state_num = plus.get_v1_account_state_num() # Same for fg/bg state. @@ -264,14 +268,14 @@ class CoopBrowserWindow(bui.MainWindow): self._refresh() - # Even though we might display cached tournament data immediately, we - # don't consider it valid until we've pinged. + # Even though we might display cached tournament data + # immediately, we don't consider it valid until we've pinged. # the server for an update self._tourney_data_up_to_date = False - # If we've got a cached tournament list for our account and info for - # each one of those tournaments, go ahead and display it as a - # starting point. + # If we've got a cached tournament list for our account and info + # for each one of those tournaments, go ahead and display it as + # a starting point. if ( classic.accounts.account_tournament_list is not None and classic.accounts.account_tournament_list[0] @@ -289,7 +293,7 @@ class CoopBrowserWindow(bui.MainWindow): # This will pull new data periodically, update timers, etc. self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() @@ -315,17 +319,15 @@ class CoopBrowserWindow(bui.MainWindow): def _preload_modules() -> None: """Preload modules we use; avoids hitches (called in bg thread).""" # pylint: disable=cyclic-import - import bauiv1lib.purchase as _unused1 - import bauiv1lib.coop.gamebutton as _unused2 - import bauiv1lib.confirm as _unused3 - import bauiv1lib.account as _unused4 - import bauiv1lib.league.rankwindow as _unused5 - import bauiv1lib.store.browser as _unused6 - import bauiv1lib.account.viewer as _unused7 - import bauiv1lib.tournamentscores as _unused8 - import bauiv1lib.tournamententry as _unused9 - import bauiv1lib.play as _unused10 - import bauiv1lib.coop.tournamentbutton as _unused11 + import bauiv1lib.coop.gamebutton as _unused1 + import bauiv1lib.confirm as _unused2 + import bauiv1lib.account as _unused3 + import bauiv1lib.league.rankwindow as _unused4 + import bauiv1lib.account.viewer as _unused5 + import bauiv1lib.tournamentscores as _unused6 + import bauiv1lib.tournamententry as _unused7 + import bauiv1lib.play as _unused8 + import bauiv1lib.coop.tournamentbutton as _unused9 def _update(self) -> None: plus = bui.app.plus @@ -356,8 +358,8 @@ class CoopBrowserWindow(bui.MainWindow): self._save_state() self._refresh() - # Also encourage a new tournament query since this will clear out - # our current results. + # Also encourage a new tournament query since this will + # clear out our current results. if not self._doing_tournament_query: self._last_tournament_query_time = None @@ -382,7 +384,9 @@ class CoopBrowserWindow(bui.MainWindow): self._doing_tournament_query = True plus.tournament_query( args={'source': 'coop window refresh', 'numScores': 1}, - callback=bui.WeakCall(self._on_tournament_query_response), + callback=bui.WeakCallPartial( + self._on_tournament_query_response + ), ) # Decrement time on our tournament buttons. @@ -457,7 +461,8 @@ class CoopBrowserWindow(bui.MainWindow): assert bui.app.classic is not None accounts = bui.app.classic.accounts if data is not None: - tournament_data = data['t'] # This used to be the whole payload. + # This used to be the whole payload. + tournament_data = data['t'] self._last_tournament_query_response_time = bui.apptime() else: tournament_data = None @@ -467,7 +472,8 @@ class CoopBrowserWindow(bui.MainWindow): self._tourney_data_up_to_date = True accounts.cache_tournament_info(tournament_data) - # Also cache the current tourney list/order for this account. + # Also cache the current tourney list/order for this + # account. accounts.account_tournament_list = ( plus.get_v1_account_state_num(), [e['tournamentID'] for e in tournament_data], @@ -477,21 +483,11 @@ class CoopBrowserWindow(bui.MainWindow): self._update_for_data(tournament_data) def _set_campaign_difficulty(self, difficulty: str) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow - plus = bui.app.plus assert plus is not None assert bui.app.classic is not None if difficulty != self._campaign_difficulty: - if ( - difficulty == 'hard' - and HARD_REQUIRES_PRO - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return bui.getsound('gunCocking').play() if difficulty not in ('easy', 'hard'): print('ERROR: invalid campaign difficulty:', difficulty) @@ -539,8 +535,12 @@ class CoopBrowserWindow(bui.MainWindow): button_type='square', autoselect=True, enable_sound=False, - on_activate_call=bui.Call(self._set_campaign_difficulty, 'easy'), - on_select_call=bui.Call(self.sel_change, 'campaign', 'easyButton'), + on_activate_call=bui.CallStrict( + self._set_campaign_difficulty, 'easy' + ), + on_select_call=bui.CallStrict( + self.sel_change, 'campaign', 'easyButton' + ), color=( sel_color if self._campaign_difficulty == 'easy' @@ -570,8 +570,12 @@ class CoopBrowserWindow(bui.MainWindow): button_type='square', autoselect=True, enable_sound=False, - on_activate_call=bui.Call(self._set_campaign_difficulty, 'hard'), - on_select_call=bui.Call(self.sel_change, 'campaign', 'hardButton'), + on_activate_call=bui.CallStrict( + self._set_campaign_difficulty, 'hard' + ), + on_select_call=bui.CallStrict( + self.sel_change, 'campaign', 'hardButton' + ), color=( sel_color_hard if self._campaign_difficulty == 'hard' @@ -842,7 +846,7 @@ class CoopBrowserWindow(bui.MainWindow): highlight=False, border_opacity=0.0, color=(0.45, 0.4, 0.5), - on_select_call=bui.Call( + on_select_call=bui.CallStrict( self._on_row_selected, 'tournament' + str(i + 1) ), ) @@ -873,7 +877,7 @@ class CoopBrowserWindow(bui.MainWindow): h, v2, is_last_sel, - on_pressed=bui.WeakCall(self.run_tournament), + on_pressed=bui.WeakCallPartial(self.run_tournament), ) ) v -= 200 @@ -927,7 +931,7 @@ class CoopBrowserWindow(bui.MainWindow): highlight=False, border_opacity=0.0, color=(0.45, 0.4, 0.5), - on_select_call=bui.Call(self._on_row_selected, 'custom'), + on_select_call=bui.CallStrict(self._on_row_selected, 'custom'), ) bui.widget( edit=h_scroll, @@ -1033,6 +1037,12 @@ class CoopBrowserWindow(bui.MainWindow): from efro.util import strict_partial from bauiv1lib.confirm import ConfirmWindow + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.START_COOP_SESSION, extra=game + ) + ) + classic = bui.app.classic assert classic is not None @@ -1055,9 +1065,11 @@ class CoopBrowserWindow(bui.MainWindow): ) -> None: """Run the provided game.""" # pylint: disable=cyclic-import + import bacommon.docui.v1 as dui1 + from bauiv1lib.confirm import ConfirmWindow - from bauiv1lib.purchase import PurchaseWindow from bauiv1lib.account.signin import show_sign_in_prompt + from bauiv1lib.store import StoreUIController plus = bui.app.plus assert plus is not None @@ -1075,21 +1087,44 @@ class CoopBrowserWindow(bui.MainWindow): cancel_button=False, width=460, height=130, + origin_widget=origin_widget, ) return required_purchases = bui.app.classic.required_purchases_for_game(game) + have_requirements = True + # Show pop-up to allow purchasing any required stuff we don't have. for purchase in required_purchases: if not purchase in bui.app.classic.purchases: - if plus.accounts.primary is None: - show_sign_in_prompt() - else: - PurchaseWindow( - items=[purchase], origin_widget=origin_widget + have_requirements = False + + if not have_requirements: + if plus.accounts.primary is None: + show_sign_in_prompt() + else: + # Push a custom store window onto our stack. We + # shouldn't use the standard auxiliary store window + # setup since this isn't a standard store window. + wait_for_connectivity( + on_connected=lambda: self.main_window_replace( + bui.CallStrict( + StoreUIController().create_window, + dui1.Request( + '/', + args={'unlockreqs': required_purchases}, + ), + origin_widget=origin_widget, + auxiliary_style=False, + ), + extra_type_id=( + StoreUIController.get_window_extra_type_id() + ), ) - return + ) + + return self._save_state() @@ -1100,9 +1135,11 @@ class CoopBrowserWindow(bui.MainWindow): """Run the provided tournament game.""" # pylint: disable=too-many-return-statements - from bauiv1lib.purchase import PurchaseWindow + import bacommon.docui.v1 as dui1 + from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.tournamententry import TournamentEntryWindow + from bauiv1lib.store import StoreUIController plus = bui.app.plus assert plus is not None @@ -1168,16 +1205,42 @@ class CoopBrowserWindow(bui.MainWindow): # We gotta be missing *something* if its locked. assert required_purchases + have_requirements = True + for purchase in required_purchases: if purchase not in classic.purchases: - if plus.accounts.primary is None: - show_sign_in_prompt() - else: - PurchaseWindow( - items=[purchase], - origin_widget=tournament_button.button, + have_requirements = False + + if not have_requirements: + if plus.accounts.primary is None: + show_sign_in_prompt() + else: + # Push a custom store window onto our stack. We + # shouldn't use the standard auxiliary store + # window setup since this isn't a standard store + # window. + wait_for_connectivity( + on_connected=lambda: self.main_window_replace( + bui.CallStrict( + StoreUIController().create_window, + dui1.Request( + '/', + args={'unlockreqs': required_purchases}, + ), + origin_widget=tournament_button.button, + auxiliary_style=False, + ), + extra_type_id=( + StoreUIController.get_window_extra_type_id() + ), ) - return + ) + + # PurchaseWindow( + # items=[purchase], + # origin_widget=tournament_button.button, + # ) + return if tournament_button.time_remaining <= 0: bui.screenmessage( diff --git a/dist/ba_data/python/bauiv1lib/coop/gamebutton.py b/dist/ba_data/python/bauiv1lib/coop/gamebutton.py index dec0dc8..52b0254 100644 --- a/dist/ba_data/python/bauiv1lib/coop/gamebutton.py +++ b/dist/ba_data/python/bauiv1lib/coop/gamebutton.py @@ -71,7 +71,7 @@ class GameButton: on_activate_call=self._on_press, button_type='square', autoselect=True, - on_select_call=bui.Call(window.sel_change, row, game), + on_select_call=bui.CallStrict(window.sel_change, row, game), ) bui.widget( edit=btn, @@ -188,7 +188,7 @@ class GameButton: # give a quasi-random update increment to spread the load.. self._update_timer = bui.AppTimer( 0.001 * (900 + random.randrange(200)), - bui.WeakCall(self._update), + bui.WeakCallStrict(self._update), repeat=True, ) self._update() diff --git a/dist/ba_data/python/bauiv1lib/coop/tournamentbutton.py b/dist/ba_data/python/bauiv1lib/coop/tournamentbutton.py index e08c26d..6df1c80 100644 --- a/dist/ba_data/python/bauiv1lib/coop/tournamentbutton.py +++ b/dist/ba_data/python/bauiv1lib/coop/tournamentbutton.py @@ -52,7 +52,7 @@ class TournamentButton: label='', button_type='square', autoselect=True, - on_activate_call=bui.WeakCall(self._pressed), + on_activate_call=bui.WeakCallStrict(self._pressed), ) bui.widget( edit=btn, @@ -322,7 +322,7 @@ class TournamentButton: selectable=True, click_activate=True, autoselect=True, - on_activate_call=bui.WeakCall(self._show_leader), + on_activate_call=bui.WeakCallStrict(self._show_leader), size=(170 / 1.4, 40), h_align='center', text='-', @@ -362,7 +362,7 @@ class TournamentButton: autoselect=True, up_widget=self.current_leader_name_text, text_scale=0.6, - on_activate_call=bui.WeakCall(self._show_scores), + on_activate_call=bui.WeakCallStrict(self._show_scores), ) # We handle reselection manually for these so no ids. bui.widget(edit=self.more_scores_button, allow_preserve_selection=False) @@ -411,7 +411,7 @@ class TournamentButton: flatness=1.0, ) self._lock_update_timer = bui.AppTimer( - 1.03, bui.WeakCall(self._update_lock_state), repeat=True + 1.03, bui.WeakCallStrict(self._update_lock_state), repeat=True ) def _pressed(self) -> None: @@ -510,7 +510,7 @@ class TournamentButton: x_offs2c = x_offs2 + 50 # Fetch prize range and trophy strings. - (pr1, pv1, pr2, pv2, pr3, pv3) = classic.get_tournament_prize_strings( + pr1, pv1, pr2, pv2, pr3, pv3 = classic.get_tournament_prize_strings( entry, include_tickets=False ) diff --git a/dist/ba_data/python/bauiv1lib/discord.py b/dist/ba_data/python/bauiv1lib/discord.py index 40aa34f..f432916 100644 --- a/dist/ba_data/python/bauiv1lib/discord.py +++ b/dist/ba_data/python/bauiv1lib/discord.py @@ -114,7 +114,7 @@ class DiscordWindow(bui.Window): autoselect=True, label=bui.Lstr(resource='discordJoinText'), text_scale=1.0, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( bui.open_url, 'https://ballistica.net/discord' ), ) diff --git a/dist/ba_data/python/bauiv1lib/docui/__init__.py b/dist/ba_data/python/bauiv1lib/docui/__init__.py new file mode 100644 index 0000000..189114b --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/__init__.py @@ -0,0 +1,11 @@ +# Released under the MIT License. See LICENSE for details. +"""Functionality for using doc-ui on top of bauiv1.""" + +from bauiv1lib.docui._controller import DocUIController, DocUILocalAction +from bauiv1lib.docui._window import DocUIWindow + +__all__ = [ + 'DocUIController', + 'DocUIWindow', + 'DocUILocalAction', +] diff --git a/dist/ba_data/python/bauiv1lib/docui/_controller.py b/dist/ba_data/python/bauiv1lib/docui/_controller.py new file mode 100644 index 0000000..a024c26 --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/_controller.py @@ -0,0 +1,971 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Controller functionality for DocUI.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, assert_never +from dataclasses import dataclass +from enum import Enum +import weakref + +from efro.util import asserttype +from efro.error import CleanError, CommunicationError +from efro.dataclassio import dataclass_to_json, dataclass_from_json +from bacommon.docui import ( + DocUIRequestTypeID, + UnknownDocUIRequest, + DocUIResponseTypeID, + UnknownDocUIResponse, + DocUIWebRequest, + DocUIWebResponse, +) +import bauiv1 as bui + +from bauiv1lib.docui._window import DocUIWindow + +if TYPE_CHECKING: + from typing import Callable + + import bacommon.docui.v1 + from bacommon.docui import DocUIRequest, DocUIResponse + import bacommon.clienteffect as clfx + + from bauiv1lib.docui import v1prep + + +class _WinState(Enum): + """Per-window state.""" + + FETCHING_FRESH_REQUEST = 0 + REDISPLAYING_OLD_STATE = 1 + REFRESHING = 2 + ERRORED = 3 + IDLE = 4 + + +@dataclass +class _WinData: + state: _WinState + refresh_timer: bui.AppTimer | None = None + + +class DocUIController: + """Manages interactions between DocUI clients and servers. + + Can include logic to handle all requests locally or can submit them + to be handled by some server or can do some combination thereof. + """ + + class ErrorType(Enum): + """Types of errors that can occur in request processing.""" + + GENERIC = 'generic' + UNDER_CONSTRUCTION = 'under_construction' + COMMUNICATION_ERROR = 'communication' + NEED_UPDATE = 'need_update' + + def fulfill_request(self, request: DocUIRequest) -> DocUIResponse: + """Handle request fulfillment. + + Expected to be overridden by child classes. + + Be aware that this will always be called in a background thread. + + This method is expected to always return a response, even in the + case of errors. Use + :meth:`~bauiv1lib.docui.DocUIController.error_response()` to + translate error conditions to responses. + + The one exception to this rule (no pun intended) is the + :class:`efro.error.CleanError` exception. This can be raised as a + quick and dirty way to show custom error messages. The code + ``raise CleanError('Something broke.')`` will have the same + effect as ``return self.error_response(custom_message='Something + broke.')``. + """ + raise NotImplementedError() + + def local_action(self, action: DocUILocalAction) -> None: + """Do something locally on behalf of the doc-ui. + + Controller classes can override this to expose named actions + that can be triggered by doc-ui button presses, responses, + etc. + + Of course controllers can also perform arbitrary local actions + alongside their normal request fulfillment; this is simply a way + to do so without needing to provide actual ui pages alongside. + + Be *very* careful and focused with what you expose here, + especially if your doc-ui pages are coming from untrusted + sources. Generally things like launching or joining games are + good candidates for local actions. + """ + + def fulfill_request_web( + self, request: DocUIRequest, url: str + ) -> DocUIResponse: + """Fulfill a request by sending it to a webserver.""" + import bacommon.docui.v1 as dui1 + + import urllib3.util + + if not isinstance(request, dui1.Request): + raise RuntimeError(f'Unsupported docui request: {type(request)}') + + upool = bui.app.net.urllib3pool + + # Allow compressed results. + headers = urllib3.util.make_headers(accept_encoding=True) + + # Bundle our doc-ui request with some extra stuff that might + # be relevant to a remote server (language we're using, etc.). + webrequest = DocUIWebRequest( + doc_ui_request=request, + locale=bui.app.locale.current_locale, + engine_build_number=bui.app.env.engine_build_number, + ) + + try: + # Map docui GET requests to http GET and POST to POST. + if request.method is dui1.RequestMethod.GET: + # For GET we embed the request into a url param. + raw_response = upool.request( + 'GET', + url, + fields={ + 'doc_ui_web_request': dataclass_to_json(webrequest) + }, + headers=headers, + ) + + elif request.method is dui1.RequestMethod.POST: + # for POST we send the webrequest as json in body. + headers['Content-Type'] = 'application/json' + raw_response = upool.request( + 'POST', + url, + headers=headers, + body=dataclass_to_json(webrequest), + ) + elif request.method is dui1.RequestMethod.UNKNOWN: + raise RuntimeError('Unknown request method.') + else: + assert_never(request.method) + + try: + # We use 'lossy' here so response versions or elements + # that we don't know about will come through as + # 'Unknown' types instead of erroring completely. + webresponse = dataclass_from_json( + DocUIWebResponse, raw_response.data.decode(), lossy=True + ) + if ( + webresponse.error is None + and webresponse.doc_ui_response is None + ): + raise RuntimeError( + 'Invalid webresponse includes neither error' + ' nor doc-ui-response.' + ) + except Exception as exc: + bui.netlog.info( + 'Error reading docui web-response.', exc_info=True + ) + raise RuntimeError('Error reading docui web-response.') from exc + + # For now, consider all errors communication errors (should + # result in retry buttons in some cases). Can get more + # specific in the future for cases where retries would not + # help. + if raw_response.status != 200: + + # If the response bundled an error, log it. + if webresponse.error is not None: + bui.netlog.info( + 'doc-ui http request returned error: %s', + webresponse.error, + ) + return self.error_response( + request, self.ErrorType.COMMUNICATION_ERROR + ) + + except Exception: + # For now, consider all errors communication errors (should + # result in retry buttons in some cases). Can get more + # specific in the future for cases where retries would not + # help. + bui.netlog.info('Error in docui http request.', exc_info=True) + return self.error_response( + request, self.ErrorType.COMMUNICATION_ERROR + ) + + assert webresponse.doc_ui_response is not None + return webresponse.doc_ui_response + + def fulfill_request_cloud( + self, request: DocUIRequest, domain: str + ) -> DocUIResponse: + """Fulfill a request by sending it to ballistica's cloud. + + :meta private: + """ + import bacommon.cloud + + try: + plus = bui.app.plus + if plus is None: + raise RuntimeError('Plus not available.') + + account = plus.accounts.primary + if account is not None: + with account: + mresponse = plus.cloud.send_message( + bacommon.cloud.FulfillDocUIRequest( + request=request, domain=domain + ) + ) + else: + mresponse = plus.cloud.send_message( + bacommon.cloud.FulfillDocUIRequest( + request=request, domain=domain + ) + ) + assert isinstance(mresponse, bacommon.cloud.FulfillDocUIResponse) + + return mresponse.response + + except CommunicationError: + # Label comm-errors so we can possibly show retry buttons. + return self.error_response( + request, self.ErrorType.COMMUNICATION_ERROR + ) + except Exception: + return self.error_response(request) + + def error_response( + self, + request: DocUIRequest, + error_type: ErrorType = ErrorType.GENERIC, + custom_message: str | None = None, + ) -> DocUIResponse: + """Build a simple error message page. + + A message is included based on ``error_type``. Pass + ``custom_message`` to override this. + + Messages will be translated to the client language using the + 'serverResponses' Lstr translation category. + """ + import bacommon.docui.v1 as dui1 + + error_msg: bui.Lstr | None = None + error_msg_simple: str | None = None + + status_code = dui1.ResponseStatus.UNKNOWN_ERROR + + if custom_message is not None: + error_msg_simple = custom_message + else: + if error_type is self.ErrorType.GENERIC: + error_msg_simple = 'An error has occurred.' + elif error_type is self.ErrorType.NEED_UPDATE: + error_msg_simple = 'You must update the app to view this.' + elif error_type is self.ErrorType.UNDER_CONSTRUCTION: + error_msg_simple = 'Under construction - check back soon.' + elif error_type is self.ErrorType.COMMUNICATION_ERROR: + status_code = dui1.ResponseStatus.COMMUNICATION_ERROR + error_msg_simple = 'Error talking to server.' + else: + assert_never(error_type) + if error_msg_simple is not None: + error_msg = bui.Lstr( + translate=('serverResponses', error_msg_simple) + ) + assert error_msg is not None + + debug = False + + # Give a retry button for comm-errors on GET requests (POSTs may + # have unintentional side-effects so holding off on those for + # now). + do_retry = ( + isinstance(request, dui1.Request) + and request.method is dui1.RequestMethod.GET + and status_code is dui1.ResponseStatus.COMMUNICATION_ERROR + ) + + return dui1.Response( + status=status_code, + page=dui1.Page( + title=bui.Lstr(resource='errorText').as_json(), + title_is_lstr=True, + center_vertically=True, + rows=[ + dui1.ButtonRow( + buttons=[ + dui1.Button( + bui.Lstr( + resource=( + 'retryText' if do_retry else 'okText' + ) + ).as_json(), + ( + dui1.Replace( + asserttype(request, dui1.Request) + ) + if do_retry + else dui1.Local(close_window=True) + ), + label_is_lstr=True, + default=True, + style=dui1.ButtonStyle.MEDIUM, + size=(130, 50), + padding_left=200, + padding_right=200, + padding_top=100, + decorations=[ + dui1.Text( + error_msg.as_json(), + is_lstr=True, + position=(0, 80), + size=(480, 50), + highlight=False, + debug=debug, + ), + ], + debug=debug, + ), + ], + center_content=True, + debug=debug, + ), + ], + ), + ) + + def create_window( + self, + request: DocUIRequest, + *, + transition: str | None = 'in_right', + origin_widget: bui.Widget | None = None, + auxiliary_style: bool = True, + uiopenstateid: str | None = None, + suppress_win_extra_type_warning: bool = False, + ) -> DocUIWindow: + """Create a new window to handle a request.""" + assert bui.in_logic_thread() + + # Create a shiny new window. + win = DocUIWindow( + self, + request, + transition=transition, + origin_widget=origin_widget, + auxiliary_style=auxiliary_style, + uiopenstateid=uiopenstateid, + suppress_win_extra_type_warning=suppress_win_extra_type_warning, + ) + self._set_win_data(win, _WinData(_WinState.FETCHING_FRESH_REQUEST)) + + # Lock its ui and kick off a bg task to populate it. + win.lock_ui() + bui.app.threadpool.submit_no_wait( + bui.CallStrict( + self._process_request_in_bg, + request, + weakwin=weakref.ref(win), + uiscale=bui.app.ui_v1.uiscale, + scroll_width=win.scroll_width, + scroll_height=win.scroll_height, + idprefix=win.main_window_id_prefix, + immediate=False, + ) + ) + return win + + def save_window_shared_state( + self, window: DocUIWindow, state: dict + ) -> None: + """Called when a window shared state is being saved.""" + del window, state # Unused. + + def restore_window_shared_state( + self, window: DocUIWindow, state: dict + ) -> None: + """Called when a window shared state is being restored.""" + del window, state # Unused. + + @classmethod + def get_window_extra_type_id(cls) -> str: + """Return a string suitable for the ``window_extra_type_id`` arg to + :meth:`~bauiv1.UIV1AppSubsystem.auxiliary_window_activate()`. + + This ensures your doc-ui window is identified distinctly from + other doc-ui windows for navigation purposes. + """ + # Include the full path of our controller class. + return f'docui:{cls.__module__}.{cls.__qualname__}' + + def restore( + self, + win: DocUIWindow, + *, + last_response: DocUIResponse | None, + has_had_response: bool, + ) -> DocUIWindow: + """Restore a window from previous state. + + May immediately display old results or may kick off a new + request. + """ + import bacommon.docui.v1 as dui1 + + assert bui.in_logic_thread() + + explicit_response: DocUIResponse | None = None + explicit_error: DocUIController.ErrorType | None = None + + if last_response is not None: + # Re-prep our restored response so we have something to show + # immediately. We'll then fetch an updated version in the + # background to get the latest version. + explicit_response = last_response + else: + # We have no previous response to restore. Fetch a new one. + + # If the current request is a POST, never auto-refetch. Just + # build an error response. + assert isinstance(win.request, dui1.Request) + if win.request.method is dui1.RequestMethod.POST: + # Do we want a specific error for this? Though this case + # should be rare I think. + explicit_error = self.ErrorType.GENERIC + else: + explicit_error = None + + # We're either errored or redisplaying an old state. + if explicit_error is None: + self._set_win_data(win, _WinData(_WinState.REDISPLAYING_OLD_STATE)) + else: + self._set_win_data(win, _WinData(_WinState.ERRORED)) + + # Lock the ui and kick off this update. + win.lock_ui() + bui.app.threadpool.submit_no_wait( + bui.CallStrict( + self._process_request_in_bg, + win.request, + weakwin=weakref.ref(win), + uiscale=bui.app.ui_v1.uiscale, + scroll_width=win.scroll_width, + scroll_height=win.scroll_height, + idprefix=win.main_window_id_prefix, + # If this window has had a response already, snap things + # in immediately with no transitions. + immediate=has_had_response, + explicit_error=explicit_error, + explicit_response=explicit_response, + ) + ) + return win + + def replace( + self, + win: DocUIWindow, + request: DocUIRequest, + *, + origin_widget: bui.Widget | None = None, + is_refresh: bool = False, + ) -> None: + """Kick off a request to replace existing window contents.""" + import bacommon.docui.v1 as dui1 + + assert bui.in_logic_thread() + + win.request = request + + requesttype = request.get_type_id() + + if requesttype is DocUIRequestTypeID.V1: + assert isinstance(win.request, dui1.Request) + + self._set_win_data( + win, + ( + _WinData( + _WinState.REFRESHING + if is_refresh + else _WinState.FETCHING_FRESH_REQUEST + ) + ), + ) + + # Lock the ui and kick off this update. + win.lock_ui(origin_widget) + bui.app.threadpool.submit_no_wait( + bui.CallStrict( + self._process_request_in_bg, + win.request, + weakwin=weakref.ref(win), + uiscale=bui.app.ui_v1.uiscale, + scroll_width=win.scroll_width, + scroll_height=win.scroll_height, + idprefix=win.main_window_id_prefix, + immediate=True, + ) + ) + elif requesttype is DocUIRequestTypeID.UNKNOWN: + assert isinstance(win.request, UnknownDocUIRequest) + # Got a request type we don't know. Show a 'need a newer + # build' error. + + self._set_win_data(win, _WinData(_WinState.ERRORED)) + + # Lock the ui and kick off this update. + win.lock_ui(origin_widget) + bui.app.threadpool.submit_no_wait( + bui.CallStrict( + self._process_request_in_bg, + win.request, + weakwin=weakref.ref(win), + uiscale=bui.app.ui_v1.uiscale, + scroll_width=win.scroll_width, + scroll_height=win.scroll_height, + idprefix=win.main_window_id_prefix, + immediate=True, + explicit_error=self.ErrorType.NEED_UPDATE, + ) + ) + else: + assert_never(requesttype) + + def run_action( + self, + window: DocUIWindow, + widgetid: str | None, + action: bacommon.docui.v1.Action | None, + is_timed: bool = False, + ) -> None: + """Called when a button is pressed in a v1 ui.""" + # pylint: disable=too-many-branches + # pylint: disable=cyclic-import + + import bacommon.docui.v1 as dui + + assert bui.in_logic_thread() + + # If locked, been and tell them to try again. + if window.locked: + bui.getsound('error').play() + bui.screenmessage( + bui.Lstr(resource='pageRefreshingTryAgainText'), color=(1, 0, 0) + ) + return + + widget: bui.Widget | None + + if widgetid is not None: + # Find the associated button. + widget = bui.widget_by_id(widgetid) + if widget is None: + bui.uilog.warning( + 'DocUI button press widget not found: %s (not expected)', + widgetid, + ) + return + else: + widget = None + + # Play error beeps on buttons with no actions assigned to let + # the user know nothing is supposed to happen. + if action is None: + bui.getsound('error').play() + return + + action_type = action.get_type_id() + + if action_type is dui.ActionTypeID.BROWSE: + assert isinstance(action, dui.Browse) + if is_timed: + # Don't let timers pop up new windows. Untrusted servers + # would have a field-day with this. + bui.uilog.warning( + 'Ignoring BROWSE action (disallowed in timed actions).' + ) + else: + if action.default_sound: + bui.getsound('swish').play() + window.main_window_replace( + lambda: self.create_window( + action.request, + origin_widget=widget, + auxiliary_style=False, + suppress_win_extra_type_warning=True, + ) + ) + + self._run_immediate_effects_and_actions( + client_effects=action.immediate_client_effects, + local_action=action.immediate_local_action, + local_action_args=action.immediate_local_action_args, + widget=widget, + window=window, + is_timed=is_timed, + ) + + elif action_type is dui.ActionTypeID.REPLACE: + assert isinstance(action, dui.Replace) + + # Play default click sound only if this is coming from a + # button. + if widget is not None and action.default_sound: + bui.getsound('click01').play() + + # Force a state save so if our UI gets rebuilt with the same + # IDs we'll wind up with the same selection and whatnot. + window.main_window_save_shared_state() + self.replace(window, action.request, origin_widget=widget) + + self._run_immediate_effects_and_actions( + client_effects=action.immediate_client_effects, + local_action=action.immediate_local_action, + local_action_args=action.immediate_local_action_args, + widget=widget, + window=window, + is_timed=is_timed, + ) + + elif action_type is dui.ActionTypeID.LOCAL: + assert isinstance(action, dui.Local) + if action.default_sound: + if action.close_window: + # Always play close-window swish, even if we don't have + # a source button. + bui.getsound('swish').play() + else: + # Only play click sound if this is coming from a button. + if widget is not None: + bui.getsound('click01').play() + if action.close_window: + window.main_window_back() + + self._run_immediate_effects_and_actions( + client_effects=action.immediate_client_effects, + local_action=action.immediate_local_action, + local_action_args=action.immediate_local_action_args, + widget=widget, + window=window, + is_timed=is_timed, + ) + elif action_type is dui.ActionTypeID.UNKNOWN: + assert isinstance(action, dui.UnknownAction) + bui.screenmessage('Unknown action.', color=(1, 0, 0)) + bui.getsound('error').play() + else: + # Make sure we handle all options. + assert_never(action_type) + + def _run_immediate_effects_and_actions( + self, + *, + client_effects: list[clfx.Effect], + local_action: str | None, + local_action_args: dict | None, + widget: bui.Widget | None, + window: DocUIWindow, + is_timed: bool, + ) -> None: + # We don't allow timed actions to trigger immediate + # client-effects/local-actions. It would be too easy for such + # things to get unintentionally re-triggered when navigating + # back/etc. We only want those to happen due to direct button + # presses or initial (non-refresh) responses, which should keep + # things feeling mostly intentional. + if is_timed: + if client_effects: + bui.uilog.warning( + 'Ignoring client-effects (disallowed in timed actions).' + ) + if local_action is not None: + bui.uilog.warning( + 'Ignoring local-action (disallowed in timed actions).' + ) + return + + if bui.app.classic is not None and client_effects: + bui.app.classic.run_bs_client_effects(client_effects) + if local_action is not None: + try: + self.local_action( + DocUILocalAction( + name=local_action, + args=( + {} + if local_action_args is None + else local_action_args + ), + widget=widget, + window=window, + ) + ) + except Exception: + bui.uilog.exception( + 'Error running local-action %s.', + local_action, + ) + + def _get_win_data(self, window: DocUIWindow) -> _WinData: + val = getattr(window, '_wcdata') + assert isinstance(val, _WinData) + return val + + def _set_win_data(self, window: DocUIWindow, data: _WinData) -> None: + setattr(window, '_wcdata', data) + + def _process_request_in_bg( + self, + request: DocUIRequest, + *, + weakwin: weakref.ref[DocUIWindow], + uiscale: bui.UIScale, + scroll_width: float, + scroll_height: float, + idprefix: str, + immediate: bool, + explicit_error: ErrorType | None = None, + explicit_response: DocUIResponse | None = None, + ) -> None: + """Wrangle a request from within a background thread. + + This will always return a response, even on error conditions. + """ + # pylint: disable=too-many-locals + # pylint: disable=cyclic-import + import bacommon.docui.v1 as dui1 + from bauiv1lib.docui import v1prep + + assert not bui.in_logic_thread() + + response: DocUIResponse | None = None + error: DocUIController.ErrorType | None = None + + if explicit_error is not None: + error = explicit_error + elif explicit_response is not None: + response = explicit_response + else: + try: + response = self.fulfill_request(request) + except CleanError as exc: + # The one exception case we officially handle. Translate + # this to an error response with a custom message. + response = self.error_response(request, custom_message=str(exc)) + + except Exception: + # fulfill_request is expected to gracefully return even + # on errors. Make noise if it didn't. + bui.uilog.exception( + 'Error in fulfill_request().\n' + 'It should always return responses; not throw exceptions.\n' + 'Use error_response() when errors occur.', + exc_info=True, + ) + error = self.ErrorType.GENERIC + + # Validate any response we got. + if response is not None: + assert error is None + responsetype = response.get_type_id() + + if responsetype is DocUIResponseTypeID.V1: + + assert isinstance(response, dui1.Response) + + # If they require a build-number newer than us, say so. + minbuild = response.minimum_engine_build + if ( + minbuild is not None + and minbuild > bui.app.env.engine_build_number + ): + error = self.ErrorType.NEED_UPDATE + + elif responsetype is DocUIResponseTypeID.UNKNOWN: + assert isinstance(response, UnknownDocUIResponse) + bui.uilog.debug( + 'Got unsupported docui response.', exc_info=True + ) + error = self.ErrorType.NEED_UPDATE + response = None + else: + # Make sure we cover all types we're aware of. + assert_never(responsetype) + + if error is not None: + response = self.error_response(request, error) + + # Currently must be v1 if it made it to here. + assert isinstance(response, dui1.Response) + + pageprep = v1prep.prep_page( + response.page, + uiscale=uiscale, + scroll_width=scroll_width, + scroll_height=scroll_height, + immediate=immediate, + idprefix=idprefix, + ) + + # Go ahead and just push the response along with our weakref + # back to the logic thread for handling. We could quick-out here + # if the window is dead, but wrangling its refs here could + # theoretically lead to it being deallocated here which could be + # problematic. + bui.pushcall( + bui.CallStrict( + self._handle_response_in_ui_thread, + response, + weakwin, + pageprep, + ), + from_other_thread=True, + ) + + def _handle_response_in_ui_thread( + self, + response: DocUIResponse, + weakwin: weakref.ref[DocUIWindow], + pageprep: v1prep.PagePrep, + ) -> None: + import bacommon.docui.v1 as dui1 + + assert bui.in_logic_thread() + + # If our target window died since we made the request, no + # biggie. + win = weakwin() + if win is None: + return + + # Currently should only be sending ourself v1 responses here. + assert isinstance(response, dui1.Response) + + win.unlock_ui() + win.set_last_response( + response, + response.status == dui1.ResponseStatus.SUCCESS, + ) + + # Set the UI. + win.instantiate_ui(pageprep) + + state = self._get_win_data(win).state + + # Run client-effects and local-actions ONLY after fresh requests + # (don't want sounds and other actions firing when we navigate + # back or resize a window). + if state is _WinState.FETCHING_FRESH_REQUEST: + if response.client_effects and bui.app.classic is not None: + bui.app.classic.run_bs_client_effects(response.client_effects) + if response.local_action is not None: + try: + self.local_action( + DocUILocalAction( + name=response.local_action, + args=( + {} + if response.local_action_args is None + else response.local_action_args + ), + widget=None, + window=win, + ) + ) + except Exception: + bui.uilog.exception( + 'Error running local-action %s.', + response.local_action, + ) + + # Possibly take further action depending on state. + if state is _WinState.REDISPLAYING_OLD_STATE: + # Ok; we're done showing old state. For POST this is as far + # as we go (don't want to repeat POST effects), but for GET + # we can now kick off a refresh to swap in the latest + # version of the page. + assert isinstance(win.request, dui1.Request) + if win.request.method is dui1.RequestMethod.GET: + self.replace(win, win.request, is_refresh=True) + elif ( + win.request.method is dui1.RequestMethod.POST + or win.request.method is dui1.RequestMethod.UNKNOWN + ): + self._set_idle_and_schedule_timed_action(response, weakwin) + else: + assert_never(win.request.method) + + elif state is _WinState.ERRORED or state is _WinState.IDLE: + pass + elif ( + state is _WinState.FETCHING_FRESH_REQUEST + or state is _WinState.REFRESHING + ): + self._set_idle_and_schedule_timed_action(response, weakwin) + else: + assert_never(state) + + def _set_idle_and_schedule_timed_action( + self, response: DocUIResponse, weakwin: weakref.ref[DocUIWindow] + ) -> None: + import bacommon.docui.v1 as dui1 + + win = weakwin() + assert win is not None + assert self._get_win_data(win).state is not _WinState.IDLE + assert isinstance(response, dui1.Response) + + refresh_timer: bui.AppTimer | None = None + + if response.timed_action is not None: + + # Limit delay to .25 seconds or more to prevent excessive + # churn. Can revisit if there is a strong use case. + refresh_timer = bui.AppTimer( + max(0.250, response.timed_action_delay), + bui.WeakCallStrict( + self._run_timed_action, + weakwin, + response.timed_action, + ), + ) + self._set_win_data(win, _WinData(_WinState.IDLE, refresh_timer)) + + def _run_timed_action( + self, + weakwin: weakref.ref[DocUIWindow], + action: bacommon.docui.v1.Action, + ) -> None: + # If our target window died since we set this timer, no biggie. + win = weakwin() + if win is None: + return + + state = self._get_win_data(win).state + if state is not _WinState.IDLE: + bui.uilog.warning( + 'win has non-idle state in _run_timed_action; not expected' + ) + return + self.run_action(win, widgetid=None, action=action, is_timed=True) + + +@dataclass +class DocUILocalAction: + """Context for a local-action.""" + + name: str + args: dict + widget: bui.Widget | None + window: DocUIWindow diff --git a/dist/ba_data/python/bauiv1lib/docui/_window.py b/dist/ba_data/python/bauiv1lib/docui/_window.py new file mode 100644 index 0000000..cd858fd --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/_window.py @@ -0,0 +1,546 @@ +# Released under the MIT License. See LICENSE for details. +# +"""UIs provided by the cloud (similar-ish to html in concept).""" + +from __future__ import annotations + +from typing import TYPE_CHECKING, override, assert_never + +import bauiv1 as bui + +from bacommon.docui import DocUIRequestTypeID, DocUIResponseTypeID +from bauiv1lib.utils import scroll_fade_bottom, scroll_fade_top + +if TYPE_CHECKING: + from typing import Callable + + from bacommon.docui import DocUIRequest, DocUIResponse + import bacommon.docui.v1 + from bauiv1lib.docui._controller import DocUIController + from bauiv1lib.docui import v1prep + + +class DocUIWindow(bui.MainWindow): + """Window showing doc-ui content.""" + + def __init__( + self, + controller: DocUIController, + request: DocUIRequest, + *, + transition: str | None = 'in_right', + origin_widget: bui.Widget | None = None, + auxiliary_style: bool = True, + restored: bool = False, + uiopenstateid: str | None = None, + suppress_win_extra_type_warning: bool = False, + has_had_response: bool = False, + ): + # pylint: disable=too-many-statements + ui = bui.app.ui_v1 + + self._uiopenstate = ( + None if uiopenstateid is None else bui.UIOpenState(uiopenstateid) + ) + + self._locked = False + + self._restored = restored + + # Note: our windows and states both hold strong references to + # the controller, so we need to make sure the opposite is not + # true to avoid cycles. + self.controller = controller + + self._suppress_win_extra_type_warning = suppress_win_extra_type_warning + self._request = request + self._request_state_id = self._default_state_id(request) + + self._last_response: DocUIResponse | None = None + self._last_response_success: bool = False + self._last_response_shared_state_id: str | None = None + self._has_had_response: bool = has_had_response + + # We want to display differently whether we're an auxiliary + # window or not, but unfortunately that value is not yet + # available until we're added to the main-window-stack so it + # must be explicitly passed in. + self._auxiliary_style = auxiliary_style + + # Calc scale and size for our backing window. For medium & large + # ui-scale we aim for a window small enough to always be fully + # visible on-screen and for small mode we aim for a window big + # enough that we never see the window edges; only the window + # texture covering the whole screen. + uiscale = ui.uiscale + self._width = ( + 1400 + if uiscale is bui.UIScale.SMALL + else 1100 if uiscale is bui.UIScale.MEDIUM else 1200 + ) + self._height = ( + 1200 + if uiscale is bui.UIScale.SMALL + else 700 if uiscale is bui.UIScale.MEDIUM else 800 + ) + self._root_scale = ( + 1.45 + if uiscale is bui.UIScale.SMALL + else 0.9 if uiscale is bui.UIScale.MEDIUM else 0.8 + ) + + # Do some fancy math to calculate our visible area; this will be + # limited by the screen size in small mode and our backing size + # otherwise. + screensize = bui.get_virtual_screen_size() + self._vis_width = min( + self._width - 150, screensize[0] / self._root_scale + ) + self._vis_height = min( + self._height - 80, screensize[1] / self._root_scale + ) + self._vis_top = 0.5 * self._height + 0.5 * self._vis_height + self._vis_left = 0.5 * self._width - 0.5 * self._vis_width + + self._scroll_width = self._vis_width + self._scroll_left = self._vis_left + 0.5 * ( + self._vis_width - self._scroll_width + ) + # Go with full-screen scrollable aread in small ui. + self._scroll_height = self._vis_height - ( + -1 if uiscale is bui.UIScale.SMALL else 43 + ) + self._scroll_bottom = ( + self._vis_top + - (-1 if uiscale is bui.UIScale.SMALL else 32) + - self._scroll_height + ) + + # Nudge our vis area up a bit when we can see the full backing + # (visual fudge factor). + if uiscale is not bui.UIScale.SMALL: + self._vis_top += 12.0 + + super().__init__( + root_widget=bui.containerwidget( + size=(self._width, self._height), + toolbar_visibility='menu_full', + toolbar_cancel_button_style=( + 'close' if auxiliary_style else 'back' + ), + scale=self._root_scale, + ), + transition=transition, + origin_widget=origin_widget, + # We respond to screen size changes only at small ui-scale; + # in other cases we assume our window remains fully visible + # always (flip to windowed mode and resize the app window to + # confirm this). + refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, + ) + # Avoid complaints if nothing is selected under us. + bui.widget(edit=self._root_widget, allow_preserve_selection=False) + + self._subcontainer: bui.Widget | None = None + + self._scrollwidget = bui.scrollwidget( + parent=self._root_widget, + highlight=True, # Will turn off once we have UI. + size=(self._scroll_width, self._scroll_height), + position=(self._scroll_left, self._scroll_bottom), + border_opacity=0.4, + center_small_content_horizontally=True, + claims_left_right=True, + ) + bui.widget(edit=self._scrollwidget, autoselect=True) + + # With full-screen scrolling, fade content as it approaches + # toolbars. + if uiscale is bui.UIScale.SMALL and bool(True): + scroll_fade_top( + self._root_widget, + self._width * 0.5 - self._scroll_width * 0.5, + self._scroll_bottom, + self._scroll_width, + self._scroll_height, + ) + scroll_fade_bottom( + self._root_widget, + self._width * 0.5 - self._scroll_width * 0.5, + self._scroll_bottom, + self._scroll_width, + self._scroll_height, + ) + + # Title. + self._title = bui.textwidget( + parent=self._root_widget, + position=(self._width * 0.5, self._vis_top - 20), + size=(0, 0), + text='', + color=ui.title_color, + scale=0.9 if uiscale is bui.UIScale.SMALL else 1.0, + # Make sure we avoid overlapping meters in small mode. + maxwidth=(130 if uiscale is bui.UIScale.SMALL else 200), + h_align='center', + v_align='center', + ) + # Needed to display properly over scrolled content. + bui.widget(edit=self._title, depth_range=(0.9, 1.0)) + + # For small UI-scale we use the system back/close button; + # otherwise we make our own. + if uiscale is bui.UIScale.SMALL: + bui.containerwidget( + edit=self._root_widget, on_cancel_call=self.main_window_back + ) + self._back_button: bui.Widget | None = None + else: + self._back_button = bui.buttonwidget( + parent=self._root_widget, + id=f'{self.main_window_id_prefix}|close', + scale=0.8, + position=(self._vis_left + 2, self._vis_top - 35), + size=(50, 50) if auxiliary_style else (60, 55), + extra_touch_border_scale=2.0, + button_type=None if auxiliary_style else 'backSmall', + on_activate_call=self.main_window_back, + autoselect=True, + label=bui.charstr( + bui.SpecialChar.CLOSE + if auxiliary_style + else bui.SpecialChar.BACK + ), + ) + bui.containerwidget( + edit=self._root_widget, cancel_button=self._back_button + ) + + # Show our vis-area bounds (for debugging). + if bool(False): + # Skip top-left since its always overlapping back/close + # buttons. + if bool(False): + bui.textwidget( + parent=self._root_widget, + position=(self._vis_left, self._vis_top), + size=(0, 0), + color=(1, 1, 1, 0.5), + scale=0.5, + text='TL', + h_align='left', + v_align='top', + ) + bui.textwidget( + parent=self._root_widget, + position=(self._vis_left + self._vis_width, self._vis_top), + size=(0, 0), + color=(1, 1, 1, 0.5), + scale=0.5, + text='TR', + h_align='right', + v_align='top', + ) + bui.textwidget( + parent=self._root_widget, + position=(self._vis_left, self._vis_top - self._vis_height), + size=(0, 0), + color=(1, 1, 1, 0.5), + scale=0.5, + text='BL', + h_align='left', + v_align='bottom', + ) + bui.textwidget( + parent=self._root_widget, + position=( + self._vis_left + self._vis_width, + self._vis_top - self._vis_height, + ), + size=(0, 0), + scale=0.5, + color=(1, 1, 1, 0.5), + text='BR', + h_align='right', + v_align='bottom', + ) + + self._spinner: bui.Widget | None = None + + if not suppress_win_extra_type_warning: + bui.pushcall(bui.WeakCallStrict(self._sanity_check_win_extra_type)) + + def _sanity_check_win_extra_type(self) -> None: + # There will be lots of windows with this same type, so we really + # need the user to provide extra-type-ids so our logic can tell + # all of us apart for navigation purposes. + if not self.main_window_extra_type_id: + bui.uilog.warning( + '%s created by %s was not assigned an extra-type-id.' + ' Always pass a "win_extra_type_id" when calling' + ' `auxiliary_window_activate()` with a DocUIWindow.', + type(self).__name__, + type(self.controller), + ) + + @property + def request(self) -> DocUIRequest: + """The current request. + + Should only be accessed from the logic thread while the ui is + unlocked. + """ + assert bui.in_logic_thread() + if self._request is None: + raise RuntimeError('No request is set.') + return self._request + + @request.setter + def request(self, request: DocUIRequest) -> None: + assert bui.in_logic_thread() + self._request = request + self._request_state_id = self._default_state_id(request) + + # New requests immediately blow away existing responses. + self._last_response = None + self._last_response_success = False + self._last_response_shared_state_id = None + + @classmethod + def _default_state_id(cls, request: DocUIRequest) -> str: + """Calc a default state id for a request.""" + requesttypeid = request.get_type_id() + if requesttypeid is DocUIRequestTypeID.V1: + import bacommon.docui.v1 as dui1 + + # One state per path seems like a reasonable default. + assert isinstance(request, dui1.Request) + return request.path + if requesttypeid is DocUIRequestTypeID.UNKNOWN: + return 'unknown' + assert_never(requesttypeid) + + def lock_ui(self, origin_widget: bui.Widget | None = None) -> None: + """Stop UI interactions during some operation.""" + assert bui.in_logic_thread() + assert not self._locked + + # If a spinner-position is provided, make the spinner in our + # subcontainer at the provided spot and have it appear + # immediately instead of fading (Makes button presses feel more + # responsive). + parent = None if origin_widget is None else origin_widget.parent + if parent is not None: + assert origin_widget is not None + self._spinner = bui.spinnerwidget( + parent=parent, + position=origin_widget.center, + size=48, + fade=False, + ) + else: + # Otherwise do one at the center of our window (not in our + # subcontainer). + self._spinner = bui.spinnerwidget( + parent=self._root_widget, + position=( + self._vis_left + self._vis_width * 0.5, + self._vis_top - self._vis_height * 0.5, + ), + size=48, + # With restored windows we're likely to have stuff under + # the spinner. Bomb looks nicer but simple is more + # readable in those cases. + style='simple' if self._restored else 'bomb', + ) + self._locked = True + + def unlock_ui(self) -> None: + """Resume normal UI interactions.""" + assert bui.in_logic_thread() + assert self._locked + + if self._spinner: + self._spinner.delete() + self._spinner = None + self._locked = False + + @property + def locked(self) -> bool: + """Are we locked?""" + assert bui.in_logic_thread() + return self._locked + + @property + def scroll_width(self) -> float: + """Width of our scroll area.""" + return self._scroll_width + + @property + def scroll_height(self) -> float: + """Height of our scroll area.""" + return self._scroll_height + + def set_last_response(self, response: DocUIResponse, success: bool) -> None: + """Set a response to a request.""" + assert bui.in_logic_thread() + assert not self._locked + self._last_response = response + self._last_response_success = success + self._has_had_response = True + + # Grab any custom shared-state-id included in this response. + responsetypeid = response.get_type_id() + if responsetypeid is DocUIResponseTypeID.V1: + import bacommon.docui.v1 as dui1 + + assert isinstance(response, dui1.Response) + self._last_response_shared_state_id = response.shared_state_id + elif responsetypeid is DocUIResponseTypeID.UNKNOWN: + self._last_response_shared_state_id = None + else: + assert_never(responsetypeid) + + def instantiate_ui(self, pageprep: v1prep.PagePrep) -> None: + """Replace any current ui with provided prepped one. + + :meta private: + """ + from bauiv1lib.docui.v1prep._calls import ( + doc_ui_v1_instantiate_page_prep, + ) + + assert bui.in_logic_thread() + + # Set title. + bui.textwidget( + edit=self._title, + literal=not pageprep.title_is_lstr, + text=pageprep.title, + ) + + # Clear any existing children. + for child in self._scrollwidget.get_children(): + child.delete() + + if pageprep.rows: + # Stop showing scroll-widget highlights now that we've got + # child stuff to be highlighted. + bui.scrollwidget( + edit=self._scrollwidget, + highlight=False, + simple_culling_v=pageprep.simple_culling_v, + center_small_content=(pageprep.center_vertically), + ) + self._subcontainer = doc_ui_v1_instantiate_page_prep( + pageprep, + rootwidget=self._root_widget, + scrollwidget=self._scrollwidget, + backbutton=( + bui.get_special_widget('back_button') + if self._back_button is None + else self._back_button + ), + windowbackbutton=self._back_button, + window=self, + ) + else: + # No child stuff to show so let the scroll-widget highlight. + bui.scrollwidget( + edit=self._scrollwidget, + highlight=True, + simple_culling_v=0.0, + center_small_content=True, + ) + self._subcontainer = None + + bui.textwidget( + parent=self._scrollwidget, + h_align='center', + v_align='center', + text=bui.Lstr( + translate=('serverResponses', 'There is nothing here.') + ), + scale=0.75, + color=(1, 1, 1, 0.5), + size=(0, 0), + ) + + # Most of our UI won't exist until this point so we need to + # explicitly restore state for selection restore to work. + # + # Note to self: perhaps we should *not* do this if significant + # time has passed since the window was made or if input commands + # have happened. + self.main_window_restore_shared_state() + + @override + def get_main_window_state(self) -> bui.MainWindowState: + # Support recreating our window for back/refresh purposes. + cls = type(self) + + assert bui.in_logic_thread() + + # IMPORTANT - Pull values from self HERE; if we do it in the + # lambda below it'll keep self alive which will lead to + # 'ui-not-getting-cleaned-up' warnings and memory leaks. + auxiliary_style = self._auxiliary_style + controller = self.controller + request = self._request + last_response = self._last_response + has_had_response = self._has_had_response + uiopenstateid = ( + None if self._uiopenstate is None else self._uiopenstate.stateid + ) + suppress_win_extra_type_warning = self._suppress_win_extra_type_warning + + return bui.BasicMainWindowState( + create_call=( + lambda transition, origin_widget: controller.restore( + cls( + controller=controller, + request=request, + transition=transition, + origin_widget=origin_widget, + auxiliary_style=auxiliary_style, + uiopenstateid=uiopenstateid, + suppress_win_extra_type_warning=( + suppress_win_extra_type_warning + ), + restored=True, + has_had_response=has_had_response, + ), + last_response=last_response, + has_had_response=has_had_response, + ) + ), + uiopenstate=self._uiopenstate, + ) + + @override + def main_window_do_save_shared_state(self, state: dict) -> None: + # Give our controller a stab at this. + self.controller.save_window_shared_state(self, state) + + @override + def main_window_do_restore_shared_state(self, state: dict) -> None: + # Give our controller a stab at this. + self.controller.restore_window_shared_state(self, state) + + @override + def main_window_should_preserve_selection(self) -> bool: + return True + + @override + def get_main_window_shared_state_id(self) -> str | None: + base_id = ( + self._request_state_id + if self._last_response_shared_state_id is None + else self._last_response_shared_state_id + ) + + # Each controller has its own unique domain, so include that in + # the id. + ctp = type(self.controller) + out = f'{ctp.__module__}.{ctp.__qualname__}:{base_id}' + return out diff --git a/dist/ba_data/python/bauiv1lib/docui/v1prep/__init__.py b/dist/ba_data/python/bauiv1lib/docui/v1prep/__init__.py new file mode 100644 index 0000000..5cf353a --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/v1prep/__init__.py @@ -0,0 +1,40 @@ +# Released under the MIT License. See LICENSE for details. +"""Functionality related to prepping a v1 doc-ui. + +.. warning:: + + This is an internal api and subject to change at any time. Do not use + it in mod code. +""" + +from bauiv1lib.docui.v1prep._types import ( + DecorationPrep, + ButtonPrep, + RowPrep, + PagePrep, +) +from bauiv1lib.docui.v1prep._calls import prep_page +from bauiv1lib.docui.v1prep._calls2 import ( + prep_text, + prep_decorations, + prep_image, + prep_row_debug, + prep_row_debug_button, + prep_button_debug, + prep_display_item, +) + +__all__ = [ + 'DecorationPrep', + 'ButtonPrep', + 'RowPrep', + 'PagePrep', + 'prep_page', + 'prep_text', + 'prep_decorations', + 'prep_image', + 'prep_row_debug', + 'prep_row_debug_button', + 'prep_button_debug', + 'prep_display_item', +] diff --git a/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls.py b/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls.py new file mode 100644 index 0000000..9cb30a8 --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls.py @@ -0,0 +1,778 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Prep functionality for our UI. + +We do all layout math and bake out partial ui calls in a background +thread so there's as little work to do in the ui thread as possible. +""" + +from __future__ import annotations + +import copy +from functools import partial +from typing import TYPE_CHECKING, assert_never + +from efro.util import strict_partial +import bacommon.docui.v1 as dui1 +import bauiv1 as bui + +from bauiv1lib.docui.v1prep._types import PagePrep, RowPrep, ButtonPrep + +if TYPE_CHECKING: + from typing import Callable + + from bauiv1lib.docui import DocUIWindow + + +def prep_page( + page: dui1.Page, + *, + uiscale: bui.UIScale, + scroll_width: float, + scroll_height: float, + idprefix: str, + immediate: bool = False, +) -> PagePrep: + """Prep a page.""" + # pylint: disable=too-many-statements + # pylint: disable=too-many-branches + # pylint: disable=too-many-locals + # pylint: disable=cyclic-import + + import bauiv1lib.docui.v1prep._calls2 as prepcalls2 + + # Create a filtered list of rows we know how to display. + page_rows_filtered: list[dui1.ButtonRow] = [] + for pagerow in page.rows: + if isinstance(pagerow, dui1.ButtonRow): + if not pagerow.buttons: + pagerow = copy.deepcopy(pagerow) + pagerow.buttons.append( + dui1.Button( + label=bui.Lstr( + translate=( + 'serverResponses', + 'There is nothing here.', + ) + ).as_json(), + label_color=(1, 1, 1, 0.3), + label_is_lstr=True, + size=(220, 100), + label_scale=0.6, + texture='buttonSquareWide', + padding_top=-8, + padding_bottom=-10, + color=(0.2, 0.2, 0.2, 0.15), + action=dui1.Local(default_sound=False), + ) + ) + page_rows_filtered.append(pagerow) + if len(page_rows_filtered) != len(page.rows): + bui.uilog.error('Got unknown row type(s) in doc-ui; ignoring.') + + # Ok; we've got some buttons. Build our full UI. + row_title_height_with_subtitle = 30.0 + row_title_height_no_subtitle = 38.0 + row_subtitle_height = 30.0 + + # Buffers for *everything*. Set bases here that look decent and + # allow page to offset them. + top_buffer = 20.0 + page.padding_top + bot_buffer = 20.0 + page.padding_bottom + left_buffer = 10.0 + page.padding_left + # Nudge a bit due to scrollbar. + right_buffer = 20.0 + page.padding_right + + # Extra buffers for title/headers stuff (not in h-scroll). + header_inset_left = 45.0 + header_inset_right = 30.0 + + default_button_width = 150.0 + default_button_height = 100.0 + + if uiscale is bui.UIScale.SMALL: + top_bar_overlap = 70 + bot_bar_overlap = 70 + top_buffer += top_bar_overlap + bot_buffer += bot_bar_overlap + else: + top_bar_overlap = 0 + bot_bar_overlap = 0 + + # Should look into why this is necessary. + fudge = 15.0 + hscrollinset = 15.0 + + rootcall: Callable[..., bui.Widget] | None = None + rows: list[RowPrep] = [] + width: float = scroll_width + fudge + height: float = ( + top_buffer + + bot_buffer + + page.row_spacing * max(0, (len(page_rows_filtered) - 1)) + ) + simple_culling_v: float = page.simple_culling_v + center_vertically: bool = page.center_vertically + title: str = page.title + title_is_lstr: bool = page.title_is_lstr + + # Called with root container after construction completes. + root_post_calls: list[Callable[[bui.Widget], None]] = [] + + nextbuttonid = 0 + + have_start_button = False + have_selected_button = False + + # Precalc basic info like dimensions for all rows. + for row in page_rows_filtered: + + # assert row.buttons + this_row_width = ( + left_buffer + + right_buffer + + row.padding_left + + row.padding_right + + row.button_spacing * (len(row.buttons) - 1) + ) + button_row_height = 30.0 + for button in row.buttons: + if button.size is None: + bwidth = default_button_width + bheight = default_button_height + else: + bwidth = button.size[0] + bheight = button.size[1] + bscale = button.scale + bwidthfull = bwidth * bscale + bheightfull = bheight * bscale + # Include button padding when calcing full needed height. + button_row_height = max( + button_row_height, + bheightfull + + (button.padding_top + button.padding_bottom) * button.scale, + ) + this_row_width += ( + bwidthfull + + (button.padding_left + button.padding_right) * button.scale + ) + # Note: this includes everything in the *scrollable* part of + # the row. + this_row_height = ( + row.padding_top + row.padding_bottom + button_row_height + ) + rows.append( + RowPrep( + width=this_row_width, + height=this_row_height, + titlecalls=[], + hscrollcall=None, + hscrolleditcall=None, + hsubcall=None, + buttons=[], + simple_culling_h=row.simple_culling_h, + decorations=[], + ) + ) + assert this_row_height > 0.0 + assert this_row_width > 0.0 + + # Add height that is *not* part of the h-scrollable area. + height += row.header_height * row.header_scale + if row.title is not None: + height += ( + row_title_height_no_subtitle + if row.subtitle is None + else row_title_height_with_subtitle + ) + if row.subtitle is not None: + height += row_subtitle_height + height += this_row_height + height += row.spacing_top + row.spacing_bottom + + # Ok; we've got all row dimensions. Now prep calls to make the + # subcontainers to fit everything and fill out all rows. + rootcall = partial( + bui.containerwidget, + size=(width, height), + claims_left_right=True, + background=False, + ) + y = height - top_buffer + + for i, (row, rowprep) in enumerate( + zip(page_rows_filtered, rows, strict=True) + ): + tdelaybase = 0.06 * (i + 1) + + y -= row.spacing_top + + if i != 0: + y -= page.row_spacing + + # Header decorations. + header_height_full = row.header_height * row.header_scale + y -= header_height_full + hdecs_l = ( + [] + if row.header_decorations_left is None + else row.header_decorations_left + ) + prepcalls2.prep_decorations( + hdecs_l, + left_buffer + header_inset_left, + y + header_height_full * 0.5, + row.header_scale, + tdelay=None if immediate else (tdelaybase + 0.05), + highlight=False, + out_decoration_preps=rowprep.decorations, + ) + hdecs_c = ( + [] + if row.header_decorations_center is None + else row.header_decorations_center + ) + prepcalls2.prep_decorations( + hdecs_c, + width * 0.5, + y + header_height_full * 0.5, + row.header_scale, + tdelay=None if immediate else (tdelaybase + 0.05), + highlight=False, + out_decoration_preps=rowprep.decorations, + ) + hdecs_r = ( + [] + if row.header_decorations_right is None + else row.header_decorations_right + ) + prepcalls2.prep_decorations( + hdecs_r, + width - right_buffer - header_inset_right, + y + header_height_full * 0.5, + row.header_scale, + tdelay=None if immediate else (tdelaybase + 0.05), + highlight=False, + out_decoration_preps=rowprep.decorations, + ) + + if row.title is not None: + rowprep.titlecalls.append( + partial( + bui.textwidget, + position=( + ( + ((width - left_buffer - right_buffer) * 0.5) + + 7.0 # Fudge factor to match hscroll + if row.center_title + else (left_buffer + header_inset_left) + ), + y - row_subtitle_height * 0.5, + ), + size=(0, 0), + text=row.title, + color=( + (0.85, 0.95, 0.89, 1.0) + if row.title_color is None + else row.title_color + ), + flatness=row.title_flatness, + shadow=row.title_shadow, + scale=1.0, + maxwidth=( + (width - left_buffer - right_buffer) + if row.center_title + else ( + width + - left_buffer + - right_buffer + - header_inset_left + - header_inset_right + ) + ), + h_align='center' if row.center_title else 'left', + v_align='center', + literal=not row.title_is_lstr, + transition_delay=( + None if immediate else (tdelaybase + 0.1) + ), + ) + ) + y -= ( + row_title_height_no_subtitle + if row.subtitle is None + else row_title_height_with_subtitle + ) + if row.subtitle is not None: + rowprep.titlecalls.append( + partial( + bui.textwidget, + position=( + ( + ((width - left_buffer - right_buffer) * 0.5) + + 7.0 # Fudge factor to match hscroll + if row.center_title + else (left_buffer + header_inset_left) + ), + y - row_subtitle_height * 0.5, + ), + size=(0, 0), + text=row.subtitle, + color=( + (0.6, 0.74, 0.6) + if row.subtitle_color is None + else row.subtitle_color + ), + flatness=row.subtitle_flatness, + shadow=row.subtitle_shadow, + scale=0.7, + maxwidth=( + (width - left_buffer - right_buffer) + if row.center_title + else ( + width + - left_buffer + - right_buffer + - header_inset_left + - header_inset_right + ) + ), + h_align='center' if row.center_title else 'left', + v_align='center', + literal=not row.subtitle_is_lstr, + transition_delay=( + None if immediate else (tdelaybase + 0.2) + ), + ) + ) + y -= row_subtitle_height + + y -= rowprep.height # includes padding-top/bottom + + if row.debug: + rowheightfull = ( + rowprep.height + row.header_height * row.header_scale + ) + if row.title is not None: + rowheightfull += ( + row_title_height_no_subtitle + if row.subtitle is None + else row_title_height_with_subtitle + ) + if row.subtitle is not None: + rowheightfull += row_subtitle_height + prepcalls2.prep_row_debug( + ( + width - left_buffer - right_buffer, + rowheightfull, + ), + (left_buffer, y), + None if immediate else tdelaybase, + rowprep.decorations, + ) + + rowprep.hscrollcall = partial( + bui.hscrollwidget, + size=(width - hscrollinset, rowprep.height), + position=(hscrollinset, y), + claims_left_right=True, + highlight=False, + border_opacity=0.0, + center_small_content=row.center_content, + simple_culling_h=row.simple_culling_h, + ) + rowprep.hsubcall = partial( + bui.containerwidget, + size=( + # Ideally we could just always use row-width, but + # currently that gets us right-aligned stuff when + # center-small-content is off. + ( + rowprep.width + if row.center_content + else max(width - hscrollinset - fudge, rowprep.width) + ), + rowprep.height, + ), + background=False, + ) + x = left_buffer + row.padding_left + # Calc height of buttons themselves (includes button padding but + # not row padding). + button_row_height = ( + rowprep.height - row.padding_top - row.padding_bottom + ) + bcount = len(row.buttons) + + # Clamp or max delay if we've got lots of buttons. + bdelaymax = min(0.5, 0.03 * bcount) + for j, button in enumerate(row.buttons): + # Calc amt 1 -> 0 across the row. + tdelayamt = 1.0 - (j / max(1, bcount - 1)) + # Rightmost buttons slide in first. + tdelay = tdelaybase + tdelayamt * bdelaymax + + xorig = x + x += button.padding_left * button.scale + bscale = button.scale + if button.size is None: + bwidth = default_button_width + bheight = default_button_height + else: + bwidth = button.size[0] + bheight = button.size[1] + bwidthfull = bscale * bwidth + bheightfull = bscale * bheight + # Vertically center the button plus its padding. + to_button_plus_padding_bottom = ( + button_row_height + - ( + bheightfull + + (button.padding_top + button.padding_bottom) + * button.scale + ) + ) * 0.5 + # Move up past bottom padding to get button bottom. + to_button_bottom = ( + to_button_plus_padding_bottom + + button.padding_bottom * button.scale + ) + + center_x = x + bwidthfull * 0.5 + center_y = row.padding_bottom + to_button_bottom + bheightfull * 0.5 + + bstyle: str + if button.style is dui1.ButtonStyle.SQUARE: + bstyle = 'square' + elif button.style is dui1.ButtonStyle.TAB: + bstyle = 'tab' + elif button.style is dui1.ButtonStyle.SMALL: + bstyle = 'small' + elif button.style is dui1.ButtonStyle.MEDIUM: + bstyle = 'medium' + elif button.style is dui1.ButtonStyle.LARGE: + bstyle = 'large' + elif button.style is dui1.ButtonStyle.LARGER: + bstyle = 'larger' + elif button.style is dui1.ButtonStyle.BACK: + bstyle = 'back' + elif button.style is dui1.ButtonStyle.BACK_SMALL: + bstyle = 'backSmall' + elif button.style is dui1.ButtonStyle.SQUARE_WIDE: + bstyle = 'squareWide' + else: + assert_never(button.style) + + widgetid: str + if button.widget_id is None: + widgetid = f'{idprefix}|button{nextbuttonid}' + nextbuttonid += 1 + else: + widgetid = f'{idprefix}|{button.widget_id}' + + if button.default: + if have_start_button: + bui.uilog.warning( + 'Multiple buttons flagged as default.' + ' There can be only one per page.' + ) + else: + have_start_button = True + root_post_calls.append(partial(_set_start_button, widgetid)) + if button.selected: + if have_selected_button: + bui.uilog.warning( + 'Multiple buttons flagged as selected.' + ' There can be only one per page.' + ) + else: + have_selected_button = True + root_post_calls.append( + partial(_set_selected_button, widgetid) + ) + + show_buffer_left = button.padding_left * bscale + show_buffer_right = button.padding_right * bscale + + # Calc the total height of what we're trying to keep on + # screen, and then nudge that towards the total visible + # height of the scroll area. + total_show_width = ( + bwidth + button.padding_left + button.padding_right + ) * bscale + + # How much to push show-height towards full available space. + # 1.0 should lead to always perfect centering (but that + # might feel too aggressive). + amt = 0.6 + buffer_extra = max( + 0.0, (scroll_width - total_show_width) * 0.5 * amt + ) + show_buffer_left += buffer_extra + show_buffer_right += buffer_extra + + buttonprep = ButtonPrep( + buttoncall=partial( + bui.buttonwidget, + id=widgetid, + position=(x, row.padding_bottom + to_button_bottom), + size=(bwidth, bheight), + scale=bscale, + color=(None if button.color is None else button.color[:3]), + textcolor=button.label_color, + text_flatness=(button.label_flatness), + text_scale=button.label_scale, + button_type=bstyle, + opacity=(1.0 if button.color is None else button.color[3]), + label='' if button.label is None else button.label, + text_literal=not button.label_is_lstr, + autoselect=True, + enable_sound=False, + transition_delay=None if immediate else tdelay, + icon_color=button.icon_color, + iconscale=button.icon_scale, + better_bg_fit=True, + ), + buttoneditcall=partial( + bui.widget, + # TODO: Calc left/right vals properly based on + # our size and padding. + show_buffer_left=show_buffer_left, + show_buffer_right=show_buffer_right, + depth_range=button.depth_range, + # We explicitly assign all neighbor selection; + # anything left over should go to toolbars. + auto_select_toolbars_only=True, + ), + decorations=[], + textures={}, + widgetid=widgetid, + action=button.action, + ) + if button.texture is not None: + buttonprep.textures['texture'] = button.texture + + if button.icon is not None: + buttonprep.textures['icon'] = button.icon + + # With row-debug on, visualize the area we try to scroll to + # show when each button is selected. Note that we're clamped + # by the h-scroll here so we have to draw a separate box for + # the row title/subtitle. + if row.debug: + prepcalls2.prep_row_debug_button( + ( + bwidthfull + + (button.padding_left + button.padding_right) + * button.scale, + rowprep.height, + ), + (xorig, 0.0), + None if immediate else tdelay, + buttonprep.decorations, + ) + + if button.debug: + prepcalls2.prep_button_debug( + (bwidthfull, bheightfull), + (center_x, center_y), + None if immediate else tdelay, + buttonprep.decorations, + ) + decorations = ( + [] if button.decorations is None else button.decorations + ) + prepcalls2.prep_decorations( + decorations, + center_x, + center_y, + bscale, + None if immediate else tdelay, + highlight=True, + out_decoration_preps=buttonprep.decorations, + ) + + rowprep.buttons.append(buttonprep) + + x += ( + bwidthfull + + (button.padding_right * button.scale) + + row.button_spacing + ) + + # Add an edit call for our new hscroll to give it proper + # show-buffers. + + # Incorporate top buffer so we scroll all the way up + # when selecting the top row (and stay clear of + # toolbars). + show_buffer_top = top_buffer + show_buffer_bottom = bot_buffer + + # Scroll so title/subtitle is in view when selecting. + # Note that we don't need to account for + # padding-top/bottom since the h-scroll that we're + # applying to encompasses both. + show_buffer_top += row.header_height * row.header_scale + if row.title is not None: + show_buffer_top += ( + row_title_height_no_subtitle + if row.subtitle is None + else row_title_height_with_subtitle + ) + if row.subtitle is not None: + show_buffer_top += row_subtitle_height + + # Calc the total height of what we're trying to keep on + # screen, and then nudge that towards the total visible + # height of the scroll area. + total_show_height = ( + rowprep.height + show_buffer_top + show_buffer_bottom + ) + # How much to push show-height towards full available space. + # 1.0 should lead to always perfect centering (but that + # might feel too aggressive). + amt = 0.5 + buffer_extra = max(0.0, (scroll_height - total_show_height) * 0.5 * amt) + + show_buffer_top += buffer_extra + show_buffer_bottom += buffer_extra + + rowprep.hscrolleditcall = partial( + bui.widget, + show_buffer_top=show_buffer_top, + show_buffer_bottom=show_buffer_bottom, + ) + y -= row.spacing_bottom + + return PagePrep( + rootcall=rootcall, + rows=rows, + width=width, + height=height, + simple_culling_v=simple_culling_v, + center_vertically=center_vertically, + title=title, + title_is_lstr=title_is_lstr, + root_post_calls=root_post_calls, + ) + + +def doc_ui_v1_instantiate_page_prep( + pageprep: PagePrep, + *, + rootwidget: bui.Widget, + scrollwidget: bui.Widget, + backbutton: bui.Widget, + windowbackbutton: bui.Widget | None, + window: DocUIWindow, +) -> bui.Widget: + """Create a UI using prepped data.""" + # pylint: disable=too-many-locals + # pylint: disable=too-many-branches + outrows: list[tuple[bui.Widget, list[bui.Widget]]] = [] + + # Now go through and run our prepped ui calls to build our + # widgets, plugging in appropriate parent widgets args and + # whatnot as we go. + assert pageprep.rootcall is not None + subcontainer = pageprep.rootcall(parent=scrollwidget) + for rowprep in pageprep.rows: + for uicall in rowprep.titlecalls: + uicall(parent=subcontainer) + assert rowprep.hscrollcall is not None + hscroll = rowprep.hscrollcall(parent=subcontainer) + for decoration in rowprep.decorations: + kwds: dict = {'parent': subcontainer} + for texarg, texname in decoration.textures.items(): + kwds[texarg] = bui.gettexture(texname) + for mesharg, meshname in decoration.meshes.items(): + kwds[mesharg] = bui.getmesh(meshname) + decoration.call(**kwds) + outrow: tuple[bui.Widget, list[bui.Widget]] = (hscroll, []) + assert rowprep.hsubcall is not None + hsub = rowprep.hsubcall(parent=hscroll) + for i, buttonprep in enumerate(rowprep.buttons): + kwds = { + 'parent': hsub, + 'on_activate_call': strict_partial( + window.controller.run_action, + window, + buttonprep.widgetid, + buttonprep.action, + ), + } + for texarg, texname in buttonprep.textures.items(): + kwds[texarg] = bui.gettexture(texname) + btn = buttonprep.buttoncall(**kwds) + assert buttonprep.buttoneditcall is not None + buttonprep.buttoneditcall(edit=btn) + for decoration in buttonprep.decorations: + kwds = {'parent': hsub} + if decoration.highlight: + kwds['draw_controller'] = btn + for texarg, texname in decoration.textures.items(): + kwds[texarg] = bui.gettexture(texname) + for mesharg, meshname in decoration.meshes.items(): + kwds[mesharg] = bui.getmesh(meshname) + decoration.call(**kwds) + + # Make sure row is scrolled so leftmost button is + # visible (though it kinda seems like this should happen + # by default). + if i == 0: + bui.containerwidget(edit=hsub, visible_child=btn) + outrow[1].append(btn) + + outrows.append(outrow) + assert rowprep.hscrolleditcall is not None + rowprep.hscrolleditcall(edit=hscroll) + + for root_post_call in pageprep.root_post_calls: + root_post_call(rootwidget) + + # Ok; we've got all widgets. Now wire up directional nav between + # rows/buttons. + + # Up press on any top-row button should select window back button + # (if there is one). + if outrows and windowbackbutton is not None: + _scroll, buttons = outrows[0] + for button in buttons: + bui.widget(edit=button, up_widget=windowbackbutton) + for _scroll, buttons in outrows: + # Left press on first button in any row should select back + # button (either system one or window one). + if buttons: + bui.widget(edit=buttons[0], left_widget=backbutton) + # Left/right presses should select neighbor button in + # row (when there is one). + for i in range(0, len(buttons) - 1): + leftbutton = buttons[i] + rightbutton = buttons[i + 1] + bui.widget(edit=leftbutton, right_widget=rightbutton) + bui.widget(edit=rightbutton, left_widget=leftbutton) + # Down/up presses should select next/prev row (when there is + # one). + for i in range(0, len(outrows) - 1): + topscroll, topbuttons = outrows[i] + botscroll, botbuttons = outrows[i + 1] + for topbutton in topbuttons: + bui.widget(edit=topbutton, down_widget=botscroll) + for botbutton in botbuttons: + bui.widget(edit=botbutton, up_widget=topscroll) + + return subcontainer + + +def _set_start_button(buttonid: str, root: bui.Widget) -> None: + widget = bui.widget_by_id(buttonid) + if widget: + bui.containerwidget(edit=root, start_button=widget) + + +def _set_selected_button(buttonid: str, root: bui.Widget) -> None: + del root # Unused. + widget = bui.widget_by_id(buttonid) + if widget: + widget.global_select() diff --git a/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls2.py b/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls2.py new file mode 100644 index 0000000..192255c --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/v1prep/_calls2.py @@ -0,0 +1,604 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Prep functionality for our UI. + +We do all layout math and bake out partial ui calls in a background +thread so there's as little work to do in the ui thread as possible. +""" + +from __future__ import annotations + +from functools import partial +from typing import TYPE_CHECKING, assert_never + +from efro.util import pairs_from_flat +import bacommon.displayitem as ditm +import bacommon.docui.v1 as dui1 +import bauiv1 as bui + +from bauiv1lib.docui.v1prep._types import DecorationPrep + +if TYPE_CHECKING: + from typing import Callable + + from bauiv1lib.docui import DocUIWindow + + +def prep_decorations( + decorations: list[dui1.Decoration], + center_x: float, + center_y: float, + scale: float, + tdelay: float | None, + *, + highlight: bool, + out_decoration_preps: list[DecorationPrep], +) -> None: + """Prep appropriate decoration types for a list of decorations.""" + for decoration in decorations: + dectypeid = decoration.get_type_id() + if dectypeid is dui1.DecorationTypeID.UNKNOWN: + if bui.do_once(): + bui.uilog.exception( + 'DocUI receieved unknown decoration;' + ' this is likely a server error.' + ) + elif dectypeid is dui1.DecorationTypeID.TEXT: + assert isinstance(decoration, dui1.Text) + prep_text( + decoration, + (center_x, center_y), + scale, + tdelay, + out_decoration_preps, + highlight=highlight, + ) + + elif dectypeid is dui1.DecorationTypeID.IMAGE: + assert isinstance(decoration, dui1.Image) + prep_image( + decoration, + (center_x, center_y), + scale, + tdelay, + out_decoration_preps, + highlight=highlight, + ) + elif dectypeid is dui1.DecorationTypeID.DISPLAY_ITEM: + assert isinstance(decoration, dui1.DisplayItem) + prep_display_item( + decoration, + (center_x, center_y), + scale, + tdelay, + out_decoration_preps, + highlight=highlight, + ) + else: + assert_never(dectypeid) + + +def prep_text( + text: dui1.Text, + bcenter: tuple[float, float], + bscale: float, + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], + *, + highlight: bool, +) -> None: + """Prep decorations for text.""" + # pylint: disable=too-many-branches + xoffs = bcenter[0] + text.position[0] * bscale + yoffs = bcenter[1] + text.position[1] * bscale + + if text.h_align is dui1.HAlign.LEFT: + h_align = 'left' + elif text.h_align is dui1.HAlign.CENTER: + h_align = 'center' + elif text.h_align is dui1.HAlign.RIGHT: + h_align = 'right' + else: + assert_never(text.h_align) + + if text.v_align is dui1.VAlign.TOP: + v_align = 'top' + elif text.v_align is dui1.VAlign.CENTER: + v_align = 'center' + elif text.v_align is dui1.VAlign.BOTTOM: + v_align = 'bottom' + else: + assert_never(text.v_align) + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.textwidget, + position=(xoffs, yoffs), + scale=text.scale * bscale, + maxwidth=text.size[0] * bscale, + max_height=text.size[1] * bscale, + flatness=text.flatness, + shadow=text.shadow, + h_align=h_align, + v_align=v_align, + size=(0, 0), + color=text.color, + text=text.text, + literal=not text.is_lstr, + transition_delay=tdelay, + depth_range=text.depth_range, + ), + textures={}, + meshes={}, + highlight=highlight and text.highlight, + ) + ) + # Draw square around max width/height in debug mode. + if text.debug: + mwfull = bscale * text.size[0] + mhfull = bscale * text.size[1] + + if text.h_align is dui1.HAlign.LEFT: + mwxoffs = xoffs + elif text.h_align is dui1.HAlign.CENTER: + mwxoffs = xoffs - mwfull * 0.5 + elif text.h_align is dui1.HAlign.RIGHT: + mwxoffs = xoffs - mwfull + else: + assert_never(text.h_align) + + if text.v_align is dui1.VAlign.TOP: + mwyoffs = yoffs - mhfull + elif text.v_align is dui1.VAlign.CENTER: + mwyoffs = yoffs - mhfull * 0.5 + elif text.v_align is dui1.VAlign.BOTTOM: + mwyoffs = yoffs + else: + assert_never(text.v_align) + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=(mwxoffs, mwyoffs), + size=(mwfull, mhfull), + color=(1, 0, 0), + opacity=0.2, + transition_delay=tdelay, + ), + textures={'texture': 'white'}, + meshes={}, + highlight=True, + ) + ) + + +def prep_image( + image: dui1.Image, + bcenter: tuple[float, float], + bscale: float, + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], + *, + highlight: bool, +) -> None: + """Prep decorations for an image.""" + xoffs = bcenter[0] + image.position[0] * bscale + yoffs = bcenter[1] + image.position[1] * bscale + + widthfull = bscale * image.size[0] + heightfull = bscale * image.size[1] + + if image.h_align is dui1.HAlign.LEFT: + xoffsfin = xoffs + elif image.h_align is dui1.HAlign.CENTER: + xoffsfin = xoffs - widthfull * 0.5 + elif image.h_align is dui1.HAlign.RIGHT: + xoffsfin = xoffs - widthfull + else: + assert_never(image.h_align) + + if image.v_align is dui1.VAlign.TOP: + yoffsfin = yoffs - heightfull + elif image.v_align is dui1.VAlign.CENTER: + yoffsfin = yoffs - heightfull * 0.5 + elif image.v_align is dui1.VAlign.BOTTOM: + yoffsfin = yoffs + else: + assert_never(image.v_align) + + textures: dict[str, str] = {'texture': image.texture} + if image.tint_texture is not None: + textures['tint_texture'] = image.tint_texture + if image.mask_texture is not None: + textures['mask_texture'] = image.mask_texture + + meshes: dict[str, str] = {} + if image.mesh_opaque is not None: + meshes['mesh_opaque'] = image.mesh_opaque + if image.mesh_transparent is not None: + meshes['mesh_transparent'] = image.mesh_transparent + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=(xoffsfin, yoffsfin), + size=(widthfull, heightfull), + color=None if image.color is None else image.color[:3], + opacity=1.0 if image.color is None else image.color[3], + tint_color=image.tint_color, + tint2_color=image.tint2_color, + transition_delay=tdelay, + depth_range=image.depth_range, + ), + textures=textures, + meshes=meshes, + highlight=highlight and image.highlight, + ) + ) + + +def prep_row_debug( + size: tuple[float, float], + pos: tuple[float, float], + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], +) -> None: + """Prep debug decorations for a row.""" + + textures: dict[str, str] = {'texture': 'white'} + + # Shrink the square we draw a tiny bit so rows butted up to + # eachother can be seen. + border_shrink = 1.0 + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=(pos[0], pos[1] + border_shrink), + size=(size[0], size[1] - 2.0 * border_shrink), + color=(0, 0, 1.0), + opacity=0.1, + transition_delay=tdelay, + ), + textures=textures, + meshes={}, + highlight=True, + ) + ) + + +def prep_row_debug_button( + bsize: tuple[float, float], + bcorner: tuple[float, float], + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], +) -> None: + """Prep debug decorations for a button.""" + xoffs = bcorner[0] + yoffs = bcorner[1] + + textures: dict[str, str] = {'texture': 'white'} + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=(xoffs, yoffs), + size=bsize, + color=(0.0, 0.0, 1), + opacity=0.15, + transition_delay=tdelay, + ), + textures=textures, + meshes={}, + highlight=True, + ) + ) + + +def prep_button_debug( + bsize: tuple[float, float], + bcenter: tuple[float, float], + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], +) -> None: + """Prep debug decorations for a button.""" + textures: dict[str, str] = {'texture': 'white'} + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=( + bcenter[0] - bsize[0] * 0.5, + bcenter[1] - bsize[1] * 0.5, + ), + size=bsize, + color=(0, 1, 0), + opacity=0.1, + transition_delay=tdelay, + ), + textures=textures, + meshes={}, + highlight=True, + ) + ) + + +def prep_display_item( + display_item: dui1.DisplayItem, + parent_center: tuple[float, float], + parent_scale: float, + tdelay: float | None, + out_decoration_preps: list[DecorationPrep], + *, + highlight: bool, +) -> None: + """Prep decorations for a display-item.""" + # pylint: disable=too-many-branches + # pylint: disable=too-many-statements + # pylint: disable=too-many-locals + + # Calc center and size of our bounds based on parent. + our_center = ( + parent_center[0] + display_item.position[0] * parent_scale, + parent_center[1] + display_item.position[1] * parent_scale, + ) + bounds_size = ( + parent_scale * display_item.size[0], + parent_scale * display_item.size[1], + ) + + wrapper = display_item.wrapper + item = wrapper.item + itemtype = item.get_type_id() + + # Draw our bounds if debug mode is enabled (or we're a test-item). + if display_item.debug or itemtype is ditm.ItemTypeID.TEST: + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + color=(1, 1, 0), + opacity=0.1, + position=( + our_center[0] - bounds_size[0] * 0.5, + our_center[1] - bounds_size[1] * 0.5, + ), + size=bounds_size, + transition_delay=tdelay, + ), + textures={'texture': 'white'}, + meshes={}, + highlight=highlight and display_item.highlight, + ) + ) + + # Calc our width and height based on our aspect ratio so we fit in + # the provided bounds. + if display_item.style is dui1.DisplayItemStyle.FULL: + aspect_ratio = 0.75 # Bit less tall than wide (graphic centric). + compact = False + icon = False + elif display_item.style is dui1.DisplayItemStyle.COMPACT: + aspect_ratio = 0.5 # Significantly wider (text centric) + compact = True + icon = False + elif display_item.style is dui1.DisplayItemStyle.ICON: + aspect_ratio = 1.0 # Square + compact = False + icon = True + else: + # Make sure we cover all possibilities. + assert_never(display_item.style) + + if bounds_size[0] * aspect_ratio > bounds_size[1]: + height = bounds_size[1] + width = height / aspect_ratio + else: + width = bounds_size[0] + height = width * aspect_ratio + + # Show our constrained bounds in debug mode. + if display_item.debug or itemtype is ditm.ItemTypeID.TEST: + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + color=(1, 0.5, 0), + opacity=0.2, + position=( + our_center[0] - width * 0.5, + our_center[1] - height * 0.5, + ), + size=(width, height), + transition_delay=tdelay, + ), + textures={'texture': 'white'}, + meshes={}, + highlight=highlight and display_item.highlight, + ) + ) + + img: str | None = None + img_x_offs = 0.0 + img_y_offs = 0.0 + imgsize = width * (0.5 if compact else 1.0 if icon else 0.33) + + show_text = True + text_mult = 0.006 + text: str | None = None # Uses default if None + text_x_offs = 0.0 + text_y_offs = 0.0 + text_align = 'center' + text_max_width: float | None = width * 0.9 + + if itemtype is ditm.ItemTypeID.CHEST: + from baclassic import ( + CHEST_APPEARANCE_DISPLAY_INFOS, + CHEST_APPEARANCE_DISPLAY_INFO_DEFAULT, + ) + import bacommon.classic + + assert isinstance(item, bacommon.classic.ClassicChestDisplayItem) + + img = None + show_text = False + c_info = CHEST_APPEARANCE_DISPLAY_INFOS.get( + item.appearance, CHEST_APPEARANCE_DISPLAY_INFO_DEFAULT + ) + c_size = width * (0.66 if compact else 1.05 if icon else 0.83) + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=( + our_center[0] - c_size * 0.5, + our_center[1] - c_size * 0.5, + ), + size=(c_size, c_size), + transition_delay=tdelay, + tint_color=c_info.tint, + tint2_color=c_info.tint2, + depth_range=display_item.depth_range, + ), + textures={ + 'texture': c_info.texclosed, + 'tint_texture': c_info.texclosedtint, + }, + meshes={}, + highlight=highlight and display_item.highlight, + ) + ) + elif itemtype is ditm.ItemTypeID.TEST: + assert isinstance(item, ditm.Test) + # Nothing to do here. This is just another way to enable debug + # drawing. + if icon or compact: + text_mult = 0.02 # Very large text. + + elif ( + itemtype is ditm.ItemTypeID.TOKENS + or itemtype is ditm.ItemTypeID.TICKETS + or itemtype is ditm.ItemTypeID.TICKETS_PURPLE + ): + if itemtype is ditm.ItemTypeID.TOKENS: + assert isinstance(item, ditm.Tokens) + img = 'coin' + if compact: + text = str(item.count) + elif itemtype is ditm.ItemTypeID.TICKETS: + assert isinstance(item, ditm.Tickets) + img = 'tickets' + if compact: + text = str(item.count) + elif itemtype is ditm.ItemTypeID.TICKETS_PURPLE: + assert isinstance(item, ditm.PurpleTickets) + img = 'ticketsPurple' + if compact: + text = str(item.count) + else: + assert_never(itemtype) + + if compact: + imgamt = 0.85 # How much of img dimensions we measure. + + assert text is not None + text_mult = 0.01 + strwidth = ( + width + * bui.get_string_width(text, suppress_warning=True) + * text_mult + ) + totwidth = strwidth + imgsize * imgamt + + maxwidth = width * 0.95 + if totwidth > maxwidth: + mult = maxwidth / totwidth + text_mult *= mult + strwidth *= mult + totwidth *= mult + imgsize *= mult + + text_max_width = None # We calc this fully ourself. + # Move to right and then left by half img width. + img_x_offs = totwidth * 0.5 - imgsize * imgamt * 0.5 + # Move to left and then right by half text width. + text_x_offs = totwidth * -0.5 + strwidth * 0.5 + elif icon: + img_y_offs = 0.0 + show_text = False + else: + img_y_offs = width * 0.11 + text_y_offs = width * -0.15 + elif itemtype is ditm.ItemTypeID.UNKNOWN: + assert isinstance(item, ditm.Unknown) + # Just do default text here. + if icon: + text_mult = 0.02 # Very large text. + else: + # Make sure we cover all possibilities. + assert_never(itemtype) + + if img is not None: + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.imagewidget, + position=( + our_center[0] - imgsize * 0.5 + img_x_offs, + our_center[1] - imgsize * 0.5 + img_y_offs, + ), + size=(imgsize, imgsize), + transition_delay=tdelay, + depth_range=display_item.depth_range, + ), + textures={'texture': img}, + meshes={}, + highlight=highlight and display_item.highlight, + ) + ) + if show_text: + if text is None: + subs = wrapper.description_subs + if subs is None: + subs = [] + text = bui.Lstr( + translate=('displayItemNames', wrapper.description), + subs=pairs_from_flat(subs), + ).as_json() + + out_decoration_preps.append( + DecorationPrep( + call=partial( + bui.textwidget, + position=( + our_center[0] + text_x_offs, + our_center[1] + text_y_offs, + ), + scale=width * text_mult, + maxwidth=text_max_width, + h_align=text_align, + v_align='center', + size=(0, 0), + color=( + (1, 1, 1) + if display_item.text_color is None + else display_item.text_color + ), + text=text, + flatness=1.0, + shadow=1.0, + literal=False, + transition_delay=tdelay, + depth_range=display_item.depth_range, + ), + textures={}, + meshes={}, + highlight=highlight and display_item.highlight, + ) + ) diff --git a/dist/ba_data/python/bauiv1lib/docui/v1prep/_types.py b/dist/ba_data/python/bauiv1lib/docui/v1prep/_types.py new file mode 100644 index 0000000..62d8f71 --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docui/v1prep/_types.py @@ -0,0 +1,73 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Types used in prepping v1 doc-ui. + +Prepping involves doing as much math and layout work as possible in a +pre-pass (generally run in a background thread) so that the actual calls +made to instantiate the ui are as fast and minimal as possible. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import Callable + + import bacommon.docui.v1 + import bauiv1 + + from bauiv1lib.docui._window import DocUIWindow + + +@dataclass +class DecorationPrep: + """Prep for a decoration in a v1 doc-ui""" + + call: Callable[..., bauiv1.Widget] + textures: dict[str, str] + meshes: dict[str, str] + highlight: bool + + +@dataclass +class ButtonPrep: + """Prep for a button in a v1 doc-ui""" + + buttoncall: Callable[..., bauiv1.Widget] + buttoneditcall: Callable | None + decorations: list[DecorationPrep] + textures: dict[str, str] + widgetid: str + action: bacommon.docui.v1.Action | None + + +@dataclass +class RowPrep: + """Prep for a row in a v1 doc-ui""" + + width: float + height: float + titlecalls: list[Callable[..., bauiv1.Widget]] + hscrollcall: Callable[..., bauiv1.Widget] | None + hscrolleditcall: Callable | None + hsubcall: Callable[..., bauiv1.Widget] | None + buttons: list[ButtonPrep] + simple_culling_h: float + decorations: list[DecorationPrep] + + +@dataclass +class PagePrep: + """Prep for a page in a v1 doc-ui""" + + rootcall: Callable[..., bauiv1.Widget] | None + rows: list[RowPrep] + width: float + height: float + simple_culling_v: float + center_vertically: bool + title: str + title_is_lstr: bool + root_post_calls: list[Callable[[bauiv1.Widget], None]] diff --git a/dist/ba_data/python/bauiv1lib/docuitest.py b/dist/ba_data/python/bauiv1lib/docuitest.py new file mode 100644 index 0000000..6e3430c --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/docuitest.py @@ -0,0 +1,1092 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Examples/tests for using DocUI to build UIs.""" + +# pylint: disable=too-many-lines +from __future__ import annotations + +import time +import copy +from typing import TYPE_CHECKING, override + +from efro.error import CleanError +import bauiv1 as bui + +from bauiv1lib.docui import DocUIWindow, DocUIController + +if TYPE_CHECKING: + from bacommon.docui import DocUIRequest, DocUIResponse + import bacommon.docui.v1 + + from bauiv1lib.docui import DocUILocalAction + + +def show_test_doc_ui_window() -> None: + """Bust out a doc-ui window.""" + import bacommon.docui.v1 as dui1 + + # Pop up an auxiliary window wherever we are in the nav stack. + bui.app.ui_v1.auxiliary_window_activate( + win_type=DocUIWindow, + win_create_call=bui.CallStrict( + TestDocUIController().create_window, dui1.Request('/') + ), + win_extra_type_id=TestDocUIController.get_window_extra_type_id(), + ) + + +class TestDocUIController(DocUIController): + """Provides various tests/demonstrations of docui functionality.""" + + @override + def fulfill_request(self, request: DocUIRequest) -> DocUIResponse: + """Fulfill a request. + + Will be called in a background thread. + """ + # pylint: disable=too-many-return-statements + + import bacommon.docui.v1 as dui1 + + # We currently support v1 requests only. + if not isinstance(request, dui1.Request): + raise CleanError('Invalid request version.') + + # Handle some pages purely locally. + if request.path == '/': + return _test_page_root(request) + if request.path == '/test2': + return _test_page_2(request) + if request.path == '/slow': + return _test_page_long(request) + if request.path == '/timedactions': + return _test_page_timed_actions(request) + if request.path == '/displayitems': + return _test_page_display_items(request) + if request.path == '/emptypage': + return _test_page_empty(request) + if request.path == '/boundstests': + return _test_bounds(request) + + # Ship '/webtest/*' off to some webserver to handle. + if request.path.startswith('/webtest/'): + return self.fulfill_request_web( + request, 'https://www.ballistica.net/docuitest' + ) + + # Ship '/cloudmsgtest/*' through our cloud connection to handle. + if request.path.startswith('/cloudmsgtest/'): + return self.fulfill_request_cloud(request, 'test') + + raise CleanError('Invalid request path.') + + @override + def local_action(self, action: DocUILocalAction) -> None: + bui.screenmessage( + f'Would do {action.name!r} with args {action.args!r}.' + ) + + +def _test_page_long( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + """Testing a page that takes a bit of time to load.""" + import bacommon.docui.v1 as dui1 + + del request # Unused. + + # Simulate a slow connection or whatnot. + time.sleep(3.0) + + return dui1.Response( + page=dui1.Page( + title='Test', + center_vertically=True, + rows=[ + dui1.ButtonRow( + title='That took a while', + center_title=True, + center_content=True, + buttons=[ + dui1.Button( + 'Sure Did', + size=(120, 80), + action=dui1.Browse(dui1.Request('/')), + ), + ], + ), + ], + ) + ) + + +def _test_page_timed_actions( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + """Testing a page that takes a bit of time to load.""" + import bacommon.docui.v1 as dui1 + + val = request.args.get('val') + if not isinstance(val, int): + val = 5 + + return dui1.Response( + page=dui1.Page( + title='Test', + center_vertically=True, + rows=[ + dui1.ButtonRow( + title=f'Hello there {val}', + subtitle='Each change here is a new request/response.', + center_title=True, + center_content=True, + buttons=[ + dui1.Button( + 'Done', + size=(120, 80), + action=dui1.Local(close_window=True), + default=True, + ), + ], + ), + ], + ), + # Refresh this page with a countdown until we hit zero and then + # close the window. + timed_action=( + dui1.Replace(dui1.Request('/timedactions', args={'val': val - 1})) + if (val - 1) > 0 + else dui1.Local(close_window=True) + ), + timed_action_delay=1.0, + ) + + +def _test_page_effects() -> bacommon.docui.v1.Page: + """Testing effects after a page load.""" + import bacommon.docui.v1 as dui1 + + return dui1.Page( + title='Effects', + center_vertically=True, + rows=[ + dui1.ButtonRow( + title='Have some lovely effects', + center_title=True, + center_content=True, + buttons=[ + dui1.Button( + 'Nice!', + size=(120, 80), + action=dui1.Local(close_window=True), + ), + ], + ), + ], + ) + + +def _test_page_2( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + """More testing.""" + import bacommon.docui.v1 as dui1 + + del request # Unused. + + return dui1.Response( + page=dui1.Page( + title='Test 2', + rows=[ + dui1.ButtonRow( + title='More Tests', + buttons=[ + dui1.Button( + 'Browse', + size=(120, 80), + action=dui1.Browse(dui1.Request('/')), + ), + dui1.Button( + 'Replace', + size=(120, 80), + action=dui1.Replace(dui1.Request('/')), + ), + dui1.Button( + 'Close', + size=(120, 80), + action=dui1.Local(close_window=True), + selected=True, # Testing this + ), + ], + ), + ], + ) + ) + + +def _test_page_root( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + """Return test page.""" + + import bacommon.clienteffect as clfx + import bacommon.docui.v1 as dui1 + + # Show some specific debug bits if they ask us to. + debug = bool(request.args.get('debug', False)) + + response = dui1.Response( + page=dui1.Page( + title='Test Root', + rows=[ + dui1.ButtonRow( + debug=debug, + header_height=100, + header_decorations_left=[ + dui1.Text( + 'HeaderLeft', + position=(0, 10 + 20), + color=(1, 1, 1, 0.3), + size=(150, 30), + h_align=dui1.HAlign.LEFT, + debug=debug, + ), + ], + header_decorations_center=[ + dui1.Text( + 'Hello From DocUI!', + position=(0, 10 + 20), + size=(300, 30), + debug=debug, + ), + dui1.Text( + ( + 'Use this as reference for building' + ' UIs with DocUI.' + ' Its code lives at bauiv1lib.docuitest' + ), + scale=0.5, + position=(0, -18 + 20), + size=(600, 23), + debug=debug, + ), + dui1.Image( + 'nub', position=(0, -58 + 20), size=(60, 60) + ), + ], + header_decorations_right=[ + dui1.Text( + 'HeaderRight', + position=(0, 10 + 20), + color=(1, 1, 1, 0.3), + size=(150, 30), + h_align=dui1.HAlign.RIGHT, + debug=debug, + ), + ], + title='Some Tests', + buttons=[ + dui1.Button( + 'Browse', + size=(120, 80), + action=dui1.Browse(dui1.Request('/test2')), + ), + dui1.Button( + 'Replace', + size=(120, 80), + action=dui1.Replace(dui1.Request('/test2')), + ), + dui1.Button( + 'Close', + size=(120, 80), + action=dui1.Local(close_window=True), + ), + dui1.Button( + 'Invalid\nRequest', + size=(120, 80), + action=dui1.Browse(dui1.Request('/invalidrequest')), + ), + dui1.Button( + 'Immediate\nClientEffects', + size=(120, 80), + action=dui1.Local( + immediate_client_effects=[ + clfx.ScreenMessage( + 'Hello From Immediate Client Effects', + color=(0, 1, 0), + ), + clfx.PlaySound(clfx.Sound.CASH_REGISTER), + clfx.Delay(1.0), + clfx.ScreenMessage( + '{"r":"successText"}', + is_lstr=True, + color=(0, 1, 0), + ), + clfx.PlaySound(clfx.Sound.CASH_REGISTER), + ] + ), + ), + dui1.Button( + 'Response\nClientEffects', + size=(120, 80), + action=dui1.Browse( + dui1.Request('/', args={'test_effects': True}) + ), + ), + dui1.Button( + 'Immediate\nLocalAction', + size=(120, 80), + action=dui1.Local( + immediate_local_action='testaction', + immediate_local_action_args={'testparam': 123}, + ), + ), + dui1.Button( + 'Response\nLocalAction', + size=(120, 80), + action=dui1.Browse( + dui1.Request('/', args={'test_action': True}) + ), + ), + ], + ), + dui1.ButtonRow( + title='A Few More Tests', + buttons=[ + dui1.Button( + 'Hide\nDebug' if debug else 'Show\nDebug', + size=(120, 80), + action=dui1.Replace( + dui1.Request('/', args={'debug': not debug}) + ), + ), + dui1.Button( + 'Slow\nBrowse', + size=(120, 80), + action=dui1.Browse(dui1.Request('/slow')), + ), + dui1.Button( + 'Slow\nReplace', + size=(120, 80), + action=dui1.Replace(dui1.Request('/slow')), + ), + dui1.Button( + 'Timed\nActions', + size=(120, 80), + action=dui1.Browse(dui1.Request('/timedactions')), + ), + dui1.Button( + 'Web\nGET', + size=(120, 80), + action=dui1.Browse(dui1.Request('/webtest/get')), + ), + dui1.Button( + 'Web\nPOST', + size=(120, 80), + action=dui1.Browse( + dui1.Request( + '/webtest/post', + method=dui1.RequestMethod.POST, + ) + ), + ), + dui1.Button( + 'DisplayItems', + size=(120, 80), + action=dui1.Browse(dui1.Request('/displayitems')), + ), + dui1.Button( + 'Empty\nPage', + size=(120, 80), + action=dui1.Browse(dui1.Request('/emptypage')), + ), + ], + ), + dui1.ButtonRow( + title='Even More Tests', + buttons=[ + dui1.Button( + 'Cloud-Msg\nGET', + size=(120, 80), + action=dui1.Browse( + dui1.Request('/cloudmsgtest/get') + ), + ), + dui1.Button( + 'Cloud-Msg\nPOST', + size=(120, 80), + action=dui1.Browse( + dui1.Request( + '/cloudmsgtest/post', + method=dui1.RequestMethod.POST, + ) + ), + ), + dui1.Button( + 'Bounds\nTests', + size=(120, 80), + action=dui1.Browse(dui1.Request('/boundstests')), + ), + ], + ), + dui1.ButtonRow(title='Empty Row', buttons=[]), + dui1.ButtonRow( + title='Layout Tests', + debug=debug, + padding_left=5.0, + buttons=[ + dui1.Button( + label='Test', + size=(180, 200), + decorations=[ + dui1.Image( + 'powerupPunch', + position=(-70, 0), + size=(40, 40), + h_align=dui1.HAlign.LEFT, + ), + dui1.Image( + 'powerupSpeed', + position=(0, 75), + size=(35, 35), + v_align=dui1.VAlign.TOP, + ), + dui1.Text( + 'TL', + position=(-70, 75), + size=(50, 50), + h_align=dui1.HAlign.LEFT, + v_align=dui1.VAlign.TOP, + debug=debug, + ), + dui1.Text( + 'TR', + position=(70, 75), + size=(50, 50), + h_align=dui1.HAlign.RIGHT, + v_align=dui1.VAlign.TOP, + debug=debug, + ), + dui1.Text( + 'BL', + position=(-70, -75), + size=(50, 50), + h_align=dui1.HAlign.LEFT, + v_align=dui1.VAlign.BOTTOM, + debug=debug, + ), + dui1.Text( + 'BR', + position=(70, -75), + size=(50, 50), + h_align=dui1.HAlign.RIGHT, + v_align=dui1.VAlign.BOTTOM, + debug=debug, + ), + ], + ), + dui1.Button( + label='Test2', + size=(100, 100), + color=(1, 0, 0, 1), + label_color=(1, 1, 1, 1), + padding_right=4, + ), + # Should look like the first button but + # scaled down. + dui1.Button( + label='Test', + size=(180, 200), + scale=0.6, + padding_bottom=30, # Should nudge us up. + debug=debug, # Show bounds. + decorations=[ + dui1.Image( + 'powerupPunch', + position=(-70, 0), + size=(40, 40), + h_align=dui1.HAlign.LEFT, + ), + dui1.Image( + 'powerupSpeed', + position=(0, 75), + size=(35, 35), + v_align=dui1.VAlign.TOP, + ), + dui1.Text( + 'TL', + position=(-70, 75), + size=(50, 50), + h_align=dui1.HAlign.LEFT, + v_align=dui1.VAlign.TOP, + debug=debug, + ), + dui1.Text( + 'TR', + position=(70, 75), + size=(50, 50), + h_align=dui1.HAlign.RIGHT, + v_align=dui1.VAlign.TOP, + debug=debug, + ), + dui1.Text( + 'BL', + position=(-70, -75), + size=(50, 50), + h_align=dui1.HAlign.LEFT, + v_align=dui1.VAlign.BOTTOM, + debug=debug, + ), + dui1.Text( + 'BR', + position=(70, -75), + size=(50, 50), + h_align=dui1.HAlign.RIGHT, + v_align=dui1.VAlign.BOTTOM, + debug=debug, + ), + ], + ), + # Testing custom button images and opacity. + dui1.Button( + label='Test3', + texture='buttonSquareWide', + padding_left=10.0, + padding_right=10.0, + color=(1, 1, 1, 0.3), + size=(200, 100), + ), + # Testing image drawing vs bounds + dui1.Button( + label='BoundsTest', + texture='white', + color=(1, 1, 1, 0.3), + size=(150, 100), + debug=debug, + ), + ], + ), + dui1.ButtonRow( + title='Long Row Test', + subtitle='Look - a subtitle!', + buttons=[ + dui1.Button( + size=(150, 100), + decorations=[ + dui1.Text( + 'MaxWidthTest', + position=(0, 25), + size=(150 * 0.8, 32.0), + flatness=1.0, + shadow=0.0, + debug=debug, + ), + dui1.Text( + 'MaxHeightTest\nSecondLine', + position=(0, -20), + size=(150 * 0.8, 40), + flatness=1.0, + shadow=0.0, + debug=debug, + ), + ], + ), + dui1.Button( + size=(150, 100), + decorations=[ + dui1.Image( + 'zoeIcon', + position=(0, 0), + size=(70, 70), + tint_texture='zoeIconColorMask', + tint_color=(1, 0, 0), + tint2_color=(0, 1, 0), + mask_texture='characterIconMask', + ), + ], + ), + dui1.Button( + size=(150, 100), + decorations=[ + dui1.Image( + 'bridgitPreview', + position=(0, 10), + size=(120, 60), + mask_texture='mapPreviewMask', + mesh_opaque='level_select_button_opaque', + mesh_transparent=( + 'level_select_button_transparent' + ), + ), + ], + ), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button( + 'foo', + size=(150, 100), + scale=0.4, + padding_left=100, + padding_right=200, + ), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + dui1.Button(size=(150, 100)), + ], + ), + dui1.ButtonRow( + spacing_top=-15, + subtitle='Subtitle only!', + buttons=[ + dui1.Button(size=(200, 120)), + ], + ), + dui1.ButtonRow( + buttons=[ + dui1.Button( + 'Row-With-No-Title Test', + size=(300, 80), + style=dui1.ButtonStyle.MEDIUM, + color=(0.8, 0.8, 0.8, 1), + icon='buttonPunch', + icon_color=(0.5, 0.3, 1.0, 1.0), + icon_scale=1.2, + ), + ], + ), + dui1.ButtonRow( + title='Centered Content / Faded Title', + title_color=(0.6, 0.6, 1.0, 0.3), + title_flatness=1.0, + title_shadow=1.0, + subtitle='Testing Centered Title/Content', + subtitle_color=(1.0, 0.5, 1.0, 0.5), + subtitle_flatness=1.0, + subtitle_shadow=0.0, + center_content=True, + center_title=True, + buttons=[ + dui1.Button( + 'Hello There!', + size=(200, 120), + color=(0.7, 0.7, 0.9, 1), + ), + ], + ), + ], + ), + ) + + # Include some client effects if they ask. + if request.args.get('test_effects', False): + response.client_effects = [ + clfx.ScreenMessage( + 'Hello From Response Client Effects', color=(0, 1, 0) + ), + clfx.PlaySound(clfx.Sound.CASH_REGISTER), + clfx.Delay(1.0), + clfx.ScreenMessage( + '{"r":"successText"}', is_lstr=True, color=(0, 1, 0) + ), + clfx.PlaySound(clfx.Sound.CASH_REGISTER), + ] + + # Include a local-action if they ask. + if request.args.get('test_action', False): + response.local_action = 'testaction' + response.local_action_args = {'testparam': 234} + + return response + + +def _test_page_empty( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + import bacommon.docui.v1 as dui1 + + del request # Unused. + + return dui1.Response(page=dui1.Page(title='EmptyPage', rows=[])) + + +def _test_page_display_items( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + """Testing display-items.""" + from bacommon.classic import ClassicChestAppearance, ClassicChestDisplayItem + import bacommon.docui.v1 as dui1 + import bacommon.displayitem as ditm + + # Show some specific debug bits if they ask us to. + debug = bool(request.args.get('debug', False)) + + def _make_test_button( + scale: float, + wrapper: ditm.Wrapper, + ) -> dui1.Button: + + # See how this looks when unrecognized (relying on wrapper info + # only). + uwrapper = copy.deepcopy(wrapper) + uwrapper.item = ditm.Unknown() + + return dui1.Button( + size=(300, 400), + scale=scale, + decorations=[ + dui1.DisplayItem( + wrapper=wrapper, + style=dui1.DisplayItemStyle.FULL, + position=(-62, 100), + size=(120, 120), + debug=debug, + ), + dui1.DisplayItem( + wrapper=uwrapper, + style=dui1.DisplayItemStyle.FULL, + position=(62, 100), + size=(120, 120), + debug=debug, + ), + dui1.DisplayItem( + wrapper=wrapper, + style=dui1.DisplayItemStyle.COMPACT, + position=(-55, -20), + size=(80, 80), + debug=debug, + ), + dui1.DisplayItem( + wrapper=uwrapper, + style=dui1.DisplayItemStyle.COMPACT, + position=(55, -20), + size=(80, 80), + debug=debug, + ), + dui1.DisplayItem( + wrapper=wrapper, + style=dui1.DisplayItemStyle.ICON, + position=(-55, -120), + size=(100, 80), + debug=debug, + ), + dui1.DisplayItem( + wrapper=uwrapper, + style=dui1.DisplayItemStyle.ICON, + position=(55, -120), + size=(100, 80), + debug=debug, + ), + ], + ) + + return dui1.Response( + page=dui1.Page( + padding_left=20, + padding_right=20, + title='DisplayItems', + rows=[ + dui1.ButtonRow( + debug=debug, + padding_left=-10, + title='Display Item Tests', + subtitle=( + 'top=FULL, center=COMPACT, bottom=ICON;' + ' left=regular, right=unknown' + ), + buttons=[ + _make_test_button( + 1.0, + ditm.Wrapper.for_item(ditm.Tickets(count=213)), + ), + _make_test_button( + 0.47, + ditm.Wrapper.for_item(ditm.Tickets(count=213)), + ), + _make_test_button( + 1.0, + ditm.Wrapper.for_item( + ClassicChestDisplayItem( + appearance=ClassicChestAppearance.L3 + ) + ), + ), + _make_test_button( + 1.0, + ditm.Wrapper.for_item(ditm.Tokens(count=3)), + ), + _make_test_button( + 1.0, + ditm.Wrapper.for_item(ditm.Tokens(count=1414287)), + ), + _make_test_button( + 1.0, + ditm.Wrapper.for_item(ditm.Test()), + ), + ], + ), + dui1.ButtonRow( + buttons=[ + dui1.Button( + 'Hide Debug' if debug else 'Show Debug', + style=dui1.ButtonStyle.MEDIUM, + size=(240, 60), + color=(0.6, 0.4, 0.8, 1.0), + action=dui1.Replace( + dui1.Request( + request.path, args={'debug': not debug} + ) + ), + ) + ], + ), + ], + ) + ) + + +def _test_bounds( + request: bacommon.docui.v1.Request, +) -> bacommon.docui.v1.Response: + import bacommon.docui.v1 as dui1 + + del request # Unused. + + def _nm(style: dui1.ButtonStyle) -> str: + return f'{type(style).__name__}.{style.name}' + + return dui1.Response( + page=dui1.Page( + title='BoundsTests', + rows=[ + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.SQUARE), + buttons=[ + dui1.Button('Hello', size=(300, 300), debug=True), + dui1.Button('Hello', size=(200, 200), debug=True), + dui1.Button('Hello', size=(100, 100), debug=True), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.SQUARE_WIDE), + buttons=[ + dui1.Button( + 'Hello', + size=(400, 200), + style=dui1.ButtonStyle.SQUARE_WIDE, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 250), + style=dui1.ButtonStyle.SQUARE_WIDE, + debug=True, + ), + dui1.Button( + 'Hello', + size=(60, 100), + style=dui1.ButtonStyle.SQUARE_WIDE, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title='(background texture)', + buttons=[ + dui1.Button( + 'Hello', + size=(300, 300), + texture='white', + color=(1, 0, 0, 0.3), + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 200), + texture='white', + color=(1, 0, 0, 0.3), + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 100), + texture='white', + color=(1, 0, 0, 0.3), + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.TAB), + buttons=[ + dui1.Button( + 'Hello', + size=(400, 100), + style=dui1.ButtonStyle.TAB, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.TAB, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.TAB, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.LARGER), + buttons=[ + dui1.Button( + 'Hello', + size=(500, 100), + style=dui1.ButtonStyle.LARGER, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.LARGER, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.LARGER, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.LARGE), + buttons=[ + dui1.Button( + 'Hello', + size=(400, 100), + style=dui1.ButtonStyle.LARGE, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.LARGE, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.LARGE, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.MEDIUM), + buttons=[ + dui1.Button( + 'Hello', + size=(300, 100), + style=dui1.ButtonStyle.MEDIUM, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.MEDIUM, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.MEDIUM, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.SMALL), + buttons=[ + dui1.Button( + 'Hello', + size=(200, 100), + style=dui1.ButtonStyle.SMALL, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.SMALL, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.SMALL, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.BACK), + buttons=[ + dui1.Button( + 'Hello', + size=(200, 100), + style=dui1.ButtonStyle.BACK, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.BACK, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.BACK, + debug=True, + ), + ], + ), + dui1.ButtonRow( + title=_nm(dui1.ButtonStyle.BACK_SMALL), + buttons=[ + dui1.Button( + 'Hello', + size=(200, 100), + style=dui1.ButtonStyle.BACK_SMALL, + debug=True, + ), + dui1.Button( + 'Hello', + size=(200, 50), + style=dui1.ButtonStyle.BACK_SMALL, + debug=True, + ), + dui1.Button( + 'Hello', + size=(100, 60), + style=dui1.ButtonStyle.BACK_SMALL, + debug=True, + ), + ], + ), + ], + ) + ) diff --git a/dist/ba_data/python/bauiv1lib/fileselector.py b/dist/ba_data/python/bauiv1lib/fileselector.py index e5f1588..161140c 100644 --- a/dist/ba_data/python/bauiv1lib/fileselector.py +++ b/dist/ba_data/python/bauiv1lib/fileselector.py @@ -249,7 +249,7 @@ class FileSelectorWindow(bui.MainWindow): if duration < min_time: time.sleep(min_time - duration) bui.pushcall( - bui.Call(self._callback, files, None), + bui.CallStrict(self._callback, files, None), from_other_thread=True, ) except Exception as exc: @@ -258,7 +258,7 @@ class FileSelectorWindow(bui.MainWindow): logging.exception('Error in fileselector refresh thread.') nofiles: list[str] = [] bui.pushcall( - bui.Call(self._callback, nofiles, str(exc)), + bui.CallStrict(self._callback, nofiles, str(exc)), from_other_thread=True, ) @@ -431,7 +431,9 @@ class FileSelectorWindow(bui.MainWindow): root_selectable=True, background=False, click_activate=True, - on_activate_call=bui.Call(self._on_entry_activated, entry), + on_activate_call=bui.CallStrict( + self._on_entry_activated, entry + ), ) if num == 0: bui.widget(edit=cnt, up_widget=self._back_button) diff --git a/dist/ba_data/python/bauiv1lib/gather/__init__.py b/dist/ba_data/python/bauiv1lib/gather/__init__.py index fe25edb..3b0ed5e 100644 --- a/dist/ba_data/python/bauiv1lib/gather/__init__.py +++ b/dist/ba_data/python/bauiv1lib/gather/__init__.py @@ -2,7 +2,6 @@ # """Provides UI for inviting/joining friends.""" - from bauiv1lib.gather._gather import GatherTab, GatherWindow __all__ = ['GatherTab', 'GatherWindow'] diff --git a/dist/ba_data/python/bauiv1lib/gather/_gather.py b/dist/ba_data/python/bauiv1lib/gather/_gather.py index 43843de..5d07195 100644 --- a/dist/ba_data/python/bauiv1lib/gather/_gather.py +++ b/dist/ba_data/python/bauiv1lib/gather/_gather.py @@ -212,7 +212,7 @@ class GatherWindow(bui.MainWindow): self._scroll_left + tab_inset, self._scroll_bottom + self._scroll_height - 4.0, ), - on_select_call=bui.WeakCall(self._set_tab), + on_select_call=bui.WeakCallPartial(self._set_tab), ) # Now instantiate handlers for these tabs. diff --git a/dist/ba_data/python/bauiv1lib/gather/abouttab.py b/dist/ba_data/python/bauiv1lib/gather/abouttab.py index bd5442d..55ab7fc 100644 --- a/dist/ba_data/python/bauiv1lib/gather/abouttab.py +++ b/dist/ba_data/python/bauiv1lib/gather/abouttab.py @@ -160,7 +160,7 @@ class AboutGatherTab(GatherTab): fallback_resource='gatherWindow.getFriendInviteCodeText', ), autoselect=True, - on_activate_call=bui.WeakCall(self._invite_to_try_press), + on_activate_call=bui.WeakCallStrict(self._invite_to_try_press), up_widget=tab_button, show_buffer_top=500, ) @@ -190,7 +190,9 @@ class AboutGatherTab(GatherTab): textcolor=(0.6, 0.6, 1), label=bui.Lstr(resource='discordJoinText'), autoselect=True, - on_activate_call=bui.WeakCall(self._join_the_discord_press), + on_activate_call=bui.WeakCallStrict( + self._join_the_discord_press + ), up_widget=( invite_button if invite_button is not None else tab_button ), diff --git a/dist/ba_data/python/bauiv1lib/gather/manualtab.py b/dist/ba_data/python/bauiv1lib/gather/manualtab.py index 5b38a89..cb24238 100644 --- a/dist/ba_data/python/bauiv1lib/gather/manualtab.py +++ b/dist/ba_data/python/bauiv1lib/gather/manualtab.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Defines the manual tab in the gather UI.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -10,11 +11,13 @@ from enum import Enum from threading import Thread from dataclasses import dataclass from typing import TYPE_CHECKING, cast, override -from bauiv1lib.gather import GatherTab +from bacommon.analytics import ClassicAnalyticsEvent import bauiv1 as bui import bascenev1 as bs +from bauiv1lib.gather import GatherTab + if TYPE_CHECKING: from typing import Any, Callable @@ -323,7 +326,7 @@ class ManualGatherTab(GatherTab): label=bui.Lstr(resource='gatherWindow.' 'manualConnectText'), position=(c_width * 0.5 - 300, v), autoselect=True, - on_activate_call=bui.Call(self._connect, txt, txt2), + on_activate_call=bui.CallStrict(self._connect, txt, txt2), ) savebutton = bui.buttonwidget( parent=self._container, @@ -332,7 +335,7 @@ class ManualGatherTab(GatherTab): label=bui.Lstr(resource='gatherWindow.favoritesSaveText'), position=(c_width * 0.5 - 240 + 490 - 200, v), autoselect=True, - on_activate_call=bui.Call(self._save_server, txt, txt2), + on_activate_call=bui.CallStrict(self._save_server, txt, txt2), ) bui.widget(edit=btn, right_widget=savebutton) bui.widget(edit=savebutton, left_widget=btn, up_widget=txt2) @@ -353,7 +356,7 @@ class ManualGatherTab(GatherTab): color=(0.5, 0.9, 0.5), scale=0.8, selectable=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._on_show_my_address_button_press, v, self._container, @@ -516,7 +519,7 @@ class ManualGatherTab(GatherTab): _HostLookupThread( name=config['addr'], port=config['port'], - call=bui.WeakCall(self._host_lookup_result), + call=bui.WeakCallPartial(self._host_lookup_result), ).start() def _on_favorites_edit_press(self) -> None: @@ -637,7 +640,7 @@ class ManualGatherTab(GatherTab): cbtn = bui.buttonwidget( parent=cnt, label=bui.Lstr(resource='cancelText'), - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( lambda c: bui.containerwidget(edit=c, transition='out_scale'), cnt, ), @@ -650,7 +653,7 @@ class ManualGatherTab(GatherTab): label=bui.Lstr(resource='saveText'), size=(180, 60), position=(c_width - 230, 30), - on_activate_call=bui.Call(self._edit_saved_party), + on_activate_call=bui.CallStrict(self._edit_saved_party), autoselect=True, ) bui.widget(edit=cbtn, right_widget=okb) @@ -754,7 +757,7 @@ class ManualGatherTab(GatherTab): selectable=True, color=(1.0, 1, 0.4), always_highlight=True, - on_select_call=bui.Call(self._on_favorite_select, server), + on_select_call=bui.CallStrict(self._on_favorite_select, server), on_activate_call=self._favorites_connect_button.activate, text=( config['Saved Servers'][server]['name'] @@ -803,6 +806,13 @@ class ManualGatherTab(GatherTab): def _connect( self, textwidget: bui.Widget, port_textwidget: bui.Widget ) -> None: + + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.JOIN_PARTY_BY_ADDRESS + ) + ) + addr = cast(str, bui.textwidget(query=textwidget)) if addr == '': bui.screenmessage( @@ -824,7 +834,9 @@ class ManualGatherTab(GatherTab): return _HostLookupThread( - name=addr, port=port, call=bui.WeakCall(self._host_lookup_result) + name=addr, + port=port, + call=bui.WeakCallPartial(self._host_lookup_result), ).start() def _save_server( @@ -906,7 +918,7 @@ class ManualGatherTab(GatherTab): val = sock.getsockname()[0] sock.close() bui.pushcall( - bui.Call( + bui.CallStrict( _safe_set_text, self._checking_state_text, val, @@ -918,7 +930,7 @@ class ManualGatherTab(GatherTab): if is_udp_communication_error(exc): bui.pushcall( - bui.Call( + bui.CallStrict( _safe_set_text, self._checking_state_text, bui.Lstr(resource='gatherWindow.' 'noConnectionText'), @@ -928,7 +940,7 @@ class ManualGatherTab(GatherTab): ) else: bui.pushcall( - bui.Call( + bui.CallStrict( _safe_set_text, self._checking_state_text, bui.Lstr( @@ -1053,7 +1065,7 @@ class ManualGatherTab(GatherTab): self._access_check_count = 0 # Cap our refreshes eventually. self._access_check_timer = bui.AppTimer( 10.0, - bui.WeakCall( + bui.WeakCallStrict( self._access_check_update, t_addr, t_accessible, @@ -1086,7 +1098,7 @@ class ManualGatherTab(GatherTab): bui.app.classic.master_server_v1_get( 'bsAccessCheck', {'b': bui.app.env.engine_build_number}, - callback=bui.WeakCall(self._on_accessible_response), + callback=bui.WeakCallPartial(self._on_accessible_response), ) def _on_accessible_response(self, data: dict[str, Any] | None) -> None: diff --git a/dist/ba_data/python/bauiv1lib/gather/nearbytab.py b/dist/ba_data/python/bauiv1lib/gather/nearbytab.py index 013e2a2..36d964f 100644 --- a/dist/ba_data/python/bauiv1lib/gather/nearbytab.py +++ b/dist/ba_data/python/bauiv1lib/gather/nearbytab.py @@ -7,6 +7,7 @@ from __future__ import annotations import weakref from typing import TYPE_CHECKING, override +from bacommon.analytics import ClassicAnalyticsEvent import bauiv1 as bui import bascenev1 as bs @@ -46,12 +47,12 @@ class NetScanner: self._last_selected_host: dict[str, Any] | None = None self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self.update), repeat=True + 1.0, bui.WeakCallStrict(self.update), repeat=True ) # Go ahead and run a few *almost* immediately so we don't # have to wait a second. self.update() - bui.apptimer(0.25, bui.WeakCall(self.update)) + bui.apptimer(0.25, bui.WeakCallStrict(self.update)) def __del__(self) -> None: bs.end_host_scanning() @@ -61,6 +62,12 @@ class NetScanner: def _on_activate(self, host: dict[str, Any]) -> None: + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.JOIN_NEARBY_PARTY + ) + ) + # Store UI location to return to when done. if bs.app.classic is not None: bs.app.classic.save_ui_state() @@ -90,8 +97,8 @@ class NetScanner: size=(self._width / t_scale, 30), selectable=True, color=(1, 1, 1), - on_select_call=bui.Call(self._on_select, host), - on_activate_call=bui.Call(self._on_activate, host), + on_select_call=bui.CallStrict(self._on_select, host), + on_activate_call=bui.CallStrict(self._on_activate, host), click_activate=True, text=host['display_string'], h_align='left', diff --git a/dist/ba_data/python/bauiv1lib/gather/privatetab.py b/dist/ba_data/python/bauiv1lib/gather/privatetab.py index 6b4bf9f..8ec6a23 100644 --- a/dist/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/dist/ba_data/python/bauiv1lib/gather/privatetab.py @@ -15,6 +15,7 @@ from typing import TYPE_CHECKING, cast, override from efro.error import CommunicationError from efro.dataclassio import dataclass_from_dict, dataclass_to_dict +from bacommon.analytics import ClassicAnalyticsEvent import bacommon.cloud from bacommon.net import ( PrivateHostingState, @@ -63,7 +64,7 @@ class PrivateGatherTab(GatherTab): self._state: State = State() self._last_datacode_refresh_time: float | None = None self._hostingstate = PrivateHostingState() - self._v2state: bacommon.bs.PrivatePartyResponse | None = None + self._v2state: bacommon.classic.PrivatePartyResponse | None = None self._join_sub_tab_text: bui.Widget | None = None self._host_sub_tab_text: bui.Widget | None = None self._update_timer: bui.AppTimer | None = None @@ -165,7 +166,7 @@ class PrivateGatherTab(GatherTab): ) self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) # Prevent taking any action until we've updated our state. @@ -322,7 +323,7 @@ class PrivateGatherTab(GatherTab): 'type': 'PRIVATE_PARTY_QUERY', 'expire_time': time.time() + 20, }, - callback=bui.WeakCall( + callback=bui.WeakCallPartial( self._idle_hosting_state_response ), ) @@ -341,7 +342,7 @@ class PrivateGatherTab(GatherTab): if plus.accounts.primary is not None: with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.PrivatePartyMessage( + bacommon.classic.PrivatePartyMessage( need_datacode=( self._last_datacode_refresh_time is None or time.monotonic() @@ -349,7 +350,7 @@ class PrivateGatherTab(GatherTab): > 30.0 ) ), - on_response=bui.WeakCall( + on_response=bui.WeakCallPartial( self._on_private_party_query_response ), ) @@ -357,7 +358,7 @@ class PrivateGatherTab(GatherTab): self._last_v2_state_query_time = now def _on_private_party_query_response( - self, response: bacommon.bs.PrivatePartyResponse | Exception + self, response: bacommon.classic.PrivatePartyResponse | Exception ) -> None: if isinstance(response, Exception): self._debug_server_comm('got pp v2 state response (err)') @@ -948,6 +949,13 @@ class PrivateGatherTab(GatherTab): ) def _connect_to_party_code(self, code: str) -> None: + + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.JOIN_PRIVATE_PARTY + ) + ) + # Ignore attempted followup sends for a few seconds (this will # reset if we get a response). plus = bui.app.plus @@ -971,7 +979,7 @@ class PrivateGatherTab(GatherTab): 'expire_time': time.time() + 20, 'code': code, }, - callback=bui.WeakCall(self._connect_response), + callback=bui.WeakCallPartial(self._connect_response), ) plus.run_v1_account_transactions() @@ -1029,7 +1037,7 @@ class PrivateGatherTab(GatherTab): 'expire_time': time.time() + 20, 'datacode': self._v2state.datacode, }, - callback=bui.WeakCall(self._hosting_state_response), + callback=bui.WeakCallPartial(self._hosting_state_response), ) plus.run_v1_account_transactions() @@ -1040,7 +1048,7 @@ class PrivateGatherTab(GatherTab): 'type': 'PRIVATE_PARTY_STOP', 'expire_time': time.time() + 20, }, - callback=bui.WeakCall(self._hosting_state_response), + callback=bui.WeakCallPartial(self._hosting_state_response), ) plus.run_v1_account_transactions() bui.getsound('click01').play() diff --git a/dist/ba_data/python/bauiv1lib/gather/publictab.py b/dist/ba_data/python/bauiv1lib/gather/publictab.py index 8aa82bf..ee43692 100644 --- a/dist/ba_data/python/bauiv1lib/gather/publictab.py +++ b/dist/ba_data/python/bauiv1lib/gather/publictab.py @@ -12,6 +12,7 @@ from enum import Enum from dataclasses import dataclass from typing import TYPE_CHECKING, cast, override +from bacommon.analytics import ClassicAnalyticsEvent from bauiv1lib.gather import GatherTab import bauiv1 as bui import bascenev1 as bs @@ -117,11 +118,13 @@ class UIRow: size=(sub_scroll_width * 0.46, 20), position=(0 + hpos, 4 + vpos), selectable=True, - on_select_call=bui.WeakCall( + on_select_call=bui.WeakCallStrict( tab.set_public_party_selection, Selection(party.get_key(), SelectionComponent.NAME), ), - on_activate_call=bui.WeakCall(tab.on_public_party_activate, party), + on_activate_call=bui.WeakCallStrict( + tab.on_public_party_activate, party + ), click_activate=True, maxwidth=sub_scroll_width * 0.45, corner_scale=1.4, @@ -160,8 +163,8 @@ class UIRow: label=bui.Lstr(resource='statsText'), parent=columnwidget, autoselect=True, - on_activate_call=bui.Call(bui.open_url, url), - on_select_call=bui.WeakCall( + on_activate_call=bui.CallStrict(bui.open_url, url), + on_select_call=bui.WeakCallStrict( tab.set_public_party_selection, Selection(party.get_key(), SelectionComponent.STATS_BUTTON), ), @@ -268,7 +271,9 @@ class AddrFetchThread(Thread): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.connect(('8.8.8.8', 80)) val = sock.getsockname()[0] - bui.pushcall(bui.Call(self._call, val), from_other_thread=True) + bui.pushcall( + bui.CallStrict(self._call, val), from_other_thread=True + ) except Exception as exc: from efro.error import is_udp_communication_error @@ -334,7 +339,7 @@ class PingThread(Thread): time.sleep(1) ping = (time.time() - starttime) * 1000.0 bui.pushcall( - bui.Call( + bui.CallStrict( self._call, self._address, self._port, @@ -497,11 +502,13 @@ class PublicGatherTab(GatherTab): # Attempt to fetch our local address so we have it for error # messages. if self._local_address is None: - AddrFetchThread(bui.WeakCall(self._fetch_local_addr_cb)).start() + AddrFetchThread( + bui.WeakCallPartial(self._fetch_local_addr_cb) + ).start() self._set_sub_tab(self._sub_tab, region_width, region_height) self._update_timer = bui.AppTimer( - 0.1, bui.WeakCall(self._update), repeat=True + 0.1, bui.WeakCallStrict(self._update), repeat=True ) return self._container @@ -814,7 +821,7 @@ class PublicGatherTab(GatherTab): parent=self._container, id=f'{self._idprefix}|maxsizeminus', size=(40, 40), - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._on_max_public_party_size_minus_press ), position=(280 + xoffs, v - 26), @@ -825,7 +832,7 @@ class PublicGatherTab(GatherTab): parent=self._container, id=f'{self._idprefix}|maxsizeplus', size=(40, 40), - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._on_max_public_party_size_plus_press ), position=(350 + xoffs, v - 26), @@ -1154,7 +1161,7 @@ class PublicGatherTab(GatherTab): # Now, new or not, update its values. party.queue = party_in.get('q') - assert isinstance(party.queue, (str, type(None))) + assert isinstance(party.queue, str | None) party.port = port party.name = party_in['n'] assert isinstance(party.name, str) @@ -1167,7 +1174,7 @@ class PublicGatherTab(GatherTab): party.ping_interval = 0.001 * party_in['pi'] assert isinstance(party.ping_interval, float) party.stats_addr = party_in['sa'] - assert isinstance(party.stats_addr, (str, type(None))) + assert isinstance(party.stats_addr, str | None) # Make sure the party's UI gets updated. party.clean_display_index = None @@ -1255,7 +1262,9 @@ class PublicGatherTab(GatherTab): 'proto': bs.protocol_version(), 'lang': bui.app.lang.language, }, - callback=bui.WeakCall(self._on_public_party_query_result), + callback=bui.WeakCallPartial( + self._on_public_party_query_result + ), ) plus.run_v1_account_transactions() else: @@ -1297,7 +1306,9 @@ class PublicGatherTab(GatherTab): party.ping_attempts += 1 PingThread( - party.address, party.port, bui.WeakCall(self._ping_callback) + party.address, + party.port, + bui.WeakCallPartial(self._ping_callback), ).start() def _ping_callback( @@ -1413,7 +1424,9 @@ class PublicGatherTab(GatherTab): bui.app.classic.master_server_v1_get( 'bsAccessCheck', {'b': bui.app.env.engine_build_number}, - callback=bui.WeakCall(self._on_public_party_accessible_response), + callback=bui.WeakCallPartial( + self._on_public_party_accessible_response + ), ) def _on_start_advertizing_press(self) -> None: @@ -1483,6 +1496,13 @@ class PublicGatherTab(GatherTab): def on_public_party_activate(self, party: PartyEntry) -> None: """Called when a party is clicked or otherwise activated.""" self.save_state() + + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.JOIN_PUBLIC_PARTY + ) + ) + if party.queue is not None: from bauiv1lib.partyqueue import PartyQueueWindow diff --git a/dist/ba_data/python/bauiv1lib/gettokens.py b/dist/ba_data/python/bauiv1lib/gettokens.py index 7602d03..1493004 100644 --- a/dist/ba_data/python/bauiv1lib/gettokens.py +++ b/dist/ba_data/python/bauiv1lib/gettokens.py @@ -6,15 +6,13 @@ from __future__ import annotations import time from enum import Enum -from functools import partial from dataclasses import dataclass from typing import TYPE_CHECKING, assert_never, override import bacommon.cloud -import bacommon.bs +import bacommon.classic import bauiv1 as bui - if TYPE_CHECKING: from typing import Any, Callable @@ -73,6 +71,9 @@ class GetTokensWindow(bui.MainWindow): auxiliary_style: bool = True, ): # pylint: disable=too-many-locals + + self._auxiliary_style = auxiliary_style + self._uiopenstate = bui.UIOpenState('gettokens') bwidthstd = 170 bwidthwide = 300 ycolor = (0, 0, 0.3) @@ -107,7 +108,12 @@ class GetTokensWindow(bui.MainWindow): _TxtDef( bui.Lstr( resource='tokens.numTokensText', - subs=[('${COUNT}', str(bacommon.bs.TOKENS1_COUNT))], + subs=[ + ( + '${COUNT}', + str(bacommon.classic.TOKENS1_COUNT), + ) + ], ), pos=(bwidthstd * 0.5, pos1), color=(1.1, 1.05, 1.0), @@ -147,7 +153,12 @@ class GetTokensWindow(bui.MainWindow): _TxtDef( bui.Lstr( resource='tokens.numTokensText', - subs=[('${COUNT}', str(bacommon.bs.TOKENS2_COUNT))], + subs=[ + ( + '${COUNT}', + str(bacommon.classic.TOKENS2_COUNT), + ) + ], ), pos=(bwidthstd * 0.5, pos1), color=(1.1, 1.05, 1.0), @@ -187,7 +198,12 @@ class GetTokensWindow(bui.MainWindow): _TxtDef( bui.Lstr( resource='tokens.numTokensText', - subs=[('${COUNT}', str(bacommon.bs.TOKENS3_COUNT))], + subs=[ + ( + '${COUNT}', + str(bacommon.classic.TOKENS3_COUNT), + ) + ], ), pos=(bwidthstd * 0.5, pos1), color=(1.1, 1.05, 1.0), @@ -227,7 +243,12 @@ class GetTokensWindow(bui.MainWindow): _TxtDef( bui.Lstr( resource='tokens.numTokensText', - subs=[('${COUNT}', str(bacommon.bs.TOKENS4_COUNT))], + subs=[ + ( + '${COUNT}', + str(bacommon.classic.TOKENS4_COUNT), + ) + ], ), pos=(bwidthstd * 0.5, pos1), color=(1.1, 1.05, 1.0), @@ -344,7 +365,7 @@ class GetTokensWindow(bui.MainWindow): color=(0.3, 0.23, 0.36), scale=scale, toolbar_visibility=( - 'get_tokens' + 'menu_tokens' if uiscale is bui.UIScale.SMALL else 'menu_full' ), @@ -433,7 +454,7 @@ class GetTokensWindow(bui.MainWindow): self._state = self.State.LOADING self._update_timer = bui.AppTimer( - 0.789, bui.WeakCall(self._update), repeat=True + 0.789, bui.WeakCallStrict(self._update), repeat=True ) self._update() @@ -441,9 +462,16 @@ class GetTokensWindow(bui.MainWindow): def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. cls = type(self) + + # Pull everything out of self here. If we do it below in the lambda, + # we'll keep self alive which is bad. + auxiliary_style = self._auxiliary_style + return bui.BasicMainWindowState( create_call=lambda transition, origin_widget: cls( - transition=transition, origin_widget=origin_widget + transition=transition, + origin_widget=origin_widget, + auxiliary_style=auxiliary_style, ) ) @@ -470,7 +498,9 @@ class GetTokensWindow(bui.MainWindow): with plus.accounts.primary: plus.cloud.send_message_cb( bacommon.cloud.StoreQueryMessage(), - on_response=bui.WeakCall(self._on_store_query_response), + on_response=bui.WeakCallPartial( + self._on_store_query_response + ), ) # Can't do much until we get a store state. @@ -615,7 +645,7 @@ class GetTokensWindow(bui.MainWindow): scale=0.8, color=(0.4, 0.25, 0.5), textcolor=self._textcolor, - on_activate_call=partial( + on_activate_call=bui.WeakCallStrict( self._on_learn_more_press, response.token_info_url ), ) @@ -650,7 +680,7 @@ class GetTokensWindow(bui.MainWindow): size=(buttondef.width, 275), position=(x, -10 + yoffs), button_type='square', - on_activate_call=partial( + on_activate_call=bui.WeakCallStrict( self._purchase_press, buttondef.itemid ), ) @@ -786,7 +816,7 @@ class GetTokensWindow(bui.MainWindow): bui.open_url(url) -def show_get_tokens_prompt() -> None: +def show_get_tokens_prompt(origin_widget: bui.Widget | None = None) -> None: """Show a 'not enough tokens' prompt with an option to purchase more. Note that the purchase option may not always be available @@ -796,14 +826,19 @@ def show_get_tokens_prompt() -> None: assert bui.app.classic is not None + get_tokens_button = bui.get_special_widget('get_tokens_button') + # Currently always allowing token purchases. if bool(True): ConfirmWindow( bui.Lstr(resource='tokens.notEnoughTokensText'), - show_get_tokens_window, + bui.CallStrict( + show_get_tokens_window, origin_widget=get_tokens_button + ), ok_text=bui.Lstr(resource='tokens.getTokensText'), width=460, height=130, + origin_widget=origin_widget, ) else: ConfirmWindow( @@ -811,39 +846,45 @@ def show_get_tokens_prompt() -> None: cancel_button=False, width=460, height=130, + origin_widget=origin_widget, ) -def show_get_tokens_window(origin_widget: bui.Widget | None = None) -> None: +def show_get_tokens_window( + origin_widget: bui.Widget | None = None, toggle: bool = False +) -> None: """Transition to the get-tokens main-window from anywhere.""" - # NOTE TO USERS: The code below is not the proper way to do things; + # NOTE TO USERS: The code below is not the standard way to do things; # whenever possible one should use a MainWindow's # main_window_replace() or main_window_back() methods or # bauiv1.auxiliary_window_activate(). We just need to do things a # bit more manually in this particular case. - # Basically we want to pop up our auxiliary window but we don't want - # to replace any existing auxiliary windows; we want our close - # button to go back to whatever was there already, no matter whether - # it was an auxiliary window or not. + # Basically we want to push our window on to the stack from + # anywhere so we can go back to where we were once done even if it + # was an auxiliary window. prev_main_window = bui.app.ui_v1.get_main_window() # Special-case: If it seems we're already in the window, do nothing. if isinstance(prev_main_window, GetTokensWindow): + if toggle: + prev_main_window.main_window_back() return ui = bui.app.ui_v1 - # Set our new main window. + # Set our new main window. Note that we pass auxiliary_style=False + # so that we get a back button instead of a close button. ui.set_main_window( - GetTokensWindow(origin_widget=origin_widget), + GetTokensWindow(origin_widget=origin_widget, auxiliary_style=False), from_window=False, # Don't check where we're coming from. back_state=ui.save_current_main_window_state(), - is_auxiliary=True, + is_auxiliary=False, suppress_warning=True, + extra_type_id='', ) # Transition out any previous main window. if prev_main_window is not None: - prev_main_window.main_window_close() + prev_main_window.main_window_close(transition='out_left') diff --git a/dist/ba_data/python/bauiv1lib/help.py b/dist/ba_data/python/bauiv1lib/help.py index 73f7ee0..cda1b6b 100644 --- a/dist/ba_data/python/bauiv1lib/help.py +++ b/dist/ba_data/python/bauiv1lib/help.py @@ -447,7 +447,9 @@ class HelpWindow(bui.MainWindow): color=(1, 0.7, 0.3), selectable=False, enable_sound=False, - on_activate_call=bui.WeakCall(self._play_sound, 'spazAttack0', 4), + on_activate_call=bui.WeakCallStrict( + self._play_sound, 'spazAttack0', 4 + ), ) txt_scale = getres(f'{self._r}.punchInfoTextScale') @@ -475,7 +477,9 @@ class HelpWindow(bui.MainWindow): color=(1, 0.3, 0.3), selectable=False, enable_sound=False, - on_activate_call=bui.WeakCall(self._play_sound, 'explosion0', 5), + on_activate_call=bui.WeakCallStrict( + self._play_sound, 'explosion0', 5 + ), ) txt = bui.Lstr(resource=f'{self._r}.bombInfoText').evaluate() @@ -504,7 +508,9 @@ class HelpWindow(bui.MainWindow): color=(0.5, 0.5, 1), selectable=False, enable_sound=False, - on_activate_call=bui.WeakCall(self._play_sound, 'spazPickup0', 1), + on_activate_call=bui.WeakCallStrict( + self._play_sound, 'spazPickup0', 1 + ), ) txtl = bui.Lstr(resource=f'{self._r}.pickUpInfoText') @@ -532,7 +538,9 @@ class HelpWindow(bui.MainWindow): color=(0.4, 1, 0.4), selectable=False, enable_sound=False, - on_activate_call=bui.WeakCall(self._play_sound, 'spazJump0', 4), + on_activate_call=bui.WeakCallStrict( + self._play_sound, 'spazJump0', 4 + ), ) txt = bui.Lstr(resource=f'{self._r}.jumpInfoText').evaluate() diff --git a/dist/ba_data/python/bauiv1lib/iconpicker.py b/dist/ba_data/python/bauiv1lib/iconpicker.py index 0a9bd4b..9c3301f 100644 --- a/dist/ba_data/python/bauiv1lib/iconpicker.py +++ b/dist/ba_data/python/bauiv1lib/iconpicker.py @@ -130,7 +130,7 @@ class IconPicker(PopupWindow): text_scale=1.2, label='', color=(0.65, 0.65, 0.65), - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._select_icon, self._icons[index] ), position=pos, @@ -176,7 +176,7 @@ class IconPicker(PopupWindow): plus = bui.app.plus assert plus is not None - if plus.get_v1_account_state() != 'signed_in': + if plus.accounts.primary is None: show_sign_in_prompt() return diff --git a/dist/ba_data/python/bauiv1lib/inbox.py b/dist/ba_data/python/bauiv1lib/inbox.py index 1ec082d..fc5c589 100644 --- a/dist/ba_data/python/bauiv1lib/inbox.py +++ b/dist/ba_data/python/bauiv1lib/inbox.py @@ -12,7 +12,9 @@ from typing import override, assert_never, TYPE_CHECKING from efro.util import strict_partial, pairs_from_flat from efro.error import CommunicationError -import bacommon.bs +import bacommon.clouddialog as cdlg +import bacommon.clouddialog.basic as bcdlg +import bacommon.classic from bauiv1lib.utils import scroll_fade_bottom, scroll_fade_top import bauiv1 as bui @@ -20,6 +22,8 @@ if TYPE_CHECKING: import datetime from typing import Callable + import bacommon.displayitem as ditm + class _Section: def get_height(self) -> float: @@ -164,7 +168,7 @@ class _DisplayItemsSection(_Section): self, *, sub_width: float, - items: list[bacommon.bs.DisplayItemWrapper], + items: list[ditm.Wrapper], width: float = 100.0, spacing_top: float = 0.0, spacing_bottom: float = 0.0, @@ -286,15 +290,17 @@ class _ExpireTimeSection(_Section): h_align='center', v_align='center', ) - self._timer = bui.AppTimer(1.0, bui.WeakCall(self._update), repeat=True) + self._timer = bui.AppTimer( + 1.0, bui.WeakCallStrict(self._update), repeat=True + ) self._update() @dataclass class _EntryDisplay: - interaction_style: bacommon.bs.BasicCloudDialog.InteractionStyle - button_label_positive: bacommon.bs.BasicCloudDialog.ButtonLabel - button_label_negative: bacommon.bs.BasicCloudDialog.ButtonLabel + interaction_style: bcdlg.InteractionStyle + button_label_positive: bcdlg.ButtonLabel + button_label_negative: bcdlg.ButtonLabel sections: list[_Section] id: str total_height: float @@ -320,6 +326,8 @@ class InboxWindow(bui.MainWindow): assert bui.app.classic is not None uiscale = bui.app.ui_v1.uiscale + self._uiopenstate = bui.UIOpenState('classicinbox') + self._action_ui_pause: bui.RootUIUpdatePause | None = None self._entry_displays: list[_EntryDisplay] = [] @@ -487,8 +495,10 @@ class InboxWindow(bui.MainWindow): with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.InboxRequestMessage(), - on_response=bui.WeakCall(self._on_inbox_request_response), + bacommon.classic.InboxRequestMessage(), + on_response=bui.WeakCallPartial( + self._on_inbox_request_response + ), ) @override @@ -517,7 +527,7 @@ class InboxWindow(bui.MainWindow): def _on_entry_display_press( self, display_weak: weakref.ReferenceType[_EntryDisplay], - action: bacommon.bs.CloudDialogAction, + action: cdlg.Action, ) -> None: display = display_weak() if display is None: @@ -529,10 +539,7 @@ class InboxWindow(bui.MainWindow): # We currently only recognize basic entries and their possible # interaction types. - if ( - display.interaction_style - is bacommon.bs.BasicCloudDialog.InteractionStyle.UNKNOWN - ): + if display.interaction_style is bcdlg.InteractionStyle.UNKNOWN: display.processing_complete = True self._close_soon_if_all_processed() return @@ -554,8 +561,8 @@ class InboxWindow(bui.MainWindow): # Ask the master-server to run our action. with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.CloudDialogActionMessage(display.id, action), - on_response=bui.WeakCall( + cdlg.ActionMessage(display.id, action), + on_response=bui.WeakCallPartial( self._on_client_ui_action_response, display_weak, action, @@ -565,12 +572,12 @@ class InboxWindow(bui.MainWindow): # Tweak the UI to show that things are in motion. button = ( display.button_positive - if action is bacommon.bs.CloudDialogAction.BUTTON_PRESS_POSITIVE + if action is cdlg.Action.BUTTON_PRESS_POSITIVE else display.button_negative ) button_spinner = ( display.button_spinner_positive - if action is bacommon.bs.CloudDialogAction.BUTTON_PRESS_POSITIVE + if action is cdlg.Action.BUTTON_PRESS_POSITIVE else display.button_spinner_negative ) if button is not None: @@ -579,7 +586,7 @@ class InboxWindow(bui.MainWindow): bui.spinnerwidget(edit=button_spinner, visible=True) def _close_soon_if_all_processed(self) -> None: - bui.apptimer(0.25, bui.WeakCall(self._close_if_all_processed)) + bui.apptimer(0.25, bui.WeakCallStrict(self._close_if_all_processed)) def _close_if_all_processed(self) -> None: if not all(m.processing_complete for m in self._entry_displays): @@ -609,8 +616,8 @@ class InboxWindow(bui.MainWindow): def _on_client_ui_action_response( self, display_weak: weakref.ReferenceType[_EntryDisplay], - action: bacommon.bs.CloudDialogAction, - response: bacommon.bs.CloudDialogActionResponse | Exception, + action: cdlg.Action, + response: cdlg.ActionResponse | Exception, ) -> None: # pylint: disable=too-many-branches @@ -633,12 +640,12 @@ class InboxWindow(bui.MainWindow): # Tweak the button to show results. button = ( display.button_positive - if action is bacommon.bs.CloudDialogAction.BUTTON_PRESS_POSITIVE + if action is cdlg.Action.BUTTON_PRESS_POSITIVE else display.button_negative ) button_spinner = ( display.button_spinner_positive - if action is bacommon.bs.CloudDialogAction.BUTTON_PRESS_POSITIVE + if action is cdlg.Action.BUTTON_PRESS_POSITIVE else display.button_spinner_negative ) # Always hide spinner at this point. @@ -690,7 +697,7 @@ class InboxWindow(bui.MainWindow): bui.buttonwidget(edit=button, label=label) def _on_inbox_request_response( - self, response: bacommon.bs.InboxRequestResponse | Exception + self, response: bacommon.classic.InboxRequestResponse | Exception ) -> None: # pylint: disable=too-many-locals # pylint: disable=too-many-statements @@ -716,7 +723,7 @@ class InboxWindow(bui.MainWindow): self._error(errmsg) return - assert isinstance(response, bacommon.bs.InboxRequestResponse) + assert isinstance(response, bacommon.classic.InboxRequestResponse) # If we got no messages, don't touch anything. This keeps # keyboard control working in the empty case. @@ -759,9 +766,9 @@ class InboxWindow(bui.MainWindow): # textfin: str color: tuple[float, float, float] - interaction_style: bacommon.bs.BasicCloudDialog.InteractionStyle - button_label_positive: bacommon.bs.BasicCloudDialog.ButtonLabel - button_label_negative: bacommon.bs.BasicCloudDialog.ButtonLabel + interaction_style: bcdlg.InteractionStyle + button_label_positive: bcdlg.ButtonLabel + button_label_negative: bcdlg.ButtonLabel sections: list[_Section] = [] total_height = 80.0 @@ -769,7 +776,7 @@ class InboxWindow(bui.MainWindow): # Display only entries where we recognize all style/label # values and ui component types. if ( - isinstance(wrapper.ui, bacommon.bs.BasicCloudDialog) + isinstance(wrapper.ui, bcdlg.BasicCloudDialog) and not wrapper.ui.contains_unknown_elements() ): color = (0.55, 0.5, 0.7) @@ -777,15 +784,13 @@ class InboxWindow(bui.MainWindow): button_label_positive = wrapper.ui.button_label_positive button_label_negative = wrapper.ui.button_label_negative - idcls = bacommon.bs.BasicCloudDialogComponentTypeID + idcls = bcdlg.ComponentTypeID for component in wrapper.ui.components: ctypeid = component.get_type_id() section: _Section if ctypeid is idcls.TEXT: - assert isinstance( - component, bacommon.bs.BasicCloudDialogComponentText - ) + assert isinstance(component, bcdlg.Text) section = _TextSection( sub_width=sub_width, text=bui.Lstr( @@ -801,9 +806,7 @@ class InboxWindow(bui.MainWindow): sections.append(section) elif ctypeid is idcls.LINK: - assert isinstance( - component, bacommon.bs.BasicCloudDialogComponentLink - ) + assert isinstance(component, bcdlg.Link) def _do_open_url(url: str, sec: _ButtonSection) -> None: del sec # Unused. @@ -827,7 +830,7 @@ class InboxWindow(bui.MainWindow): elif ctypeid is idcls.DISPLAY_ITEMS: assert isinstance( component, - bacommon.bs.BasicCloudDialogDisplayItems, + bcdlg.DisplayItems, ) section = _DisplayItemsSection( sub_width=sub_width, @@ -844,7 +847,7 @@ class InboxWindow(bui.MainWindow): assert isinstance( component, - bacommon.bs.BasicCloudDialogBsClassicTourneyResult, + bcdlg.ClassicTourneyResult, ) campaignname, levelname = component.game.split(':') assert bui.app.classic is not None @@ -968,9 +971,7 @@ class InboxWindow(bui.MainWindow): sections.append(section) elif ctypeid is idcls.EXPIRE_TIME: - assert isinstance( - component, bacommon.bs.BasicCloudDialogExpireTime - ) + assert isinstance(component, bcdlg.ExpireTime) section = _ExpireTimeSection( sub_width=sub_width, time=component.time, @@ -991,15 +992,9 @@ class InboxWindow(bui.MainWindow): # Display anything with unknown components as an # 'upgrade your app to see this' message. color = (0.6, 0.6, 0.6) - interaction_style = ( - bacommon.bs.BasicCloudDialog.InteractionStyle.UNKNOWN - ) - button_label_positive = ( - bacommon.bs.BasicCloudDialog.ButtonLabel.OK - ) - button_label_negative = ( - bacommon.bs.BasicCloudDialog.ButtonLabel.CANCEL - ) + interaction_style = bcdlg.InteractionStyle.UNKNOWN + button_label_positive = bcdlg.ButtonLabel.OK + button_label_negative = bcdlg.ButtonLabel.CANCEL section = _TextSection( sub_width=sub_width, @@ -1047,9 +1042,7 @@ class InboxWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL: y -= 36 - # for i, _wrapper in enumerate(response.wrappers): for entry_display in self._entry_displays: - # entry_display = self._entry_displays[i] entry_display_weak = weakref.ref(entry_display) bwidth = 140 bheight = 40 @@ -1089,9 +1082,7 @@ class InboxWindow(bui.MainWindow): buttonrow: list[bui.Widget] = [] have_negative_button = ( entry_display.interaction_style - is ( - bacommon.bs.BasicCloudDialog - ).InteractionStyle.BUTTON_POSITIVE_NEGATIVE + is bcdlg.InteractionStyle.BUTTON_POSITIVE_NEGATIVE ) bpos = ( @@ -1116,10 +1107,10 @@ class InboxWindow(bui.MainWindow): ), color=entry_display.color, textcolor=(0, 1, 0), - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._on_entry_display_press, entry_display_weak, - bacommon.bs.CloudDialogAction.BUTTON_PRESS_POSITIVE, + cdlg.Action.BUTTON_PRESS_POSITIVE, ), enable_sound=False, ) @@ -1151,10 +1142,10 @@ class InboxWindow(bui.MainWindow): ), color=(0.85, 0.5, 0.7), textcolor=(1, 0.4, 0.4), - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._on_entry_display_press, entry_display_weak, - (bacommon.bs.CloudDialogAction).BUTTON_PRESS_NEGATIVE, + (cdlg.Action).BUTTON_PRESS_NEGATIVE, ), enable_sound=False, ) diff --git a/dist/ba_data/python/bauiv1lib/ingamemenu.py b/dist/ba_data/python/bauiv1lib/ingamemenu.py index f9fe988..c425ec0 100644 --- a/dist/ba_data/python/bauiv1lib/ingamemenu.py +++ b/dist/ba_data/python/bauiv1lib/ingamemenu.py @@ -177,7 +177,9 @@ class InGameMenuWindow(bui.MainWindow): # Keep updating in a timer in case it gets changed elsewhere. self._change_replay_speed_timer = bui.AppTimer( - 0.25, bui.WeakCall(self._change_replay_speed, 0), repeat=True + 0.25, + bui.WeakCallStrict(self._change_replay_speed, 0), + repeat=True, ) btn = bui.buttonwidget( parent=self._root_widget, @@ -190,7 +192,7 @@ class InGameMenuWindow(bui.MainWindow): size=(b_size, b_size), label='', autoselect=True, - on_activate_call=bui.Call(self._change_replay_speed, -1), + on_activate_call=bui.CallStrict(self._change_replay_speed, -1), ) bui.textwidget( parent=self._root_widget, @@ -213,7 +215,7 @@ class InGameMenuWindow(bui.MainWindow): size=(b_size, b_size), label='', autoselect=True, - on_activate_call=bui.Call(self._change_replay_speed, 1), + on_activate_call=bui.CallStrict(self._change_replay_speed, 1), ) bui.textwidget( parent=self._root_widget, @@ -240,7 +242,7 @@ class InGameMenuWindow(bui.MainWindow): else bui.SpecialChar.PAUSE_BUTTON ), autoselect=True, - on_activate_call=bui.Call(self._pause_or_resume_replay), + on_activate_call=bui.CallStrict(self._pause_or_resume_replay), ) btn = bui.buttonwidget( parent=self._root_widget, @@ -253,7 +255,7 @@ class InGameMenuWindow(bui.MainWindow): size=(b_size, b_size), label='', autoselect=True, - on_activate_call=bui.WeakCall(self._rewind_replay), + on_activate_call=bui.WeakCallStrict(self._rewind_replay), ) bui.textwidget( parent=self._root_widget, @@ -280,7 +282,7 @@ class InGameMenuWindow(bui.MainWindow): size=(b_size, b_size), label='', autoselect=True, - on_activate_call=bui.WeakCall(self._forward_replay), + on_activate_call=bui.WeakCallStrict(self._forward_replay), ) bui.textwidget( parent=self._root_widget, @@ -408,9 +410,11 @@ class InGameMenuWindow(bui.MainWindow): resume = bool(entry.get('resume_on_call', True)) if resume: - call = bui.Call(self._resume_and_call, entry['call']) + call = bui.CallStrict(self._resume_and_call, entry['call']) else: - call = bui.Call(entry['call'], bui.WeakCall(self._resume)) + call = bui.CallStrict( + entry['call'], bui.WeakCallStrict(self._resume) + ) bui.buttonwidget( parent=self._root_widget, diff --git a/dist/ba_data/python/bauiv1lib/inventory.py b/dist/ba_data/python/bauiv1lib/inventory.py index 256f5ae..5a9bcac 100644 --- a/dist/ba_data/python/bauiv1lib/inventory.py +++ b/dist/ba_data/python/bauiv1lib/inventory.py @@ -4,151 +4,405 @@ from __future__ import annotations -from typing import override +import random +from typing import override, TYPE_CHECKING + +from efro.util import asserttype +import bacommon.docui.v1 as dui1 import bauiv1 as bui +from bauiv1lib.docui import DocUIController -class InventoryWindow(bui.MainWindow): - """Shows what you got.""" +if TYPE_CHECKING: + from typing import Any - def __init__( - self, - transition: str | None = 'in_right', - origin_widget: bui.Widget | None = None, - auxiliary_style: bool = True, - ): + from bacommon.docui import DocUIRequest, DocUIResponse - uiscale = bui.app.ui_v1.uiscale - self._width = 1400 if uiscale is bui.UIScale.SMALL else 750 - self._height = ( - 1200 - if uiscale is bui.UIScale.SMALL - else 530 if uiscale is bui.UIScale.MEDIUM else 600 - ) + from bauiv1lib.docui import DocUILocalAction, DocUIWindow - # Do some fancy math to fill all available screen area up to the - # size of our backing container. This lets us fit to the exact - # screen shape at small ui scale. - screensize = bui.get_virtual_screen_size() - scale = ( - 1.55 - if uiscale is bui.UIScale.SMALL - else 1.15 if uiscale is bui.UIScale.MEDIUM else 1.0 - ) - # Calc screen size in our local container space and clamp to a - # bit smaller than our container size. - target_height = min(self._height - 100, screensize[1] / scale) +class InventoryUIController(DocUIController): + """DocUI setup for inventory.""" - # To get top/left coords, go to the center of our window and - # offset by half the width/height of our target area. - yoffs = 0.5 * self._height + 0.5 * target_height + 30.0 + def __init__(self, player_profiles_only: bool = False) -> None: + self._next_selected_profile: str | None = None + self._player_profiles_only = player_profiles_only - super().__init__( - root_widget=bui.containerwidget( - size=(self._width, self._height), - toolbar_visibility=( - 'menu_full' if uiscale is bui.UIScale.SMALL else 'menu_full' - ), - toolbar_cancel_button_style=( - 'close' if auxiliary_style else 'back' - ), - scale=scale, - ), - transition=transition, - origin_widget=origin_widget, - # We're affected by screen size only at small ui-scale. - refresh_on_screen_size_changes=uiscale is bui.UIScale.SMALL, - ) + @override + def fulfill_request(self, request: DocUIRequest) -> DocUIResponse: - bui.textwidget( - parent=self._root_widget, - position=( - self._width * 0.5, - yoffs - (50 if uiscale is bui.UIScale.SMALL else 30), - ), - size=(0, 0), - text=bui.Lstr(resource='inventoryText'), - color=bui.app.ui_v1.title_color, - scale=0.9 if uiscale is bui.UIScale.SMALL else 1.0, - maxwidth=(130 if uiscale is bui.UIScale.SMALL else 200), - h_align='center', - v_align='center', - ) + response: DocUIResponse - if uiscale is bui.UIScale.SMALL: - bui.containerwidget( - edit=self._root_widget, on_cancel_call=self.main_window_back + # If we only want player profiles, we can skip the whole cloud + # request bit. + if self._player_profiles_only: + response = dui1.Response( + page=dui1.Page( + title='{"r":"inventoryText"}', + title_is_lstr=True, + rows=[], + ) ) else: - btn = bui.buttonwidget( - parent=self._root_widget, - id=f'{self.main_window_id_prefix}|back', - scale=0.8, - position=(50, yoffs - 50), - size=(50, 50) if auxiliary_style else (60, 55), - extra_touch_border_scale=2.0, - button_type=None if auxiliary_style else 'backSmall', - on_activate_call=self.main_window_back, - autoselect=True, - label=bui.charstr( - bui.SpecialChar.CLOSE - if auxiliary_style - else bui.SpecialChar.BACK - ), - ) - bui.containerwidget(edit=self._root_widget, cancel_button=btn) + # *Most* of our inventory comes from the cloud - we just supply + # profiles ourself so it works offline. + response = self.fulfill_request_cloud(request, 'classicinventory') - if bool(False): - print('WOULD TEST NEW STUFF') + assert isinstance(request, dui1.Request) + assert isinstance(response, dui1.Response) + + if request.path != '/': + return response + + signed_in = ( + bui.app.plus is not None + and bui.app.plus.accounts.primary is not None + ) + + # If anything went wrong, replace the error page they sent us with + # a minimal 'most stuff is only available online' page. + inv_only_signin_t = '{"r":"inventoryOnlyAvailableSignedInText"}' + inv_only_online_t = '{"r":"inventoryOnlyAvailableOnlineText"}' + if response.status is not dui1.ResponseStatus.SUCCESS: + response = dui1.Response( + page=dui1.Page( + title='{"r":"inventoryText"}', + title_is_lstr=True, + rows=[ + dui1.ButtonRow( + center_content=True, + buttons=[ + dui1.Button( + ( + inv_only_signin_t + if not signed_in + else inv_only_online_t + ), + label_is_lstr=True, + texture='white', + size=(600, 100), + color=(1, 1, 1, 0.0), + label_scale=0.7, + label_color=(1, 0.4, 0.4, 0.8), + ) + ], + ), + ], + ), + ) + + for row in response.page.rows: + if ( + isinstance(row, dui1.ButtonRow) + and row.title + and '"r":"store.yourCharactersText"' in row.title + ): + for button in row.buttons: + if not button.decorations: + continue + for decoration in button.decorations: + if isinstance(decoration, dui1.Text): + button.action = dui1.Local( + immediate_local_action='spawn_bot', + immediate_local_action_args={ + 'name': decoration.text + }, + ) + break + + # Now add in our profiles, which we handle locally so it is + # available offline. + response.page.rows = [ + dui1.ButtonRow( + title='{"r":"playerProfilesWindow.titleText"}', + title_is_lstr=True, + subtitle='{"r":"playerProfilesWindow.explanationText"}', + subtitle_is_lstr=True, + button_spacing=15, + buttons=self._get_profile_buttons(), + ), + dui1.ButtonRow( + spacing_top=-15, + spacing_bottom=15, + padding_left=13, + buttons=[ + dui1.Button( + '{"r":"editProfileWindow.titleNewText"}', + dui1.Local( + default_sound=False, + immediate_local_action='new_profile', + ), + icon='plusButton', + icon_scale=1.3, + icon_color=(0.7, 0.6, 0.9, 1), + label_is_lstr=True, + style=dui1.ButtonStyle.MEDIUM, + size=(210, 60), + scale=0.8, + color=(0.6, 0.5, 0.8, 1.0), + label_color=(1, 1, 1, 1), + ), + ], + ), + ] + response.page.rows + + return response + + @override + def local_action(self, action: DocUILocalAction) -> None: + if action.name == 'new_profile': + self._new_profile(action) + elif action.name == 'edit_profile': + self._edit_profile(action) + elif action.name == 'spawn_bot': + self._spawn_bot(action) else: - button_width = 300 - self._player_profiles_button = btn = bui.buttonwidget( - parent=self._root_widget, - id=f'{self.main_window_id_prefix}|playerprofiles', - position=(self._width * 0.5 - button_width * 0.5, yoffs - 200), - autoselect=True, - size=(button_width, 60), - label=bui.Lstr(resource='playerProfilesWindow.titleText'), - color=(0.55, 0.5, 0.6), - icon=bui.gettexture('cuteSpaz'), - textcolor=(0.75, 0.7, 0.8), - on_activate_call=self._player_profiles_press, + bui.screenmessage( + f'Invalid local-action "{action.name}".', color=(1, 0, 0) ) - # Select this by default. - bui.containerwidget(edit=self._root_widget, selected_child=btn) - bui.textwidget( - parent=self._root_widget, - position=(self._width * 0.5, yoffs - 250), - size=(0, 0), - text=bui.Lstr(resource='moreSoonText'), - scale=0.7, - maxwidth=self._width * 0.9, - h_align='center', - v_align='center', + bui.getsound('error').play() + + @override + def restore_window_shared_state( + self, window: DocUIWindow, state: dict + ) -> None: + """Called when a window shared state is being restored.""" + + if not isinstance(window.request, dui1.Request): + return + + # If desired, set the profile button that will be selected in + # the new window. We do this when coming back from creating a + # new profile/etc. + if ( + window.request.path == '/' + and self._next_selected_profile is not None + ): + state['selection'] = f'$(WIN)|profile.{self._next_selected_profile}' + + # Only do this once (return to normal selection save/restore + # after). + self._next_selected_profile = None + + def _on_profile_save(self, name: str) -> None: + # An editor we launched tells us it saved a profile. + + # Have this one selected when we go back to the listing. + self._next_selected_profile = name + bui.pushcall(self._notify_profiles_changed) + + def _on_profile_delete(self, name: str) -> None: + # An editor we launched tells us it deleted a profile. + + # Ask the inventory list to select/show the profile right before + # the one we're deleting. + profiles = bui.app.config.get('Player Profiles', {}) + items = list(profiles.items()) + items.sort(key=lambda x: asserttype(x[0], str).lower()) + + namelower = name.lower() + + prevname = items[0][0] if items else None + for item in items: + if item[0].lower() < namelower: + prevname = item[0] + else: + break + + if prevname is not None: + self._next_selected_profile = prevname + + self._notify_profiles_changed() + + def _notify_profiles_changed(self) -> None: + import bascenev1 as bs + + # If there's a team-chooser in existence, tell it the profile-list + # has probably changed. + session = bs.get_foreground_host_session() + if session is not None: + session.handlemessage(bs.PlayerProfilesChangedMessage()) + + def _get_profile_buttons(self) -> list[dui1.Button]: + # pylint: disable=too-many-locals + + plus = bui.app.plus + assert plus is not None + classic = bui.app.classic + assert classic is not None + + buttons: list[dui1.Button] = [] + + profiles = bui.app.config.get('Player Profiles', {}) + items = list(profiles.items()) + items.sort(key=lambda x: asserttype(x[0], str).lower()) + + account_name: str | None + if plus.get_v1_account_state() == 'signed_in': + account_name = plus.get_v1_account_display_string() + else: + account_name = None + + spaz_appearances = classic.spaz_appearances + spaz_appearance_default = spaz_appearances['Spaz'] + + for p_name, p_info in items: + if p_name == '__account__' and account_name is None: + continue + color, highlight = classic.get_player_profile_colors(p_name) + tval = ( + account_name + if p_name == '__account__' + else classic.get_player_profile_icon(p_name) + p_name + ) + assert tval is not None + + tcolor: Any = bui.safecolor(color, 0.4) + (1.0,) + assert len(tcolor) == 4 + + appearance = spaz_appearances.get(p_info['character']) + if appearance is None: + appearance = spaz_appearance_default + + buttons.append( + dui1.Button( + texture='white', + size=(145, 175), + action=dui1.Local( + default_sound=False, + immediate_local_action='edit_profile', + immediate_local_action_args={'profile': p_name}, + ), + # color=(0.6, 0.5, 0.7, 1.0), + color=(1, 1, 1, 0.0), + widget_id=f'profile.{p_name}', + decorations=[ + dui1.Image( + appearance.icon_texture, + position=(0, 15), + size=(140, 140), + mask_texture='characterIconMask', + tint_texture=appearance.icon_mask_texture, + tint_color=color, + tint2_color=highlight, + ), + dui1.Text( + tval, + position=(0, -75), + size=(130, 40), + flatness=1.0, + shadow=1.0, + color=tcolor, + ), + ], + ) ) - def _player_profiles_press(self) -> None: + return buttons + + def _new_profile(self, action: DocUILocalAction) -> None: # pylint: disable=cyclic-import - from bauiv1lib.profile.browser import ProfileBrowserWindow + from bauiv1lib.profile.edit import EditProfileWindow - self.main_window_replace( - lambda: ProfileBrowserWindow( - origin_widget=self._player_profiles_button + bui.getsound('swish').play() + + plus = bui.app.plus + assert plus is not None + + # Clamp at 100 profiles (otherwise the server will and that's less + # elegant looking). + profiles = bui.app.config.get('Player Profiles', {}) + if len(profiles) > 100: + bui.screenmessage( + bui.Lstr( + translate=( + 'serverResponses', + 'Max number of profiles reached.', + ) + ), + color=(1, 0, 0), + ) + bui.getsound('error').play() + return + + action.window.main_window_replace( + lambda: EditProfileWindow( + existing_profile=None, + on_profile_save=bui.WeakCallPartial(self._on_profile_save), + on_profile_delete=bui.WeakCallPartial(self._on_profile_delete), ) ) - @override - def get_main_window_state(self) -> bui.MainWindowState: - # Support recreating our window for back/refresh purposes. - cls = type(self) - return bui.BasicMainWindowState( - create_call=lambda transition, origin_widget: cls( - transition=transition, origin_widget=origin_widget + def _edit_profile(self, action: DocUILocalAction) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.profile.edit import EditProfileWindow + + bui.getsound('swish').play() + + profile = action.args.get('profile') + assert isinstance(profile, str) + + # Play a random sound from the character. + classic = bui.app.classic + if classic is not None: + profiles = bui.app.config.get('Player Profiles', {}) + p_info = profiles.get(profile) + if p_info: + char = p_info.get('character', 'Spaz') + appearance = classic.spaz_appearances.get(char) + if appearance: + sounds = ( + appearance.jump_sounds + + appearance.attack_sounds + + appearance.pickup_sounds + ) + if sounds: + bui.getsound(random.choice(sounds)).play() + + action.window.main_window_replace( + lambda: EditProfileWindow( + profile, + origin_widget=action.widget, + on_profile_save=bui.WeakCallPartial(self._on_profile_save), + on_profile_delete=bui.WeakCallPartial(self._on_profile_delete), ) ) - @override - def main_window_should_preserve_selection(self) -> bool: - return True + def _spawn_bot(self, action: DocUILocalAction) -> None: + import bascenev1 as bs + from bascenev1lib.mainmenu import MainMenuActivity + from bascenev1lib.actor.spazbot import DemoSpazBotSet, DemoBot + from bascenev1lib.actor.spazappearance import get_appearances + + name = action.args.get('name') + assert isinstance(name, str) + + activity = bs.get_foreground_host_activity() + if not isinstance(activity, MainMenuActivity) or activity.map is None: + return + bounds = activity.map.get_def_bound_box('map_bounds') + if bounds is None: + return + i = 0 + while i < len(activity.bot_sets): + if activity.bot_sets[i].have_living_bots(): + i += 1 + else: + activity.bot_sets.pop(i) + for appearance in get_appearances(True): + if f'"{appearance}"' in name: + with activity.context: + bot_set = DemoSpazBotSet() + DemoBot.randomize_traits(appearance) + bot_set.spawn_bot( + DemoBot, + ( + (bounds[0] + bounds[3]) / 2 + random.uniform(-7, 7), + bounds[4] - 2, + (bounds[2] + bounds[5]) / 2 + random.uniform(-7, 7), + ), + 0, + ) + activity.bot_sets.append(bot_set) + break diff --git a/dist/ba_data/python/bauiv1lib/kiosk.py b/dist/ba_data/python/bauiv1lib/kiosk.py index 64da3c5..bf3453f 100644 --- a/dist/ba_data/python/bauiv1lib/kiosk.py +++ b/dist/ba_data/python/bauiv1lib/kiosk.py @@ -114,7 +114,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'easy'), + on_activate_call=bui.CallStrict(self._do_game, 'easy'), transition_delay=tdelay, position=(h - b_width * 0.5, b_v), label='', @@ -149,7 +149,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'medium'), + on_activate_call=bui.CallStrict(self._do_game, 'medium'), position=(h - b_width * 0.5, b_v), label='', button_type='square', @@ -184,7 +184,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'hard'), + on_activate_call=bui.CallStrict(self._do_game, 'hard'), transition_delay=tdelay, position=(h - b_width * 0.5, b_v), label='', @@ -239,7 +239,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'ctf'), + on_activate_call=bui.CallStrict(self._do_game, 'ctf'), transition_delay=tdelay, position=(h - b_width * 0.5, b_v), label='', @@ -275,7 +275,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'hockey'), + on_activate_call=bui.CallStrict(self._do_game, 'hockey'), position=(h - b_width * 0.5, b_v), label='', button_type='square', @@ -310,7 +310,7 @@ class KioskWindow(bui.MainWindow): parent=self._root_widget, autoselect=True, size=(b_width, b_height), - on_activate_call=bui.Call(self._do_game, 'epic'), + on_activate_call=bui.CallStrict(self._do_game, 'epic'), transition_delay=tdelay, position=(h - b_width * 0.5, b_v), label='', @@ -361,7 +361,7 @@ class KioskWindow(bui.MainWindow): self._restore_state() self._update() self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) @override @@ -468,9 +468,11 @@ class KioskWindow(bui.MainWindow): appconfig['Free-for-All Playlist Selection'] = 'Just Epic Elim' bui.fade_screen( False, - endcall=bui.Call( + endcall=bui.CallStrict( bui.pushcall, - bui.Call(bs.new_host_session, bs.FreeForAllSession), + bui.CallStrict( + bs.new_host_session, bs.FreeForAllSession + ), ), ) else: @@ -507,9 +509,9 @@ class KioskWindow(bui.MainWindow): ) bui.fade_screen( False, - endcall=bui.Call( + endcall=bui.CallStrict( bui.pushcall, - bui.Call(bs.new_host_session, bs.DualTeamSession), + bui.CallStrict(bs.new_host_session, bs.DualTeamSession), ), ) bui.containerwidget(edit=self._root_widget, transition='out_left') diff --git a/dist/ba_data/python/bauiv1lib/league/presidency.py b/dist/ba_data/python/bauiv1lib/league/presidency.py new file mode 100644 index 0000000..3d35b76 --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/league/presidency.py @@ -0,0 +1,40 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Shiny new doc-ui based store.""" + +from __future__ import annotations + +from typing import override, TYPE_CHECKING + +from bauiv1lib.docui import DocUIController + +import bauiv1 as bui + +if TYPE_CHECKING: + from bacommon.docui import DocUIRequest, DocUIResponse + + from bauiv1lib.docui import DocUILocalAction + + +class LeaguePresidencyUIController(DocUIController): + """DocUI setup for store.""" + + @override + def fulfill_request(self, request: DocUIRequest) -> DocUIResponse: + return self.fulfill_request_cloud(request, 'classicleaguepresidency') + + @override + def local_action(self, action: DocUILocalAction) -> None: + if action.name == 'get_tokens': + self._get_tokens(action) + else: + bui.screenmessage( + f'Invalid local-action "{action.name}".', color=(1, 0, 0) + ) + bui.getsound('error').play() + + def _get_tokens(self, action: DocUILocalAction) -> None: + from bauiv1lib.gettokens import show_get_tokens_window + + bui.getsound('swish').play() + show_get_tokens_window(origin_widget=bui.existing(action.widget)) diff --git a/dist/ba_data/python/bauiv1lib/league/rankwindow.py b/dist/ba_data/python/bauiv1lib/league/rankwindow.py index f145abb..f27bd4f 100644 --- a/dist/ba_data/python/bauiv1lib/league/rankwindow.py +++ b/dist/ba_data/python/bauiv1lib/league/rankwindow.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """UI related to league rank.""" + # pylint: disable=too-many-lines from __future__ import annotations @@ -9,9 +10,10 @@ import copy import logging from typing import TYPE_CHECKING, override +import bacommon.classic +import bauiv1 as bui from bauiv1lib.utils import scroll_fade_bottom, scroll_fade_top from bauiv1lib.popup import PopupMenu -import bauiv1 as bui if TYPE_CHECKING: from typing import Any @@ -30,6 +32,8 @@ class LeagueRankWindow(bui.MainWindow): plus = bui.app.plus assert plus is not None + self._uiopenstate = bui.UIOpenState('classicleaguerank') + bui.set_analytics_screen('League Rank Window') self._league_rank_data: dict[str, Any] | None = None @@ -216,10 +220,34 @@ class LeagueRankWindow(bui.MainWindow): self._update_for_league_rank_data(info) self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update(show=info is None) + def _on_p_button_info_response( + self, + response: ( + bacommon.classic.GetClassicLeaguePresidentButtonInfoResponse + | Exception + ), + ) -> None: + + # If our window has died, no-op. + if not self._root_widget: + return + + if isinstance(response, Exception) or response.name is None: + bui.textwidget( + edit=self._president_name, color=(0.6, 0.6, 1, 0.2), text='-' + ) + return + + bui.textwidget( + edit=self._president_name, + color=(0.6, 0.6, 1, 0.9), + text=response.name, + ) + @override def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. @@ -381,8 +409,24 @@ class LeagueRankWindow(bui.MainWindow): self._doing_power_ranking_query = True plus.power_ranking_query( season=self._requested_season, - callback=bui.WeakCall(self._on_power_ranking_query_response), + callback=bui.WeakCallPartial( + self._on_power_ranking_query_response + ), ) + # Also kick off a query to v2 for latest league-president + # info. + if plus.accounts.primary is not None: + with plus.accounts.primary: + plus.cloud.send_message_cb( + ( + bacommon.classic + ).GetClassicLeaguePresidentButtonInfoMessage( + season=self._requested_season + ), + on_response=bui.WeakCallPartial( + self._on_p_button_info_response + ), + ) def _refresh(self) -> None: # pylint: disable=too-many-statements @@ -413,7 +457,7 @@ class LeagueRankWindow(bui.MainWindow): v2 = v - 60 worth_color = (0.6, 0.6, 0.65) tally_color = (0.5, 0.6, 0.8) - spc = 43 + spc = 23 h_offs_tally = 150 tally_maxwidth = 120 @@ -440,7 +484,7 @@ class LeagueRankWindow(bui.MainWindow): size=(200, 80), icon=bui.gettexture('achievementsIcon'), autoselect=True, - on_activate_call=bui.WeakCall(self._on_achievements_press), + on_activate_call=bui.WeakCallStrict(self._on_achievements_press), up_widget=self._back_button, left_widget=self._back_button, color=(0.5, 0.5, 0.6), @@ -471,7 +515,7 @@ class LeagueRankWindow(bui.MainWindow): size=(200, 80), icon=bui.gettexture('medalSilver'), autoselect=True, - on_activate_call=bui.WeakCall(self._on_trophies_press), + on_activate_call=bui.WeakCallStrict(self._on_trophies_press), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), @@ -518,7 +562,9 @@ class LeagueRankWindow(bui.MainWindow): icon_color=(0.5, 0, 0.5), label=bui.Lstr(resource='coopSelectWindow.activityText'), autoselect=True, - on_activate_call=bui.WeakCall(self._on_activity_mult_press), + on_activate_call=bui.WeakCallStrict( + self._on_activity_mult_press + ), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), @@ -550,7 +596,9 @@ class LeagueRankWindow(bui.MainWindow): icon_color=(0.3, 0, 0.3), label=bui.Lstr(resource='league.upToDateBonusText'), autoselect=True, - on_activate_call=bui.WeakCall(self._on_up_to_date_bonus_press), + on_activate_call=bui.WeakCallStrict( + self._on_up_to_date_bonus_press + ), left_widget=self._back_button, color=(0.5, 0.5, 0.6), textcolor=(0.7, 0.7, 0.8), @@ -599,6 +647,64 @@ class LeagueRankWindow(bui.MainWindow): maxwidth=tally_maxwidth, ) + self._president_button = bui.buttonwidget( + parent=w_parent, + id=f'{self.main_window_id_prefix}|president', + label='', + position=(self._xoffs + h2 - 60, v2 - 100), + color=(0.7, 0.55, 0.9), + texture=bui.gettexture('buttonSquareWide'), + opacity=0.3, + size=(200, 80), + autoselect=True, + on_activate_call=bui.WeakCallStrict(self._on_president_press), + ) + self._president_label = bui.textwidget( + parent=w_parent, + text=bui.Lstr(resource='league.leaguePresidentText'), + flatness=1.0, + shadow=0.0, + color=(0.6, 0.6, 1, 0.7), + draw_controller=self._president_button, + scale=0.5, + h_align='center', + v_align='center', + maxwidth=140, + position=(self._xoffs + h2 - 60 + 100, v2 - 100 + 59), + size=(0, 0), + ) + self._president_name = bui.textwidget( + parent=w_parent, + text='-', + draw_controller=self._president_button, + color=(0.6, 0.6, 1, 0.2), + flatness=1.0, + shadow=0.0, + h_align='center', + v_align='center', + maxwidth=120, + position=(self._xoffs + h2 - 60 + 100, v2 - 100 + 34), + size=(0, 0), + ) + self._president_star1 = bui.imagewidget( + parent=w_parent, + draw_controller=self._president_button, + texture=bui.gettexture('star'), + color=(0.7, 0.55, 0.9), + opacity=0.2, + position=(self._xoffs + h2 - 60 + 5, v2 - 100 + 17), + size=(32, 32), + ) + self._president_star1 = bui.imagewidget( + parent=w_parent, + draw_controller=self._president_button, + texture=bui.gettexture('star'), + color=(0.7, 0.55, 0.9), + opacity=0.2, + position=(self._xoffs + h2 - 60 + 200 - 5 - 32, v2 - 100 + 17), + size=(32, 32), + ) + self._season_show_text = bui.textwidget( parent=w_parent, position=(self._xoffs + 390 - 15, v - 20), @@ -748,7 +854,44 @@ class LeagueRankWindow(bui.MainWindow): textcolor=(0.7, 0.7, 0.8), size=(230, 60), autoselect=True, - on_activate_call=bui.WeakCall(self._on_more_press), + on_activate_call=bui.WeakCallStrict(self._on_more_press), + ) + + def _on_president_press(self) -> None: + import bacommon.docui.v1 as dui1 + + from bauiv1lib.league.presidency import LeaguePresidencyUIController + from bauiv1lib.connectivity import wait_for_connectivity + + # No-op if we're not in control. + if not self.main_window_has_control(): + return + + plus = bui.app.plus + assert plus is not None + + # We should be signed in at this point, but let's be sure. + if plus.accounts.primary is None: + bui.screenmessage( + bui.Lstr(resource='notSignedInErrorText'), color=(1, 0, 0) + ) + bui.getsound('error').play() + return + + # Wait for connectivity if need be, then bring up a cloud based + # doc-ui window for showing/futzing-with league president stuff. + wait_for_connectivity( + on_connected=lambda: self.main_window_replace( + bui.CallStrict( + LeaguePresidencyUIController().create_window, + dui1.Request('/', args={'season': self._season}), + origin_widget=self._president_button, + auxiliary_style=False, + ), + extra_type_id=( + LeaguePresidencyUIController + ).get_window_extra_type_id(), + ) ) def _on_more_press(self) -> None: @@ -893,7 +1036,9 @@ class LeagueRankWindow(bui.MainWindow): width=150, button_size=(200, 50), choices=season_choices, - on_value_change_call=bui.WeakCall(self._on_season_change), + on_value_change_call=bui.WeakCallPartial( + self._on_season_change + ), choices_display=season_choices_display, current_choice=self._season, ) @@ -1142,7 +1287,7 @@ class LeagueRankWindow(bui.MainWindow): widget.delete() self._power_ranking_score_widgets = [] - scores = data['scores'] if data is not None else [] + scores: list = data['scores'] if data is not None else [] tally_color = (0.5, 0.6, 0.8) w_parent = self._subcontainer v2 = self._power_ranking_score_v @@ -1202,7 +1347,7 @@ class LeagueRankWindow(bui.MainWindow): self._power_ranking_score_widgets.append(txt) bui.textwidget( edit=txt, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._show_account_info, score[4], txt ), ) diff --git a/dist/ba_data/python/bauiv1lib/mainmenu.py b/dist/ba_data/python/bauiv1lib/mainmenu.py index f0e1bb3..d4b7af0 100644 --- a/dist/ba_data/python/bauiv1lib/mainmenu.py +++ b/dist/ba_data/python/bauiv1lib/mainmenu.py @@ -75,9 +75,7 @@ class MainMenuWindow(bui.MainWindow): create_call=lambda transition, origin_widget: cls( transition=transition, origin_widget=origin_widget, - # id_prefix=id_prefix, ), - # restore_selection=True, ) @override @@ -91,13 +89,12 @@ class MainMenuWindow(bui.MainWindow): import bauiv1lib.getremote as _unused import bauiv1lib.confirm as _unused2 import bauiv1lib.account.settings as _unused5 - import bauiv1lib.store.browser as _unused6 - import bauiv1lib.credits as _unused7 - import bauiv1lib.help as _unused8 - import bauiv1lib.settings.allsettings as _unused9 - import bauiv1lib.gather as _unused10 - import bauiv1lib.watch as _unused11 - import bauiv1lib.play as _unused12 + import bauiv1lib.credits as _unused6 + import bauiv1lib.help as _unused7 + import bauiv1lib.settings.allsettings as _unused8 + import bauiv1lib.gather as _unused9 + import bauiv1lib.watch as _unused10 + import bauiv1lib.play as _unused11 def _show_remote_app_info_on_first_launch(self) -> None: app = bui.app @@ -256,7 +253,7 @@ class MainMenuWindow(bui.MainWindow): text=( f'{app.env.engine_version}' f' build {app.env.engine_build_number}.' - f' Copyright 2011-2025 Eric Froemling.' + f' Copyright 2011-2026 Eric Froemling.' ), h_align='center', v_align='center', diff --git a/dist/ba_data/python/bauiv1lib/party.py b/dist/ba_data/python/bauiv1lib/party.py index d1628f7..dbe1453 100644 --- a/dist/ba_data/python/bauiv1lib/party.py +++ b/dist/ba_data/python/bauiv1lib/party.py @@ -21,11 +21,9 @@ if TYPE_CHECKING: class PartyWindow(bui.Window): """Party list/chat window.""" - def __del__(self) -> None: - bui.set_party_window_open(False) - def __init__(self, origin: Sequence[float] = (0, 0)): - bui.set_party_window_open(True) + + self._uiopenstate = bui.UIOpenState('classicparty') self._r = 'partyWindow' self._popup_type: str | None = None self._popup_party_member_client_id: int | None = None @@ -91,7 +89,7 @@ class PartyWindow(bui.Window): label='...', autoselect=True, button_type='square', - on_activate_call=bui.WeakCall(self._on_menu_button_press), + on_activate_call=bui.WeakCallStrict(self._on_menu_button_press), color=(0.55, 0.73, 0.25), iconscale=1.2, ) @@ -213,7 +211,7 @@ class PartyWindow(bui.Window): self._name_widgets: list[bui.Widget] = [] self._roster: list[dict[str, Any]] | None = None self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() @@ -234,7 +232,7 @@ class PartyWindow(bui.Window): maxwidth=self._scroll_width * 0.94, shadow=0.3, flatness=1.0, - on_activate_call=bui.Call(self._copy_msg, msg), + on_activate_call=bui.CallStrict(self._copy_msg, msg), selectable=True, ) @@ -428,7 +426,7 @@ class PartyWindow(bui.Window): # client_id is more readily available though). bui.textwidget( edit=widget, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._on_party_member_press, self._roster[index]['client_id'], is_host, diff --git a/dist/ba_data/python/bauiv1lib/partyqueue.py b/dist/ba_data/python/bauiv1lib/partyqueue.py index 202b138..398c272 100644 --- a/dist/ba_data/python/bauiv1lib/partyqueue.py +++ b/dist/ba_data/python/bauiv1lib/partyqueue.py @@ -69,7 +69,7 @@ class PartyQueueWindow(bui.Window): ) bui.buttonwidget( edit=self._body_image, - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( parent.on_account_press, account_id, self._body_image ), ) @@ -131,7 +131,7 @@ class PartyQueueWindow(bui.Window): widget.delete() bui.pushcall( - bui.Call( + bui.CallStrict( kill_widgets, [ self._body_image, @@ -318,7 +318,7 @@ class PartyQueueWindow(bui.Window): # Update at roughly 30fps. self._update_timer = bui.AppTimer( - 0.033, bui.WeakCall(self.update), repeat=True + 0.033, bui.WeakCallStrict(self.update), repeat=True ) self.update() @@ -591,7 +591,7 @@ class PartyQueueWindow(bui.Window): 't': self._boost_tickets, 'q': self._queue_id, }, - callback=bui.WeakCall(self.on_update_response), + callback=bui.WeakCallPartial(self.on_update_response), ) # Let's not run these immediately (since they may be rapid-fire, # just bucket them until the next tick). @@ -654,7 +654,7 @@ class PartyQueueWindow(bui.Window): self._last_transaction_time = current_time plus.add_v1_account_transaction( {'type': 'PARTY_QUEUE_QUERY', 'q': self._queue_id}, - callback=bui.WeakCall(self.on_update_response), + callback=bui.WeakCallPartial(self.on_update_response), ) plus.run_v1_account_transactions() diff --git a/dist/ba_data/python/bauiv1lib/play.py b/dist/ba_data/python/bauiv1lib/play.py index 5ad3c49..dd509e0 100644 --- a/dist/ba_data/python/bauiv1lib/play.py +++ b/dist/ba_data/python/bauiv1lib/play.py @@ -603,7 +603,7 @@ class PlayWindow(bui.MainWindow): assert plus is not None if plus.get_v1_account_state() != 'signed_in': - show_sign_in_prompt() + show_sign_in_prompt(origin_widget=self._coop_button) return self.main_window_replace( diff --git a/dist/ba_data/python/bauiv1lib/playlist/addgame.py b/dist/ba_data/python/bauiv1lib/playlist/addgame.py index b2457a0..199fab3 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/addgame.py +++ b/dist/ba_data/python/bauiv1lib/playlist/addgame.py @@ -58,7 +58,11 @@ class PlaylistAddGameWindow(bui.MainWindow): root_widget=bui.containerwidget( size=(self._width, self._height), scale=scale, - toolbar_visibility='menu_minimal', + toolbar_visibility=( + 'menu_minimal' + if uiscale is bui.UIScale.SMALL + else 'menu_full' + ), ), transition=transition, origin_widget=origin_widget, @@ -252,7 +256,9 @@ class PlaylistAddGameWindow(bui.MainWindow): v_align='center', color=(0.8, 0.8, 0.8, 1.0), maxwidth=self._scroll_width * 0.8, - on_select_call=bui.Call(self._set_selected_game_type, gametype), + on_select_call=bui.CallStrict( + self._set_selected_game_type, gametype + ), always_highlight=True, selectable=True, on_activate_call=_doit, @@ -277,25 +283,35 @@ class PlaylistAddGameWindow(bui.MainWindow): ) def _on_get_more_games_press(self) -> None: - from bauiv1lib.account.signin import show_sign_in_prompt - from bauiv1lib.store.browser import StoreBrowserWindow + import bacommon.docui.v1 as dui1 - # No-op if we're not in control. - if not self.main_window_has_control(): - return + from bauiv1lib.docui import DocUIWindow + from bauiv1lib.account.signin import show_sign_in_prompt + from bauiv1lib.store import StoreUIController + from bauiv1lib.connectivity import wait_for_connectivity plus = bui.app.plus assert plus is not None - - if plus.get_v1_account_state() != 'signed_in': + if plus.accounts.primary is None: show_sign_in_prompt() return - self.main_window_replace( - lambda: StoreBrowserWindow( - show_tab=StoreBrowserWindow.TabID.MINIGAMES, - origin_widget=self._get_more_games_button, - minimal_toolbars=True, + # Playlist editing happens in the regular non-auxiliary window + # stack so we can just pop up the regular auxiliary-mode store + # and it'll do the right thing and take us back to our editing + # when we close it. + wait_for_connectivity( + on_connected=lambda: bui.app.ui_v1.auxiliary_window_activate( + win_type=DocUIWindow, + win_create_call=bui.CallStrict( + StoreUIController().create_window, + dui1.Request('/'), + origin_widget=self._get_more_games_button, + uiopenstateid='classicstore', + ), + win_extra_type_id=( + StoreUIController.get_window_extra_type_id() + ), ) ) diff --git a/dist/ba_data/python/bauiv1lib/playlist/browser.py b/dist/ba_data/python/bauiv1lib/playlist/browser.py index 77b30d5..d296867 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/browser.py +++ b/dist/ba_data/python/bauiv1lib/playlist/browser.py @@ -190,7 +190,7 @@ class PlaylistBrowserWindow(bui.MainWindow): # refresh). self._update() self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) @override @@ -527,10 +527,12 @@ class PlaylistBrowserWindow(bui.MainWindow): ) bui.buttonwidget( edit=btn, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._on_playlist_press, btn, name ), - on_select_call=bui.Call(self._on_playlist_select, name), + on_select_call=bui.CallStrict( + self._on_playlist_select, name + ), ) # Top row biases things up more to show header above it. diff --git a/dist/ba_data/python/bauiv1lib/playlist/customizebrowser.py b/dist/ba_data/python/bauiv1lib/playlist/customizebrowser.py index a8b2476..1ba27a7 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/customizebrowser.py +++ b/dist/ba_data/python/bauiv1lib/playlist/customizebrowser.py @@ -16,8 +16,6 @@ if TYPE_CHECKING: import bascenev1 as bs -REQUIRE_PRO = False - class PlaylistCustomizeBrowserWindow(bui.MainWindow): """Window for viewing a playlist.""" @@ -275,7 +273,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): # Keep our lock images up to date/etc. self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() @@ -310,12 +308,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): cfg.commit() def _update(self) -> None: - assert bui.app.classic is not None - have = bui.app.classic.accounts.have_pro_options() for lock in self._lock_images: - bui.imagewidget( - edit=lock, opacity=0.0 if (have or not REQUIRE_PRO) else 1.0 - ) + bui.imagewidget(edit=lock, opacity=0.0) # No more pro req. def _select(self, name: str, index: int) -> None: self._selected_playlist_name = name @@ -365,8 +359,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): else (0.85, 0.85, 0.85, 1) ), always_highlight=True, - on_select_call=bui.Call(self._select, pname, index), - on_activate_call=bui.Call(self._edit_button.activate), + on_select_call=bui.CallStrict(self._select, pname, index), + on_activate_call=bui.CallStrict(self._edit_button.activate), selectable=True, ) # We don't give these widgets ids because we handle @@ -437,17 +431,11 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): def _new_playlist(self) -> None: # pylint: disable=cyclic-import from bauiv1lib.playlist.editcontroller import PlaylistEditController - from bauiv1lib.purchase import PurchaseWindow # No-op if we're not in control. if not self.main_window_has_control(): return - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): - PurchaseWindow(items=['pro']) - return - # Clamp at our max playlist number. if len(bui.app.config[self._config_name_full]) > self._max_playlists: bui.screenmessage( @@ -471,12 +459,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): def _edit_playlist(self) -> None: # pylint: disable=cyclic-import from bauiv1lib.playlist.editcontroller import PlaylistEditController - from bauiv1lib.purchase import PurchaseWindow - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): - PurchaseWindow(items=['pro']) - return if self._selected_playlist_name is None: return if self._selected_playlist_name == '__default__': @@ -530,7 +513,9 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): share.SharePlaylistImportWindow( origin_widget=self._import_button, - on_success_callback=bui.WeakCall(self._on_playlist_import_success), + on_success_callback=bui.WeakCallStrict( + self._on_playlist_import_success + ), ) def _on_playlist_import_success(self) -> None: @@ -550,17 +535,9 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): share.SharePlaylistResultsWindow(name, response) def _share_playlist(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow - plus = bui.app.plus assert plus is not None - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): - PurchaseWindow(items=['pro']) - return - # Gotta be signed in for this to work. if plus.get_v1_account_state() != 'signed_in': bui.screenmessage( @@ -586,7 +563,7 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): 'playlistType': self._pvars.config_name, 'playlistName': self._selected_playlist_name, }, - callback=bui.WeakCall( + callback=bui.WeakCallPartial( self._on_share_playlist_response, self._selected_playlist_name ), ) @@ -594,15 +571,8 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): bui.screenmessage(bui.Lstr(resource='sharingText')) def _delete_playlist(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow from bauiv1lib.confirm import ConfirmWindow - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): - PurchaseWindow(items=['pro']) - return - if self._selected_playlist_name is None: return if self._selected_playlist_name == '__default__': @@ -631,17 +601,9 @@ class PlaylistCustomizeBrowserWindow(bui.MainWindow): ) def _duplicate_playlist(self) -> None: - # pylint: disable=too-many-branches - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow - plus = bui.app.plus assert plus is not None - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro_options(): - PurchaseWindow(items=['pro']) - return if self._selected_playlist_name is None: return plst: list[dict[str, Any]] | None diff --git a/dist/ba_data/python/bauiv1lib/playlist/edit.py b/dist/ba_data/python/bauiv1lib/playlist/edit.py index 88735e4..7c8c95b 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/edit.py +++ b/dist/ba_data/python/bauiv1lib/playlist/edit.py @@ -49,8 +49,10 @@ class PlaylistEditWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), - stack_offset=( - (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0) + toolbar_visibility=( + 'menu_minimal_no_back' + if uiscale is bui.UIScale.SMALL + else 'menu_full' ), ), transition=transition, @@ -156,7 +158,7 @@ class PlaylistEditWindow(bui.MainWindow): position=(h, v), size=(110, 61.0 * scl), on_activate_call=self._add, - on_select_call=bui.Call(self._set_ui_selection, 'add_button'), + on_select_call=bui.CallStrict(self._set_ui_selection, 'add_button'), autoselect=True, button_type='square', color=b_color, @@ -172,7 +174,7 @@ class PlaylistEditWindow(bui.MainWindow): position=(h, v), size=(110, 61.0 * scl), on_activate_call=self._edit, - on_select_call=bui.Call(self._set_ui_selection, 'editButton'), + on_select_call=bui.CallStrict(self._set_ui_selection, 'editButton'), autoselect=True, button_type='square', color=b_color, @@ -230,7 +232,7 @@ class PlaylistEditWindow(bui.MainWindow): parent=self._root_widget, position=(160 + x_inset, v - scroll_height), highlight=False, - on_select_call=bui.Call(self._set_ui_selection, 'gameList'), + on_select_call=bui.CallStrict(self._set_ui_selection, 'gameList'), size=(self._scroll_width, (scroll_height - 15)), border_opacity=0.4, ) @@ -415,7 +417,7 @@ class PlaylistEditWindow(bui.MainWindow): txtw = bui.textwidget( parent=self._columnwidget, size=(self._width - 80, 30), - on_select_call=bui.Call(self._select, index), + on_select_call=bui.CallStrict(self._select, index), always_highlight=True, color=(0.8, 0.8, 0.8, 1.0), padding=0, diff --git a/dist/ba_data/python/bauiv1lib/playlist/editgame.py b/dist/ba_data/python/bauiv1lib/playlist/editgame.py index f83b2a4..9fc6869 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/editgame.py +++ b/dist/ba_data/python/bauiv1lib/playlist/editgame.py @@ -132,8 +132,10 @@ class PlaylistEditGameWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ), - stack_offset=( - (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0) + toolbar_visibility=( + 'menu_minimal_no_back' + if uiscale is bui.UIScale.SMALL + else 'menu_full' ), ), transition=transition, @@ -153,7 +155,7 @@ class PlaylistEditGameWindow(bui.MainWindow): autoselect=True, scale=1.0 if is_add else 0.75, text_scale=1.3, - on_activate_call=bui.Call(self._cancel), + on_activate_call=bui.CallStrict(self._cancel), ) bui.containerwidget(edit=self._root_widget, cancel_button=btn) @@ -248,7 +250,7 @@ class PlaylistEditGameWindow(bui.MainWindow): parent=self._subcontainer, size=(140, 60), position=(h + 448, v - 72), - on_activate_call=bui.Call(self._select_map), + on_activate_call=bui.CallStrict(self._select_map), scale=0.7, label=bui.Lstr(resource='mapSelectText'), ) @@ -359,7 +361,7 @@ class PlaylistEditGameWindow(bui.MainWindow): size=(28, 28), label='<', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._choice_inc, setting.name, txt, setting, -1 ), repeat=True, @@ -370,7 +372,7 @@ class PlaylistEditGameWindow(bui.MainWindow): size=(28, 28), label='>', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._choice_inc, setting.name, txt, setting, 1 ), repeat=True, @@ -410,7 +412,7 @@ class PlaylistEditGameWindow(bui.MainWindow): size=(28, 28), label='-', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._inc, txt, min_value, @@ -427,7 +429,7 @@ class PlaylistEditGameWindow(bui.MainWindow): size=(28, 28), label='+', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._inc, txt, min_value, @@ -476,7 +478,7 @@ class PlaylistEditGameWindow(bui.MainWindow): autoselect=True, textcolor=(0.8, 0.8, 0.8), value=value, - on_value_change_call=bui.Call( + on_value_change_call=bui.CallPartial( self._check_value_change, setting.name, txt ), ) @@ -503,7 +505,9 @@ class PlaylistEditGameWindow(bui.MainWindow): 'Error wiring up game-settings-select widget column.' ) - bui.buttonwidget(edit=add_button, on_activate_call=bui.Call(self._add)) + bui.buttonwidget( + edit=add_button, on_activate_call=bui.CallStrict(self._add) + ) bui.containerwidget( edit=self._root_widget, selected_child=add_button, diff --git a/dist/ba_data/python/bauiv1lib/playlist/mapselect.py b/dist/ba_data/python/bauiv1lib/playlist/mapselect.py index ad60a2a..8895f6c 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/mapselect.py +++ b/dist/ba_data/python/bauiv1lib/playlist/mapselect.py @@ -67,8 +67,10 @@ class PlaylistMapSelectWindow(bui.MainWindow): if uiscale is bui.UIScale.SMALL else 1.3 if uiscale is bui.UIScale.MEDIUM else 1.0 ), - stack_offset=( - (0, 0) if uiscale is bui.UIScale.SMALL else (0, 0) + toolbar_visibility=( + 'menu_minimal_no_back' + if uiscale is bui.UIScale.SMALL + else 'menu_full' ), ), transition=transition, @@ -230,7 +232,7 @@ class PlaylistMapSelectWindow(bui.MainWindow): mesh_transparent=mesh_transparent, label='', color=(1, 1, 1), - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._select_with_delay, self._maps[index][0] ), position=pos, @@ -288,8 +290,12 @@ class PlaylistMapSelectWindow(bui.MainWindow): ) def _on_store_press(self) -> None: + import bacommon.docui.v1 as dui1 + + from bauiv1lib.docui import DocUIWindow + from bauiv1lib.connectivity import wait_for_connectivity + from bauiv1lib.store import StoreUIController from bauiv1lib.account.signin import show_sign_in_prompt - from bauiv1lib.store.browser import StoreBrowserWindow # No-op if we're not in control. if not self.main_window_has_control(): @@ -298,17 +304,28 @@ class PlaylistMapSelectWindow(bui.MainWindow): plus = bui.app.plus assert plus is not None - if plus.get_v1_account_state() != 'signed_in': + if plus.accounts.primary is None: show_sign_in_prompt() return self._selected_get_more_maps = True - self.main_window_replace( - lambda: StoreBrowserWindow( - show_tab=StoreBrowserWindow.TabID.MAPS, - origin_widget=self._get_more_maps_button, - minimal_toolbars=True, + # Playlist editing happens in the regular non-auxiliary window + # stack so we can just pop up the regular auxiliary-mode store + # and it'll do the right thing and take us back to our editing + # when we close it. + wait_for_connectivity( + on_connected=lambda: bui.app.ui_v1.auxiliary_window_activate( + win_type=DocUIWindow, + win_create_call=bui.CallStrict( + StoreUIController().create_window, + dui1.Request('/'), + origin_widget=self._get_more_maps_button, + uiopenstateid='classicstore', + ), + win_extra_type_id=( + StoreUIController.get_window_extra_type_id() + ), ) ) @@ -324,4 +341,4 @@ class PlaylistMapSelectWindow(bui.MainWindow): def _select_with_delay(self, map_name: str) -> None: bui.lock_all_input() bui.apptimer(0.1, bui.unlock_all_input) - bui.apptimer(0.1, bui.WeakCall(self._select, map_name)) + bui.apptimer(0.1, bui.WeakCallStrict(self._select, map_name)) diff --git a/dist/ba_data/python/bauiv1lib/playlist/share.py b/dist/ba_data/python/bauiv1lib/playlist/share.py index 9e429cf..03fc597 100644 --- a/dist/ba_data/python/bauiv1lib/playlist/share.py +++ b/dist/ba_data/python/bauiv1lib/playlist/share.py @@ -67,7 +67,7 @@ class SharePlaylistImportWindow(SendInfoWindowLegacyModal): 'expire_time': time.time() + 5, 'code': bui.textwidget(query=self._text_field), }, - callback=bui.WeakCall(self._on_import_response), + callback=bui.WeakCallPartial(self._on_import_response), ) plus.run_v1_account_transactions() bui.screenmessage(bui.Lstr(resource='importingText')) diff --git a/dist/ba_data/python/bauiv1lib/playoptions.py b/dist/ba_data/python/bauiv1lib/playoptions.py index 70fcae0..d333c0d 100644 --- a/dist/ba_data/python/bauiv1lib/playoptions.py +++ b/dist/ba_data/python/bauiv1lib/playoptions.py @@ -7,6 +7,7 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING, override +from bacommon.analytics import ClassicAnalyticsEvent import bascenev1 as bs import bauiv1 as bui @@ -17,8 +18,6 @@ if TYPE_CHECKING: from bauiv1lib.play import PlaylistSelectContext -REQUIRE_PRO = False - class PlayOptionsWindow(PopupWindow): """A popup window for configuring play options.""" @@ -240,7 +239,7 @@ class PlayOptionsWindow(PopupWindow): position=(h, v), texture=bui.gettexture(tex_name if owned else 'empty'), mesh_opaque=mesh_opaque if owned else None, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( bui.screenmessage, desc, desc_color ), label='', @@ -316,7 +315,9 @@ class PlayOptionsWindow(PopupWindow): parent=self.root_widget, position=(100, 195 + y_offs), size=(290, 35), - on_activate_call=bui.WeakCall(self._custom_colors_names_press), + on_activate_call=bui.WeakCallStrict( + self._custom_colors_names_press + ), autoselect=True, textcolor=(0.8, 0.8, 0.8), label=bui.Lstr(resource='teamNamesColorText'), @@ -325,16 +326,6 @@ class PlayOptionsWindow(PopupWindow): edit=self._custom_colors_names_button, allow_preserve_selection=False, ) - - assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro(): - bui.imagewidget( - parent=self.root_widget, - size=(30, 30), - position=(95, 202 + y_offs), - texture=bui.gettexture('lock'), - draw_controller=self._custom_colors_names_button, - ) else: self._custom_colors_names_button = None @@ -439,26 +430,17 @@ class PlayOptionsWindow(PopupWindow): # Update now and once per second. self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() def _custom_colors_names_press(self) -> None: - from bauiv1lib.account.signin import show_sign_in_prompt from bauiv1lib.teamnamescolors import TeamNamesColorsWindow - from bauiv1lib.purchase import PurchaseWindow plus = bui.app.plus assert plus is not None assert bui.app.classic is not None - if REQUIRE_PRO and not bui.app.classic.accounts.have_pro(): - if plus.get_v1_account_state() != 'signed_in': - show_sign_in_prompt() - else: - PurchaseWindow(items=['pro']) - self._transition_out() - return assert self._custom_colors_names_button TeamNamesColorsWindow( scale_origin=( @@ -544,6 +526,21 @@ class PlayOptionsWindow(PopupWindow): if bs.app.classic is not None: bs.app.classic.save_ui_state() + # Log analytics for when teams/ffa sessions are started from the + # UI. + if self._sessiontype is bs.FreeForAllSession: + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.START_FFA_SESSION + ) + ) + elif self._sessiontype is bs.DualTeamSession: + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.START_TEAMS_SESSION + ) + ) + try: bs.new_host_session(self._sessiontype) except Exception: diff --git a/dist/ba_data/python/bauiv1lib/popup.py b/dist/ba_data/python/bauiv1lib/popup.py index dfc87d5..b1f5774 100644 --- a/dist/ba_data/python/bauiv1lib/popup.py +++ b/dist/ba_data/python/bauiv1lib/popup.py @@ -234,7 +234,7 @@ class PopupMenuWindow(PopupWindow): wdg = bui.textwidget( parent=self._columnwidget, size=(self._width - 40, 28), - on_select_call=bui.Call(self._select, index), + on_select_call=bui.CallStrict(self._select, index), click_activate=True, color=( (0.5, 0.5, 0.5, 0.5) @@ -277,7 +277,7 @@ class PopupMenuWindow(PopupWindow): if delegate is not None: # Call this in a timer so it doesn't interfere with us killing # our widgets and whatnot. - call = bui.Call( + call = bui.CallStrict( delegate.popup_menu_selected_choice, self, self._current_choice ) bui.apptimer(0, call) diff --git a/dist/ba_data/python/bauiv1lib/profile/edit.py b/dist/ba_data/python/bauiv1lib/profile/edit.py index 275e269..2f652d1 100644 --- a/dist/ba_data/python/bauiv1lib/profile/edit.py +++ b/dist/ba_data/python/bauiv1lib/profile/edit.py @@ -1,47 +1,43 @@ # Released under the MIT License. See LICENSE for details. # +# pylint: disable=too-many-lines """Provides UI to edit a player profile.""" from __future__ import annotations import random -from typing import cast, override +from typing import cast, override, TYPE_CHECKING from bauiv1lib.colorpicker import ColorPicker from bauiv1lib.characterpicker import CharacterPickerDelegate from bauiv1lib.iconpicker import IconPickerDelegate +from bauiv1lib.connectivity import wait_for_connectivity import bauiv1 as bui import bascenev1 as bs +if TYPE_CHECKING: + from typing import Callable + class EditProfileWindow( bui.MainWindow, CharacterPickerDelegate, IconPickerDelegate ): """Window for editing a player profile.""" - def reload_window(self) -> None: - """Transitions out and recreates ourself.""" - - # Replace ourself with ourself, but keep the same back location. - assert self.main_window_back_state is not None - self.main_window_replace( - lambda: EditProfileWindow(self.getname()), - back_state=self.main_window_back_state, - ) - def __init__( self, existing_profile: str | None, + *, transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, + on_profile_save: Callable[[str], None] | None = None, + on_profile_delete: Callable[[str], None] | None = None, ): - # FIXME: Tidy this up a bit. # pylint: disable=too-many-branches # pylint: disable=too-many-statements # pylint: disable=too-many-locals assert bui.app.classic is not None - # print(f'EditProfileWindow({id(self)})') plus = bui.app.plus assert plus is not None @@ -51,6 +47,8 @@ class EditProfileWindow( self._spazzes: list[str] = [] self._icon_textures: list[bui.Texture] = [] self._icon_tint_textures: list[bui.Texture] = [] + self._on_profile_save = on_profile_save + self._on_profile_delete = on_profile_delete # Grab profile colors or pick random ones. ( @@ -58,17 +56,17 @@ class EditProfileWindow( self._highlight, ) = bui.app.classic.get_player_profile_colors(existing_profile) uiscale = bui.app.ui_v1.uiscale - self._width = width = 880.0 if uiscale is bui.UIScale.SMALL else 680.0 - self._x_inset = x_inset = 100.0 if uiscale is bui.UIScale.SMALL else 0.0 + self._width = width = 1000.0 if uiscale is bui.UIScale.SMALL else 680.0 + self._x_inset = x_inset = 140.0 if uiscale is bui.UIScale.SMALL else 0.0 self._height = height = ( 500.0 if uiscale is bui.UIScale.SMALL - else 400.0 if uiscale is bui.UIScale.MEDIUM else 450.0 + else 450.0 if uiscale is bui.UIScale.MEDIUM else 450.0 ) - yoffs = -42 if uiscale is bui.UIScale.SMALL else 0 + yoffs = 2 if uiscale is bui.UIScale.SMALL else 0 spacing = 40 self._base_scale = ( - 2.0 + 1.72 if uiscale is bui.UIScale.SMALL else 1.35 if uiscale is bui.UIScale.MEDIUM else 1.0 ) @@ -101,6 +99,7 @@ class EditProfileWindow( scale=0.8, label=bui.Lstr(resource='saveText'), ) + bui.widget(edit=save_button, left_widget=cancel_button) bui.widget(edit=cancel_button, right_widget=save_button) bui.containerwidget(edit=self._root_widget, start_button=btn) @@ -347,7 +346,7 @@ class EditProfileWindow( editable=True, padding=4, color=(0.9, 0.9, 0.9, 1.0), - on_return_press_call=bui.Call(save_button.activate), + on_return_press_call=bui.CallStrict(save_button.activate), ) # FIXME hard coded strings are bad @@ -404,7 +403,7 @@ class EditProfileWindow( self._update_clipped_name() self._clipped_name_timer = bui.AppTimer( - 0.333, bui.WeakCall(self._update_clipped_name), repeat=True + 0.333, bui.WeakCallStrict(self._update_clipped_name), repeat=True ) v -= spacing * 3.0 @@ -423,7 +422,9 @@ class EditProfileWindow( origin = self._color_button.get_screen_space_center() bui.buttonwidget( edit=self._color_button, - on_activate_call=bui.WeakCall(self._make_picker, 'color', origin), + on_activate_call=bui.WeakCallStrict( + self._make_picker, 'color', origin + ), ) bui.textwidget( parent=self._root_widget, @@ -493,7 +494,7 @@ class EditProfileWindow( origin = self._highlight_button.get_screen_space_center() bui.buttonwidget( edit=self._highlight_button, - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._make_picker, 'highlight', origin ), ) @@ -509,8 +510,102 @@ class EditProfileWindow( color=bui.app.ui_v1.title_color, maxwidth=120, ) + + if existing_profile is not None: + bui.buttonwidget( + parent=self._root_widget, + position=(self._width * 0.5 - 43, v - 185), + size=(140, 60), + autoselect=True, + scale=0.6, + color=( + (0.5, 0.5, 0.5) + if self._is_account_profile + else (0.65, 0.45, 0.5) + ), + textcolor=( + (0.5, 0.5, 0.5) + if self._is_account_profile + else (1.0, 0.5, 0.5) + ), + label=bui.Lstr(resource='deleteText'), + on_activate_call=bui.WeakCallStrict(self._delete_press), + enable_sound=not self._is_account_profile, + ) + self._update_character() + def reload_window(self) -> None: + """Transitions out and recreates ourself.""" + + # Replace ourself with ourself, but keep the same back location. + assert self.main_window_back_state is not None + self.main_window_replace( + lambda: EditProfileWindow(self.getname()), + back_state=self.main_window_back_state, + ) + + def _delete_press(self) -> None: + # pylint: disable=cyclic-import + from bauiv1lib.confirm import ConfirmWindow + + if self._is_account_profile: + bui.getsound('error').play() + bui.screenmessage( + bui.Lstr( + resource='playerProfilesWindow.cantDeleteAccountProfileText' + ), + color=(1, 0, 0), + ) + return + + if self._existing_profile is None: + bui.getsound('error').play() + bui.screenmessage( + bui.Lstr(resource='nothingIsSelectedErrorText'), color=(1, 0, 0) + ) + return + ConfirmWindow( + bui.Lstr( + resource='playerProfilesWindow.deleteConfirmText', + subs=[('${PROFILE}', self._existing_profile)], + ), + self._do_delete_profile, + width=350, + ) + + def _do_delete_profile(self) -> None: + plus = bui.app.plus + assert plus is not None + + assert self._existing_profile is not None + + # Play a death sound of the character. + classic = bui.app.classic + if classic is not None: + profiles = bui.app.config.get('Player Profiles', {}) + p_info = profiles.get(self._existing_profile) + if p_info: + char = p_info.get('character', 'Spaz') + appearance = classic.spaz_appearances.get(char) + if appearance: + bui.getsound(random.choice(appearance.death_sounds)).play() + + plus.add_v1_account_transaction( + {'type': 'REMOVE_PLAYER_PROFILE', 'name': self._existing_profile} + ) + + plus.run_v1_account_transactions() + bui.getsound('shieldDown').play() + + if self._on_profile_delete is not None: + try: + self._on_profile_delete(self._existing_profile) + except Exception: + bui.balog.exception('Error in _on_profile_delete cb.') + + self.main_window_back() + @override def get_main_window_state(self) -> bui.MainWindowState: # Support recreating our window for back/refresh purposes. @@ -518,6 +613,8 @@ class EditProfileWindow( # Pull things out of self here; if we do it within the lambda # we'll keep ourself alive which is bad. + on_profile_save = self._on_profile_save + on_profile_delete = self._on_profile_delete existing_profile = self._existing_profile return bui.BasicMainWindowState( @@ -525,6 +622,8 @@ class EditProfileWindow( transition=transition, origin_widget=origin_widget, existing_profile=existing_profile, + on_profile_save=on_profile_save, + on_profile_delete=on_profile_delete, ) ) @@ -648,12 +747,30 @@ class EditProfileWindow( @override def on_icon_picker_get_more_press(self) -> None: """User wants to get more icons.""" - from bauiv1lib.store.browser import StoreBrowserWindow + import bacommon.docui.v1 as dui1 - self.main_window_replace( - lambda: StoreBrowserWindow( - minimal_toolbars=True, - show_tab=StoreBrowserWindow.TabID.ICONS, + from bauiv1lib.store import StoreUIController + + if not self._ensure_signed_in( + origin_widget=bui.get_special_widget('store_button') + ): + return + + # Because profile editing is happening within an auxiliary + # window stack, we need to bring up the store as a regular + # non-auxiliary window pushed onto our stack. If we did the + # simple thing and triggered it as an auxiliary window then it + # would *replace* our stack and we wouldn't be able to get back + # to our editing. + wait_for_connectivity( + on_connected=lambda: self.main_window_replace( + bui.CallStrict( + StoreUIController().create_window, + dui1.Request('/'), + origin_widget=bui.get_special_widget('store_button'), + auxiliary_style=False, + ), + extra_type_id=StoreUIController.get_window_extra_type_id(), ) ) @@ -671,14 +788,46 @@ class EditProfileWindow( ) self._update_character() + def _ensure_signed_in( + self, *, origin_widget: bui.Widget | None = None + ) -> bool: + """Make sure we're signed in (requiring modern v2 accounts).""" + from bauiv1lib.account.signin import show_sign_in_prompt + + plus = bui.app.plus + if plus is None: + bui.screenmessage('This requires plus.', color=(1, 0, 0)) + bui.getsound('error').play() + return False + if plus.accounts.primary is None: + show_sign_in_prompt(origin_widget=origin_widget) + return False + return True + @override def on_character_picker_get_more_press(self) -> None: - from bauiv1lib.store.browser import StoreBrowserWindow + import bacommon.docui.v1 as dui1 - self.main_window_replace( - lambda: StoreBrowserWindow( - minimal_toolbars=True, - show_tab=StoreBrowserWindow.TabID.CHARACTERS, + from bauiv1lib.store import StoreUIController + + if not self._ensure_signed_in( + origin_widget=bui.get_special_widget('store_button') + ): + return + + # Set this up as a non-auxiliary window so we can nav back to + # char editing (otherwise it would replace the whole inventory + # stack). Also don't set uiopenstateid in this case since we don't + # want store button to glow (since inventory button already is). + wait_for_connectivity( + on_connected=lambda: self.main_window_replace( + bui.CallStrict( + StoreUIController().create_window, + dui1.Request('/'), + origin_widget=bui.get_special_widget('store_button'), + auxiliary_style=False, + ), + extra_type_id=StoreUIController.get_window_extra_type_id(), ) ) @@ -824,9 +973,6 @@ class EditProfileWindow( def save(self, transition_out: bool = True) -> bool: """Save has been selected.""" - # pylint: disable=cyclic-import - - from bauiv1lib.profile.browser import ProfileBrowserWindow # no-op if our underlying widget is dead or on its way out. if not self._root_widget or self._root_widget.transitioning_out: @@ -851,8 +997,11 @@ class EditProfileWindow( bui.getsound('error').play() return False - # Set the profile-browser to have this one selected by default. - ProfileBrowserWindow.selected_profile = new_name + if self._on_profile_save is not None: + try: + self._on_profile_save(new_name) + except Exception: + bui.balog.exception('Error in _on_profile_save cb.') if transition_out: bui.getsound('gunCocking').play() diff --git a/dist/ba_data/python/bauiv1lib/profile/upgrade.py b/dist/ba_data/python/bauiv1lib/profile/upgrade.py index 0866f68..06a2900 100644 --- a/dist/ba_data/python/bauiv1lib/profile/upgrade.py +++ b/dist/ba_data/python/bauiv1lib/profile/upgrade.py @@ -8,7 +8,7 @@ import time import weakref from typing import TYPE_CHECKING -import bacommon.bs +import bacommon.classic import bauiv1 as bui @@ -142,20 +142,20 @@ class ProfileUpgradeWindow(bui.Window): assert plus.accounts.primary is not None with plus.accounts.primary: plus.cloud.send_message_cb( - bacommon.bs.GlobalProfileCheckMessage(self._name), - on_response=bui.WeakCall( + bacommon.classic.GlobalProfileCheckMessage(self._name), + on_response=bui.WeakCallPartial( self._on_global_profile_check_response ), ) self._status: str | None = 'waiting' self._update_timer = bui.AppTimer( - 1.023, bui.WeakCall(self._update), repeat=True + 1.023, bui.WeakCallStrict(self._update), repeat=True ) self._update() def _on_global_profile_check_response( - self, response: bacommon.bs.GlobalProfileCheckResponse | Exception + self, response: bacommon.classic.GlobalProfileCheckResponse | Exception ) -> None: if isinstance(response, Exception): bui.textwidget( diff --git a/dist/ba_data/python/bauiv1lib/qrcode.py b/dist/ba_data/python/bauiv1lib/qrcode.py index c76749c..aac2546 100644 --- a/dist/ba_data/python/bauiv1lib/qrcode.py +++ b/dist/ba_data/python/bauiv1lib/qrcode.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides functionality for displaying QR codes.""" + from __future__ import annotations from typing import override diff --git a/dist/ba_data/python/bauiv1lib/radiogroup.py b/dist/ba_data/python/bauiv1lib/radiogroup.py index 6492786..e1236d3 100644 --- a/dist/ba_data/python/bauiv1lib/radiogroup.py +++ b/dist/ba_data/python/bauiv1lib/radiogroup.py @@ -33,7 +33,7 @@ def make_radio_group( edit=check_box, value=(value == value_names[i]), is_radio_button=True, - on_value_change_call=bui.Call( + on_value_change_call=bui.CallPartial( _radio_press, value_names[i], [c for c in check_boxes if c != check_box], diff --git a/dist/ba_data/python/bauiv1lib/resourcetypeinfo.py b/dist/ba_data/python/bauiv1lib/resourcetypeinfo.py index c5eb343..a3bb211 100644 --- a/dist/ba_data/python/bauiv1lib/resourcetypeinfo.py +++ b/dist/ba_data/python/bauiv1lib/resourcetypeinfo.py @@ -22,6 +22,9 @@ class ResourceTypeInfoWindow(PopupWindow): origin_widget: bui.Widget, ): assert bui.app.classic is not None + + self._uiopenstate = bui.UIOpenState(f'resourcetypeinfo{resource_type}') + uiscale = bui.app.ui_v1.uiscale scale = ( 2.0 @@ -87,7 +90,9 @@ class ResourceTypeInfoWindow(PopupWindow): label=bui.Lstr(resource='tokens.getTokensText'), size=(bwidth, bheight), autoselect=True, - on_activate_call=bui.WeakCall(self._on_get_tokens_press), + on_activate_call=bui.WeakCallStrict( + self._on_get_tokens_press + ), ) elif resource_type == 'trophies': diff --git a/dist/ba_data/python/bauiv1lib/sendinfo.py b/dist/ba_data/python/bauiv1lib/sendinfo.py index ddb63cc..7eb3281 100644 --- a/dist/ba_data/python/bauiv1lib/sendinfo.py +++ b/dist/ba_data/python/bauiv1lib/sendinfo.py @@ -377,7 +377,7 @@ class SendInfoWindowLegacyModal(bui.Window): async def _send_info(description: str) -> None: - from bacommon.bs import SendInfoMessage + from bacommon.classic import SendInfoMessage plus = bui.app.plus assert plus is not None diff --git a/dist/ba_data/python/bauiv1lib/settings/advanced.py b/dist/ba_data/python/bauiv1lib/settings/advanced.py index d7a3f2b..4dd4420 100644 --- a/dist/ba_data/python/bauiv1lib/settings/advanced.py +++ b/dist/ba_data/python/bauiv1lib/settings/advanced.py @@ -10,9 +10,9 @@ import logging from typing import TYPE_CHECKING, override from bacommon.locale import LocaleResolved -from bauiv1lib.popup import PopupMenu -from bauiv1lib.utils import scroll_fade_bottom, scroll_fade_top import bauiv1 as bui +from bauiv1lib.utils import scroll_fade_bottom, scroll_fade_top +from bauiv1lib.popup import PopupMenu if TYPE_CHECKING: from typing import Any @@ -216,14 +216,14 @@ class AdvancedSettingsWindow(bui.MainWindow): # Rebuild periodically to pick up language changes/additions/etc. self._rebuild_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._rebuild), repeat=True + 1.0, bui.WeakCallStrict(self._rebuild), repeat=True ) # Fetch the list of completed languages. bui.app.classic.master_server_v1_get( 'bsLangGetCompleted', {'b': app.env.engine_build_number}, - callback=bui.WeakCall(self._completed_langs_cb), + callback=bui.WeakCallPartial(self._completed_langs_cb), ) @override @@ -414,10 +414,10 @@ class AdvancedSettingsWindow(bui.MainWindow): button_id=f'{self.main_window_id_prefix}|language', position=(210, v - 19), width=250, - opening_call=bui.WeakCall(self._on_menu_open), - closing_call=bui.WeakCall(self._on_menu_close), + opening_call=bui.WeakCallStrict(self._on_menu_open), + closing_call=bui.WeakCallStrict(self._on_menu_close), autoselect=True, - on_value_change_call=bui.WeakCall(self._on_menu_choice), + on_value_change_call=bui.WeakCallPartial(self._on_menu_choice), choices=['Auto'] + available_languages, button_size=(300, 60), choices_display=( @@ -478,7 +478,7 @@ class AdvancedSettingsWindow(bui.MainWindow): subs=[('${APP_NAME}', bui.Lstr(resource='titleText'))], ), autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( bui.open_url, 'https://legacy.ballistica.net/translate' ), ) @@ -509,7 +509,7 @@ class AdvancedSettingsWindow(bui.MainWindow): textcolor=(0.8, 0.8, 0.8), value=lang_inform, text=bui.Lstr(resource=f'{self._r}.translationInformMe'), - on_value_change_call=bui.WeakCall( + on_value_change_call=bui.WeakCallPartial( self._on_lang_inform_value_change ), ) @@ -686,7 +686,7 @@ class AdvancedSettingsWindow(bui.MainWindow): autoselect=True, label=bui.Lstr(resource=f'{self._r}.moddingGuideText'), text_scale=1.0, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( bui.open_url, 'https://ballistica.net/wiki/modding-guide' ), ) @@ -913,7 +913,7 @@ class AdvancedSettingsWindow(bui.MainWindow): self.main_window_save_shared_state() - bui.apptimer(0.1, bui.WeakCall(self._rebuild)) + bui.apptimer(0.1, bui.WeakCallStrict(self._rebuild)) def _completed_langs_cb(self, results: dict[str, Any] | None) -> None: if results is not None and results['langs'] is not None: @@ -922,4 +922,4 @@ class AdvancedSettingsWindow(bui.MainWindow): else: self._complete_langs_list = None self._complete_langs_error = True - bui.apptimer(0.001, bui.WeakCall(self._update_lang_status)) + bui.apptimer(0.001, bui.WeakCallStrict(self._update_lang_status)) diff --git a/dist/ba_data/python/bauiv1lib/settings/allsettings.py b/dist/ba_data/python/bauiv1lib/settings/allsettings.py index 7065061..2f92110 100644 --- a/dist/ba_data/python/bauiv1lib/settings/allsettings.py +++ b/dist/ba_data/python/bauiv1lib/settings/allsettings.py @@ -27,6 +27,8 @@ class AllSettingsWindow(bui.MainWindow): # have a visual hitch when the user taps them. bui.app.threadpool.submit_no_wait(self._preload_modules) + self._uiopenstate = bui.UIOpenState('settings') + bui.set_analytics_screen('Settings Window') assert bui.app.classic is not None uiscale = bui.app.ui_v1.uiscale @@ -245,7 +247,10 @@ class AllSettingsWindow(bui.MainWindow): return bui.BasicMainWindowState( create_call=lambda transition, origin_widget: cls( transition=transition, origin_widget=origin_widget - ) + ), + # Keeps our icon glowing as long as this is in the back + # stack. + uiopenstate=self._uiopenstate, ) @override diff --git a/dist/ba_data/python/bauiv1lib/settings/audio.py b/dist/ba_data/python/bauiv1lib/settings/audio.py index 14bf15c..97c897a 100644 --- a/dist/ba_data/python/bauiv1lib/settings/audio.py +++ b/dist/ba_data/python/bauiv1lib/settings/audio.py @@ -214,7 +214,8 @@ class AudioSettingsWindow(bui.MainWindow): color=(0.5, 1, 0.5), ) bui.apptimer( - 1.0, bui.Call(bui.request_permission, bui.Permission.STORAGE) + 1.0, + bui.CallStrict(bui.request_permission, bui.Permission.STORAGE), ) return diff --git a/dist/ba_data/python/bauiv1lib/settings/benchmarks.py b/dist/ba_data/python/bauiv1lib/settings/benchmarks.py index 4296108..522ece9 100644 --- a/dist/ba_data/python/bauiv1lib/settings/benchmarks.py +++ b/dist/ba_data/python/bauiv1lib/settings/benchmarks.py @@ -266,7 +266,9 @@ class BenchmarksAndStressTestsWindow(bui.MainWindow): size=(28, 28), label='-', autoselect=True, - on_activate_call=bui.Call(self._stress_test_player_count_decrement), + on_activate_call=bui.CallStrict( + self._stress_test_player_count_decrement + ), repeat=True, enable_sound=True, ) @@ -277,7 +279,9 @@ class BenchmarksAndStressTestsWindow(bui.MainWindow): size=(28, 28), label='+', autoselect=True, - on_activate_call=bui.Call(self._stress_test_player_count_increment), + on_activate_call=bui.CallStrict( + self._stress_test_player_count_increment + ), repeat=True, enable_sound=True, ) @@ -313,7 +317,7 @@ class BenchmarksAndStressTestsWindow(bui.MainWindow): size=(28, 28), label='-', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._stress_test_round_duration_decrement ), repeat=True, @@ -326,7 +330,7 @@ class BenchmarksAndStressTestsWindow(bui.MainWindow): size=(28, 28), label='+', autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._stress_test_round_duration_increment ), repeat=True, diff --git a/dist/ba_data/python/bauiv1lib/settings/gamepad.py b/dist/ba_data/python/bauiv1lib/settings/gamepad.py index 48740f0..2c4aad7 100644 --- a/dist/ba_data/python/bauiv1lib/settings/gamepad.py +++ b/dist/ba_data/python/bauiv1lib/settings/gamepad.py @@ -585,8 +585,8 @@ class GamepadSettingsWindow(bui.MainWindow): if 'analogStickUD' + self._ext in self._settings else 6 if self._is_secondary else None ) - assert isinstance(sval1, (int, type(None))) - assert isinstance(sval2, (int, type(None))) + assert isinstance(sval1, int | None) + assert isinstance(sval2, int | None) if sval1 is not None and sval2 is not None: return ( self._inputdevice.get_axis_name(sval1) @@ -630,7 +630,7 @@ class GamepadSettingsWindow(bui.MainWindow): if 'dpad' + self._ext in self._settings else 2 if self._is_secondary else None ) - assert isinstance(dpadnum, (int, type(None))) + assert isinstance(dpadnum, int | None) if dpadnum is not None: return bui.Lstr( value='${A} ${B}', @@ -811,7 +811,7 @@ class GamepadSettingsWindow(bui.MainWindow): self._textwidgets[button] = txt bui.buttonwidget( edit=btn, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( AwaitGamepadInputWindow, self._inputdevice, button, @@ -1037,9 +1037,11 @@ class AwaitGamepadInputWindow(bui.Window): text=str(self._counter), ) self._decrement_timer: bui.AppTimer | None = bui.AppTimer( - 1.0, bui.Call(self._decrement), repeat=True + 1.0, bui.CallStrict(self._decrement), repeat=True + ) + bs.capture_game_controller_input( + bui.WeakCallPartial(self._event_callback) ) - bs.capture_game_controller_input(bui.WeakCall(self._event_callback)) def die(self) -> None: """Kill the window.""" diff --git a/dist/ba_data/python/bauiv1lib/settings/gamepadadvanced.py b/dist/ba_data/python/bauiv1lib/settings/gamepadadvanced.py index ab06216..9738505 100644 --- a/dist/ba_data/python/bauiv1lib/settings/gamepadadvanced.py +++ b/dist/ba_data/python/bauiv1lib/settings/gamepadadvanced.py @@ -415,7 +415,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): label=bui.Lstr(resource=f'{self._r}.clearText'), size=(110, 50), scale=0.7, - on_activate_call=bui.Call(self._clear_control, control), + on_activate_call=bui.CallStrict(self._clear_control, control), ) bui.widget(edit=btn, right_widget=btn2) @@ -439,7 +439,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): self._textwidgets[control] = txt bui.buttonwidget( edit=btn, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( AwaitGamepadInputWindow, self._parent_window.get_input(), control, @@ -509,7 +509,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): position=(330 + x_offset, position[1] + 4), size=(28, 28), label='-', - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._inc, control, min_val, max_val, -increment ), repeat=True, @@ -521,7 +521,7 @@ class GamepadAdvancedSettingsWindow(bui.Window): position=(380 + x_offset, position[1] + 4), size=(28, 28), label='+', - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._inc, control, min_val, max_val, increment ), repeat=True, diff --git a/dist/ba_data/python/bauiv1lib/settings/gamepadselect.py b/dist/ba_data/python/bauiv1lib/settings/gamepadselect.py index dbbf268..5af7af9 100644 --- a/dist/ba_data/python/bauiv1lib/settings/gamepadselect.py +++ b/dist/ba_data/python/bauiv1lib/settings/gamepadselect.py @@ -106,7 +106,7 @@ class GamepadSelectWindow(bui.MainWindow): ) bs.capture_game_controller_input( - bui.WeakCall(self.gamepad_configure_callback) + bui.WeakCallPartial(self.gamepad_configure_callback) ) def __del__(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/settings/graphics.py b/dist/ba_data/python/bauiv1lib/settings/graphics.py index e538d3f..a898619 100644 --- a/dist/ba_data/python/bauiv1lib/settings/graphics.py +++ b/dist/ba_data/python/bauiv1lib/settings/graphics.py @@ -455,7 +455,7 @@ class GraphicsSettingsWindow(bui.MainWindow): # Make a timer to update our controls in case the config changes # under us. self._update_timer = bui.AppTimer( - 0.25, bui.WeakCall(self._update_controls), repeat=True + 0.25, bui.WeakCallStrict(self._update_controls), repeat=True ) @override diff --git a/dist/ba_data/python/bauiv1lib/settings/keyboard.py b/dist/ba_data/python/bauiv1lib/settings/keyboard.py index 63f3cc1..73b4072 100644 --- a/dist/ba_data/python/bauiv1lib/settings/keyboard.py +++ b/dist/ba_data/python/bauiv1lib/settings/keyboard.py @@ -310,7 +310,7 @@ class ConfigKeyboardWindow(bui.MainWindow): bui.buttonwidget( edit=btn, autoselect=True, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( AwaitKeyboardInputWindow, button, txt, self._settings ), ) @@ -468,7 +468,7 @@ class AwaitKeyboardInputWindow(bui.Window): self._decrement_timer: bui.AppTimer | None = bui.AppTimer( 1.0, self._decrement, repeat=True ) - bs.capture_keyboard_input(bui.WeakCall(self._button_callback)) + bs.capture_keyboard_input(bui.WeakCallPartial(self._button_callback)) def __del__(self) -> None: bs.release_keyboard_input() diff --git a/dist/ba_data/python/bauiv1lib/settings/nettesting.py b/dist/ba_data/python/bauiv1lib/settings/nettesting.py index b6a521f..018d05b 100644 --- a/dist/ba_data/python/bauiv1lib/settings/nettesting.py +++ b/dist/ba_data/python/bauiv1lib/settings/nettesting.py @@ -163,7 +163,9 @@ class NetTestingWindow(bui.MainWindow): # Pass a weak-ref to this window so we don't keep it alive # if we back out before it completes. Also set is as daemon # so it doesn't keep the app running if the user is trying to quit. - Thread(target=bui.Call(_run_diagnostics, weakref.ref(self))).start() + Thread( + target=bui.CallStrict(_run_diagnostics, weakref.ref(self)) + ).start() @override def get_main_window_state(self) -> bui.MainWindowState: diff --git a/dist/ba_data/python/bauiv1lib/settings/plugins.py b/dist/ba_data/python/bauiv1lib/settings/plugins.py index c6b78b2..9fdcfdb 100644 --- a/dist/ba_data/python/bauiv1lib/settings/plugins.py +++ b/dist/ba_data/python/bauiv1lib/settings/plugins.py @@ -35,6 +35,7 @@ class PluginWindow(bui.MainWindow): transition: str | None = 'in_right', origin_widget: bui.Widget | None = None, ): + # pylint: disable=too-many-statements # pylint: disable=too-many-locals app = bui.app @@ -54,7 +55,7 @@ class PluginWindow(bui.MainWindow): # screen shape at small ui scale. screensize = bui.get_virtual_screen_size() scale = ( - 1.9 + 1.7 if uiscale is bui.UIScale.SMALL else 1.4 if uiscale is bui.UIScale.MEDIUM else 1.0 ) @@ -121,16 +122,21 @@ class PluginWindow(bui.MainWindow): size=(0, 0), text=bui.Lstr(resource='pluginsText'), color=app.ui_v1.title_color, - maxwidth=170, + maxwidth=140, h_align='center', v_align='center', ) - settings_button_x = ( - self._width * 0.5 - + self._scroll_width * 0.5 - - (100 if uiscale is bui.UIScale.SMALL else 40) - ) + settings_button_x = self._width * 0.5 + self._scroll_width * 0.5 - 40 + if uiscale is bui.UIScale.SMALL: + # In small UI there's stuff top right we need to avoid. + if bui.in_main_menu(): + # Squads button + settings_button_x -= 65 + else: + # Squads and settings buttons + settings_button_x -= 115 + button_row_yoffs = yoffs + (-2 if uiscale is bui.UIScale.SMALL else 10) self._num_plugins_text = bui.textwidget( @@ -150,7 +156,7 @@ class PluginWindow(bui.MainWindow): size=(130, 60), label=bui.Lstr(resource='allText'), autoselect=True, - on_activate_call=bui.WeakCall(self._show_category_options), + on_activate_call=bui.WeakCallStrict(self._show_category_options), color=(0.55, 0.73, 0.25), iconscale=1.2, ) @@ -378,7 +384,7 @@ class PluginWindow(bui.MainWindow): ), position=(10, item_y), size=(self._scroll_width - 40, 50), - on_value_change_call=bui.Call( + on_value_change_call=bui.CallPartial( self._check_value_changed, plugspec ), textcolor=( @@ -402,7 +408,9 @@ class PluginWindow(bui.MainWindow): ) bui.buttonwidget( edit=button, - on_activate_call=bui.Call(plugin.show_settings_ui, button), + on_activate_call=bui.CallStrict( + plugin.show_settings_ui, button + ), ) else: button = None diff --git a/dist/ba_data/python/bauiv1lib/settings/testing.py b/dist/ba_data/python/bauiv1lib/settings/testing.py index 712ce93..b439d99 100644 --- a/dist/ba_data/python/bauiv1lib/settings/testing.py +++ b/dist/ba_data/python/bauiv1lib/settings/testing.py @@ -171,7 +171,9 @@ class TestingWindow(bui.MainWindow): left_widget=self._back_button, button_type='square', label='-', - on_activate_call=bui.Call(self._on_minus_press, entry['name']), + on_activate_call=bui.CallStrict( + self._on_minus_press, entry['name'] + ), ) if i == 0: bui.widget(edit=btn, up_widget=self._back_button) @@ -192,7 +194,9 @@ class TestingWindow(bui.MainWindow): repeat=True, button_type='square', label='+', - on_activate_call=bui.Call(self._on_plus_press, entry['name']), + on_activate_call=bui.CallStrict( + self._on_plus_press, entry['name'] + ), ) if i == 0: bui.widget(edit=btn, up_widget=self._back_button) diff --git a/dist/ba_data/python/bauiv1lib/settings/touchscreen.py b/dist/ba_data/python/bauiv1lib/settings/touchscreen.py index 580097a..5ea269a 100644 --- a/dist/ba_data/python/bauiv1lib/settings/touchscreen.py +++ b/dist/ba_data/python/bauiv1lib/settings/touchscreen.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """UI settings functionality related to touchscreens.""" + from __future__ import annotations from typing import override diff --git a/dist/ba_data/python/bauiv1lib/soundtrack/browser.py b/dist/ba_data/python/bauiv1lib/soundtrack/browser.py index 6ab5c52..2a78067 100644 --- a/dist/ba_data/python/bauiv1lib/soundtrack/browser.py +++ b/dist/ba_data/python/bauiv1lib/soundtrack/browser.py @@ -13,8 +13,6 @@ import bauiv1 as bui if TYPE_CHECKING: from typing import Any -REQUIRE_PRO = False - class SoundtrackBrowserWindow(bui.MainWindow): """Window for browsing soundtracks.""" @@ -225,7 +223,7 @@ class SoundtrackBrowserWindow(bui.MainWindow): # Keep our lock images up to date/etc. self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() @@ -284,14 +282,8 @@ class SoundtrackBrowserWindow(bui.MainWindow): self._save_state() def _update(self) -> None: - have_pro = ( - bui.app.classic is None - or bui.app.classic.accounts.have_pro_options() - ) for lock in self._lock_images: - bui.imagewidget( - edit=lock, opacity=0.0 if (have_pro or not REQUIRE_PRO) else 1.0 - ) + bui.imagewidget(edit=lock, opacity=0.0 if bool(True) else 1.0) def _do_delete_soundtrack(self) -> None: cfg = bui.app.config @@ -309,15 +301,8 @@ class SoundtrackBrowserWindow(bui.MainWindow): def _delete_soundtrack(self) -> None: # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow from bauiv1lib.confirm import ConfirmWindow - if REQUIRE_PRO and ( - bui.app.classic is not None - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return if self._selected_soundtrack is None: return if self._selected_soundtrack == '__default__': @@ -338,15 +323,7 @@ class SoundtrackBrowserWindow(bui.MainWindow): ) def _duplicate_soundtrack(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow - if REQUIRE_PRO and ( - bui.app.classic is not None - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return cfg = bui.app.config cfg.setdefault('Soundtracks', {}) @@ -408,34 +385,16 @@ class SoundtrackBrowserWindow(bui.MainWindow): ) def _edit_soundtrack_with_sound(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow - - if REQUIRE_PRO and ( - bui.app.classic is not None - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return bui.getsound('swish').play() self._edit_soundtrack() def _edit_soundtrack(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow from bauiv1lib.soundtrack.edit import SoundtrackEditWindow # no-op if we don't have control. if not self.main_window_has_control(): return - if REQUIRE_PRO and ( - bui.app.classic is not None - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return - if self._selected_soundtrack is None: return @@ -489,7 +448,7 @@ class SoundtrackBrowserWindow(bui.MainWindow): v_align='center', maxwidth=self._width - 110, always_highlight=True, - on_select_call=bui.WeakCall(self._select, pname, index), + on_select_call=bui.WeakCallStrict(self._select, pname, index), on_activate_call=self._edit_soundtrack_with_sound, selectable=True, ) @@ -530,7 +489,7 @@ class SoundtrackBrowserWindow(bui.MainWindow): # Eww need to run this in a timer so it happens after our select # callbacks. With a small-enough time sometimes it happens before # anyway. Ew. need a way to just schedule a callable i guess. - bui.apptimer(0.1, bui.WeakCall(self._set_allow_changing)) + bui.apptimer(0.1, bui.WeakCallStrict(self._set_allow_changing)) def _set_allow_changing(self) -> None: self._allow_changing_soundtracks = True @@ -539,21 +498,12 @@ class SoundtrackBrowserWindow(bui.MainWindow): self._select(self._selected_soundtrack, self._selected_soundtrack_index) def _new_soundtrack(self) -> None: - # pylint: disable=cyclic-import - from bauiv1lib.purchase import PurchaseWindow from bauiv1lib.soundtrack.edit import SoundtrackEditWindow # no-op if we're not in control. if not self.main_window_has_control(): return - if REQUIRE_PRO and ( - bui.app.classic is not None - and not bui.app.classic.accounts.have_pro_options() - ): - PurchaseWindow(items=['pro']) - return - self.main_window_replace( lambda: SoundtrackEditWindow(existing_soundtrack=None) ) diff --git a/dist/ba_data/python/bauiv1lib/soundtrack/edit.py b/dist/ba_data/python/bauiv1lib/soundtrack/edit.py index 1dfd58a..f79248f 100644 --- a/dist/ba_data/python/bauiv1lib/soundtrack/edit.py +++ b/dist/ba_data/python/bauiv1lib/soundtrack/edit.py @@ -313,7 +313,7 @@ class SoundtrackEditWindow(bui.MainWindow): size=(230, 32), label=self._get_entry_button_display_name(entry), text_scale=0.6, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._get_entry, song_type, entry, type_name ), icon=( @@ -364,7 +364,9 @@ class SoundtrackEditWindow(bui.MainWindow): size=(50, 32), label=bui.Lstr(resource=f'{self._r}.testText'), text_scale=0.6, - on_activate_call=bui.Call(self._test, bs.MusicType(song_type)), + on_activate_call=bui.CallStrict( + self._test, bs.MusicType(song_type) + ), up_widget=( prev_test_button if prev_test_button is not None @@ -429,7 +431,7 @@ class SoundtrackEditWindow(bui.MainWindow): } new_win = self.main_window_replace( lambda: music.get_music_player().select_entry( - bui.Call(self._restore_editor, state, song_type), + bui.CallPartial(self._restore_editor, state, song_type), entry, selection_target_name, ) diff --git a/dist/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py b/dist/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py index 4061aef..281dd87 100644 --- a/dist/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py +++ b/dist/ba_data/python/bauiv1lib/soundtrack/entrytypeselect.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Provides UI for selecting soundtrack entry types.""" + from __future__ import annotations import copy diff --git a/dist/ba_data/python/bauiv1lib/soundtrack/macmusicapp.py b/dist/ba_data/python/bauiv1lib/soundtrack/macmusicapp.py index 2c47085..65af31e 100644 --- a/dist/ba_data/python/bauiv1lib/soundtrack/macmusicapp.py +++ b/dist/ba_data/python/bauiv1lib/soundtrack/macmusicapp.py @@ -126,7 +126,7 @@ class MacMusicAppPlaylistSelectWindow(bui.MainWindow): v_align='center', maxwidth=self._width - 110, selectable=True, - on_activate_call=bui.Call(self._sel, playlist), + on_activate_call=bui.CallStrict(self._sel, playlist), click_activate=True, ) bui.widget(edit=txt, show_buffer_top=40, show_buffer_bottom=40) diff --git a/dist/ba_data/python/bauiv1lib/store.py b/dist/ba_data/python/bauiv1lib/store.py new file mode 100644 index 0000000..be521f0 --- /dev/null +++ b/dist/ba_data/python/bauiv1lib/store.py @@ -0,0 +1,59 @@ +# Released under the MIT License. See LICENSE for details. +# +"""Shiny new doc-ui based store.""" + +from __future__ import annotations + +from typing import override, TYPE_CHECKING + +from bauiv1lib.docui import DocUIController + +import bauiv1 as bui + +if TYPE_CHECKING: + from bacommon.docui import DocUIRequest, DocUIResponse + + from bauiv1lib.docui import DocUILocalAction + + +class StoreUIController(DocUIController): + """DocUI setup for store.""" + + @override + def fulfill_request(self, request: DocUIRequest) -> DocUIResponse: + return self.fulfill_request_cloud(request, 'classicstore') + + @override + def local_action(self, action: DocUILocalAction) -> None: + + if action.name == 'get_tokens': + self._get_tokens(action) + elif action.name == 'restore_purchases': + self._restore_purchases() + else: + bui.screenmessage( + f'Invalid local-action "{action.name}".', color=(1, 0, 0) + ) + bui.getsound('error').play() + + def _restore_purchases(self) -> None: + + plus = bui.app.plus + assert plus is not None + + # We should always be signed in here. Make noise if not. + if plus.accounts.primary is None: + bui.screenmessage( + bui.Lstr(resource='notSignedInText'), color=(1, 0, 0) + ) + bui.getsound('error').play() + return + + plus.restore_purchases() + + def _get_tokens(self, action: DocUILocalAction) -> None: + from bauiv1lib.gettokens import show_get_tokens_window + + bui.getsound('swish').play() + + show_get_tokens_window(origin_widget=bui.existing(action.widget)) diff --git a/dist/ba_data/python/bauiv1lib/tabs.py b/dist/ba_data/python/bauiv1lib/tabs.py index a3d298d..a4d85c3 100644 --- a/dist/ba_data/python/bauiv1lib/tabs.py +++ b/dist/ba_data/python/bauiv1lib/tabs.py @@ -62,7 +62,7 @@ class TabRow[T: Enum]: size=size, label=tab_label, enable_sound=False, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._tick_and_call, on_select_call, tab_id ), ) diff --git a/dist/ba_data/python/bauiv1lib/teamnamescolors.py b/dist/ba_data/python/bauiv1lib/teamnamescolors.py index 4e4622e..ed90fb7 100644 --- a/dist/ba_data/python/bauiv1lib/teamnamescolors.py +++ b/dist/ba_data/python/bauiv1lib/teamnamescolors.py @@ -73,7 +73,7 @@ class TeamNamesColorsWindow(PopupWindow): id=f'{self._idprefix}|colorbutton{i}', autoselect=True, position=(50, 0 + 195 - 90 * i), - on_activate_call=bui.Call(self._color_click, i), + on_activate_call=bui.CallStrict(self._color_click, i), size=(70, 70), color=self._colors[i], label='', diff --git a/dist/ba_data/python/bauiv1lib/template.py b/dist/ba_data/python/bauiv1lib/template.py index c9e25cb..9687d8e 100644 --- a/dist/ba_data/python/bauiv1lib/template.py +++ b/dist/ba_data/python/bauiv1lib/template.py @@ -212,7 +212,7 @@ class TemplateMainWindow(bui.MainWindow): autoselect=True, size=(button_width, 60), label=f'Template{child_dummy_data}', - on_activate_call=bui.WeakCall( + on_activate_call=bui.WeakCallStrict( self._child_press, child_dummy_data ), ) diff --git a/dist/ba_data/python/bauiv1lib/tournamententry.py b/dist/ba_data/python/bauiv1lib/tournamententry.py index b09cf5a..1717a53 100644 --- a/dist/ba_data/python/bauiv1lib/tournamententry.py +++ b/dist/ba_data/python/bauiv1lib/tournamententry.py @@ -7,9 +7,11 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING, override -from bauiv1lib.popup import PopupWindow +from bacommon.analytics import ClassicAnalyticsEvent import bauiv1 as bui +from bauiv1lib.popup import PopupWindow + if TYPE_CHECKING: from typing import Any, Callable import bascenev1 as bs @@ -361,7 +363,7 @@ class TournamentEntryWindow(PopupWindow): self._fg_state = bui.app.fg_state self._running_query = False self._update_timer = bui.AppTimer( - 1.0, bui.WeakCall(self._update), repeat=True + 1.0, bui.WeakCallStrict(self._update), repeat=True ) self._update() self._restore_state() @@ -433,7 +435,9 @@ class TournamentEntryWindow(PopupWindow): else 'retry entry window' ) }, - callback=bui.WeakCall(self._on_tournament_query_response), + callback=bui.WeakCallPartial( + self._on_tournament_query_response + ), ) self._last_query_time = bui.apptime() self._running_query = True @@ -588,6 +592,13 @@ class TournamentEntryWindow(PopupWindow): self._launched = True launched = False + bui.app.analytics.submit_event( + ClassicAnalyticsEvent( + ClassicAnalyticsEvent.EventType.START_TOURNEY_COOP_SESSION, + extra=self._tournament_info.get('game'), + ) + ) + # If they gave us an existing, non-consistent practice activity, # just restart it. if ( @@ -751,7 +762,7 @@ class TournamentEntryWindow(PopupWindow): assert bui.app.plus is not None bui.app.plus.ads.show_ad_2( 'tournament_entry', - on_completion_call=bui.WeakCall(self._on_ad_complete), + on_completion_call=bui.WeakCallPartial(self._on_ad_complete), ) def _on_practice_press(self) -> None: diff --git a/dist/ba_data/python/bauiv1lib/tournamentscores.py b/dist/ba_data/python/bauiv1lib/tournamentscores.py index 227e1c6..e334742 100644 --- a/dist/ba_data/python/bauiv1lib/tournamentscores.py +++ b/dist/ba_data/python/bauiv1lib/tournamentscores.py @@ -114,7 +114,7 @@ class TournamentScoresWindow(PopupWindow): 'numScores': 50, 'source': 'scores window', }, - callback=bui.WeakCall(self._on_tournament_query_response), + callback=bui.WeakCallPartial(self._on_tournament_query_response), ) def _on_tournament_query_response( @@ -200,7 +200,7 @@ class TournamentScoresWindow(PopupWindow): bui.textwidget( edit=txt, - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._show_player_info, entry, txt ), ) diff --git a/dist/ba_data/python/bauiv1lib/watch.py b/dist/ba_data/python/bauiv1lib/watch.py index 2b8d923..35375f3 100644 --- a/dist/ba_data/python/bauiv1lib/watch.py +++ b/dist/ba_data/python/bauiv1lib/watch.py @@ -405,7 +405,7 @@ class WatchWindow(bui.MainWindow): bs.new_host_session(mainmenu.MainMenuSession) - bui.fade_screen(False, endcall=bui.Call(bui.pushcall, do_it)) + bui.fade_screen(False, endcall=bui.CallStrict(bui.pushcall, do_it)) bui.containerwidget(edit=self._root_widget, transition='out_left') def _on_my_replay_rename_press(self) -> None: @@ -458,7 +458,7 @@ class WatchWindow(bui.MainWindow): parent=cnt, id=f'{self.main_window_id_prefix}|replayrenamecancel', label=bui.Lstr(resource='cancelText'), - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( lambda c: bui.containerwidget(edit=c, transition='out_scale'), cnt, ), @@ -472,7 +472,7 @@ class WatchWindow(bui.MainWindow): label=bui.Lstr(resource=f'{self._r}.renameText'), size=(180, 60), position=(c_width - 230, 30), - on_activate_call=bui.Call( + on_activate_call=bui.CallStrict( self._rename_my_replay, self._my_replay_selected ), autoselect=True, @@ -558,7 +558,7 @@ class WatchWindow(bui.MainWindow): ) ], ), - bui.Call(self._delete_replay, self._my_replay_selected), + bui.CallStrict(self._delete_replay, self._my_replay_selected), width=450, height=150, ) @@ -616,7 +616,7 @@ class WatchWindow(bui.MainWindow): (1.0, 1, 0.4) if name == '__lastReplay.brp' else (1, 1, 1) ), always_highlight=True, - on_select_call=bui.Call(self._on_my_replay_select, name), + on_select_call=bui.CallStrict(self._on_my_replay_select, name), on_activate_call=self._my_replays_watch_replay_button.activate, text=self._get_replay_display_name(name), h_align='left', diff --git a/dist/ba_data/python/efro/dataclassio/_base.py b/dist/ba_data/python/efro/dataclassio/_base.py index c8a3969..51e7fde 100644 --- a/dist/ba_data/python/efro/dataclassio/_base.py +++ b/dist/ba_data/python/efro/dataclassio/_base.py @@ -93,21 +93,28 @@ class IOMultiType[EnumT: Enum]: """A base class for types that can map to multiple dataclass types. This enables usage of high level base classes (for example a - 'Message' type) in annotations, with dataclassio automatically - serializing & deserializing dataclass subclasses based on their type - ('MessagePing', 'MessageChat', etc.) + ``Message`` type) in annotations, with dataclassio automatically + serializing & deserializing type-specific data for subclasses + (``MessagePing``, ``MessageChat``, etc.) - Standard usage involves creating a class which inherits from this - one which acts as a 'registry', and then creating dataclass classes - inheriting from that registry class. Dataclassio will then do the - right thing when that registry class is used in type annotations. + Standard usage involves a 'registry' class inheriting from this one + and dataclass classes inheriting from that registry class. + Dataclassio will then do the right thing when that registry class is + used in type annotations. - See tests/test_efro/test_dataclassio.py for examples. + For an example multitype class (useful to use as a starting point + for your own) see :class:`efro.dataclassio.templatemultitype`. """ @classmethod def get_type(cls, type_id: EnumT) -> type[Self]: - """Return a specific subclass given a type-id.""" + """Return a specific subclass given a type-id. + + Should be overridden by child classes. Generally, users of the + class should call + :meth:`~efro.dataclassio.IOMultiType.get_type_cached()` instead + of this, as it is more efficient. + """ raise NotImplementedError() @final @@ -220,6 +227,10 @@ class IOAttrs: #: minute boundaries (see :meth:`efro.util.utc_this_minute()`). whole_minutes: bool = False + #: If ``True``, requires ``datetime.datetime`` values to lie exactly on + #: second boundaries (see :meth:`efro.util.utc_this_second()`). + whole_seconds: bool = False + #: If ``True``, values of type ``datetime.datetime`` (in json codec) #: and ``datetime.timedelta`` (in all codecs) will be stored as single #: float timestamp/seconds values instead of the default list of @@ -256,6 +267,12 @@ class IOAttrs: #: editing the value. Does not actually affect value input/output. multiline: bool | None = None + #: If provided for a string, hints whether the value should be + #: edited as distinct options in something like a popup menu instead + #: of as a text field. Can be referenced when creating UI for + #: editing the value. Does not actually affect value input/output. + edit_as_options: bool | None = None + def __init__( self, storagename: str | None = storagename, @@ -264,12 +281,16 @@ class IOAttrs: whole_days: bool = whole_days, whole_hours: bool = whole_hours, whole_minutes: bool = whole_minutes, + whole_seconds: bool = whole_seconds, float_times: bool = float_times, soft_default: Any = MISSING, soft_default_factory: Callable[[], Any] | _MissingType = MISSING, enum_fallback: Enum | None = None, multiline: bool | None = None, + edit_as_options: bool | None = None, ): + # pylint: disable=too-many-branches + # Only store values that differ from class defaults to keep # our instances nice and lean. cls = type(self) @@ -283,6 +304,8 @@ class IOAttrs: self.whole_hours = whole_hours if whole_minutes != cls.whole_minutes: self.whole_minutes = whole_minutes + if whole_seconds != cls.whole_seconds: + self.whole_seconds = whole_seconds if float_times != cls.float_times: self.float_times = float_times if soft_default is not cls.soft_default: @@ -304,6 +327,8 @@ class IOAttrs: self.enum_fallback = enum_fallback if multiline is not cls.multiline: self.multiline = multiline + if edit_as_options is not cls.multiline: + self.edit_as_options = edit_as_options def validate_for_field(self, cls: type, field: dataclasses.Field) -> None: """Ensure the IOAttrs is ok to use with provided field.""" @@ -321,7 +346,7 @@ class IOAttrs: and self.soft_default_factory is self.MISSING ): raise TypeError( - f'Field {field.name} of {cls} has' + f'Field \'{field.name}\' of {cls} has' f' neither a default nor a default_factory' f' and IOAttrs contains neither a soft_default' f' nor a soft_default_factory;' @@ -357,6 +382,11 @@ class IOAttrs: raise ValueError( f'Value {value} at {fieldpath}' f' is not a whole minute.' ) + elif self.whole_seconds: + if any(x != 0 for x in (value.microsecond,)): + raise ValueError( + f'Value {value} at {fieldpath}' f' is not a whole second.' + ) class TypeNotPresentError(TypeError): diff --git a/dist/ba_data/python/efro/dataclassio/_prep.py b/dist/ba_data/python/efro/dataclassio/_prep.py index 4e9cd1d..baf1d87 100644 --- a/dist/ba_data/python/efro/dataclassio/_prep.py +++ b/dist/ba_data/python/efro/dataclassio/_prep.py @@ -266,176 +266,180 @@ class PrepSession: # pylint: disable=too-many-branches # pylint: disable=too-many-statements - if recursion_level > MAX_RECURSION: - raise RuntimeError('Max recursion exceeded.') + if not TYPE_CHECKING: - origin = _get_origin(anntype) + if recursion_level > MAX_RECURSION: + raise RuntimeError('Max recursion exceeded.') - # If we inherit from IOMultiType, we use its type map to - # determine which type we're going to instead of the annotation. - # And we can't really check those types because they are - # lazy-loaded. So I guess we're done here. - if issubclass(origin, IOMultiType): - return + origin = _get_origin(anntype) - if origin is typing.Union or origin is types.UnionType: - self.prep_union( - cls, attrname, anntype, recursion_level=recursion_level + 1 - ) - return + # If we inherit from IOMultiType, we use its type map to + # determine which type we're going to instead of the + # annotation. And we can't really check those types because + # they are lazy-loaded. So I guess we're done here. + if issubclass(origin, IOMultiType): + return - if anntype is typing.Any: - return + if origin is typing.Union or origin is types.UnionType: + self.prep_union( + cls, attrname, anntype, recursion_level=recursion_level + 1 + ) + return - # Everything below this point assumes the annotation type - # resolves to a concrete type. - if not isinstance(origin, type): - raise TypeError( - f'Unsupported type found for \'{attrname}\' on {cls}:' - f' {anntype}' - ) + if anntype is typing.Any: + return - # If a soft_default value/factory was passed, we do some basic - # type checking on the top-level value here. We also run full - # recursive validation on values later during inputting, but - # this should catch at least some errors early on, which can be - # useful since soft_defaults are not static type checked. - if ioattrs is not None: - have_soft_default = False - soft_default: Any = None - if ioattrs.soft_default is not ioattrs.MISSING: - have_soft_default = True - soft_default = ioattrs.soft_default - elif ioattrs.soft_default_factory is not ioattrs.MISSING: - assert callable(ioattrs.soft_default_factory) - have_soft_default = True - soft_default = ioattrs.soft_default_factory() + # Everything below this point assumes the annotation type + # resolves to a concrete type. + if not isinstance(origin, type): + raise TypeError( + f'Unsupported type found for \'{attrname}\' on {cls}:' + f' {anntype}' + ) - # Do a simple type check for the top level to catch basic - # soft_default mismatches early; full check will happen at - # input time. - if have_soft_default: - if not isinstance(soft_default, origin): + # If a soft_default value/factory was passed, we do some + # basic type checking on the top-level value here. We also + # run full recursive validation on values later during + # inputting, but this should catch at least some errors + # early on, which can be useful since soft_defaults are not + # static type checked. + if ioattrs is not None: + have_soft_default = False + soft_default: Any = None + if ioattrs.soft_default is not ioattrs.MISSING: + have_soft_default = True + soft_default = ioattrs.soft_default + elif ioattrs.soft_default_factory is not ioattrs.MISSING: + assert callable(ioattrs.soft_default_factory) + have_soft_default = True + soft_default = ioattrs.soft_default_factory() + + # Do a simple type check for the top level to catch basic + # soft_default mismatches early; full check will happen at + # input time. + if have_soft_default: + if not isinstance(soft_default, origin): + raise TypeError( + f'{cls} attr {attrname} has type {origin}' + f' but soft_default value is type' + f' {type(soft_default)}' + ) + + if origin in SIMPLE_TYPES: + return + + # For sets and lists, check out their single contained type (if + # any). + if origin in (list, set): + childtypes = typing.get_args(anntype) + if len(childtypes) == 0: + # This is equivalent to Any; nothing else needs + # checking. + return + if len(childtypes) > 1: raise TypeError( - f'{cls} attr {attrname} has type {origin}' - f' but soft_default value is type {type(soft_default)}' + f'Unrecognized typing arg count {len(childtypes)}' + f" for {anntype} attr '{attrname}' on {cls}" + ) + self.prep_type( + cls, + attrname, + childtypes[0], + ioattrs=None, + recursion_level=recursion_level + 1, + ) + return + + if origin is dict: + childtypes = typing.get_args(anntype) + assert len(childtypes) in (0, 2) + + # For key types we support Any, str, int, + # and Enums with uniform str/int values. + if not childtypes or childtypes[0] is typing.Any: + # 'Any' needs no further checks (just checked + # per-instance). + pass + elif childtypes[0] in (str, int): + # str and int are all good as keys. + pass + elif issubclass(childtypes[0], Enum): + # Allow our usual str or int enum types as keys. + self.prep_enum(childtypes[0], ioattrs=None) + else: + raise TypeError( + f'Dict key type {childtypes[0]} for \'{attrname}\'' + f' on {cls.__name__} is not supported by dataclassio.' ) - if origin in SIMPLE_TYPES: - return - - # For sets and lists, check out their single contained type (if - # any). - if origin in (list, set): - childtypes = typing.get_args(anntype) - if len(childtypes) == 0: - # This is equivalent to Any; nothing else needs - # checking. + # For value types we support any of our normal types. + if not childtypes or _get_origin(childtypes[1]) is typing.Any: + # 'Any' needs no further checks (just checked + # per-instance). + pass + else: + self.prep_type( + cls, + attrname, + childtypes[1], + ioattrs=None, + recursion_level=recursion_level + 1, + ) return - if len(childtypes) > 1: - raise TypeError( - f'Unrecognized typing arg count {len(childtypes)}' - f" for {anntype} attr '{attrname}' on {cls}" - ) - self.prep_type( - cls, - attrname, - childtypes[0], - ioattrs=None, - recursion_level=recursion_level + 1, + + # For Tuples, simply check individual member types. (and, for + # now, explicitly disallow zero member types or usage of + # ellipsis) + if origin is tuple: + childtypes = typing.get_args(anntype) + if not childtypes: + raise TypeError( + f'Tuple at \'{attrname}\'' + f' has no type args; dataclassio requires type args.' + ) + if childtypes[-1] is ...: + raise TypeError( + f'Found ellipsis as part of type for' + f' \'{attrname}\' on {cls.__name__};' + f' these are not' + f' supported by dataclassio.' + ) + for childtype in childtypes: + self.prep_type( + cls, + attrname, + childtype, + ioattrs=None, + recursion_level=recursion_level + 1, + ) + return + + if issubclass(origin, Enum): + self.prep_enum(origin, ioattrs=ioattrs) + return + + # We allow datetime objects (and google's extended subclass of + # them used in firestore, which is why we don't look for exact + # type here). + if issubclass(origin, datetime.datetime): + return + + # We support datetime.timedelta. + if issubclass(origin, datetime.timedelta): + return + + if dataclasses.is_dataclass(origin): + self.prep_dataclass(origin, recursion_level=recursion_level + 1) + return + + if origin is bytes: + return + + raise TypeError( + f"Attr '{attrname}' on {cls.__name__} contains" + f" type '{anntype}'" + f' which is not supported by dataclassio.' ) - return - - if origin is dict: - childtypes = typing.get_args(anntype) - assert len(childtypes) in (0, 2) - - # For key types we support Any, str, int, - # and Enums with uniform str/int values. - if not childtypes or childtypes[0] is typing.Any: - # 'Any' needs no further checks (just checked - # per-instance). - pass - elif childtypes[0] in (str, int): - # str and int are all good as keys. - pass - elif issubclass(childtypes[0], Enum): - # Allow our usual str or int enum types as keys. - self.prep_enum(childtypes[0], ioattrs=None) - else: - raise TypeError( - f'Dict key type {childtypes[0]} for \'{attrname}\'' - f' on {cls.__name__} is not supported by dataclassio.' - ) - - # For value types we support any of our normal types. - if not childtypes or _get_origin(childtypes[1]) is typing.Any: - # 'Any' needs no further checks (just checked - # per-instance). - pass - else: - self.prep_type( - cls, - attrname, - childtypes[1], - ioattrs=None, - recursion_level=recursion_level + 1, - ) - return - - # For Tuples, simply check individual member types. (and, for - # now, explicitly disallow zero member types or usage of - # ellipsis) - if origin is tuple: - childtypes = typing.get_args(anntype) - if not childtypes: - raise TypeError( - f'Tuple at \'{attrname}\'' - f' has no type args; dataclassio requires type args.' - ) - if childtypes[-1] is ...: - raise TypeError( - f'Found ellipsis as part of type for' - f' \'{attrname}\' on {cls.__name__};' - f' these are not' - f' supported by dataclassio.' - ) - for childtype in childtypes: - self.prep_type( - cls, - attrname, - childtype, - ioattrs=None, - recursion_level=recursion_level + 1, - ) - return - - if issubclass(origin, Enum): - self.prep_enum(origin, ioattrs=ioattrs) - return - - # We allow datetime objects (and google's extended subclass of - # them used in firestore, which is why we don't look for exact - # type here). - if issubclass(origin, datetime.datetime): - return - - # We support datetime.timedelta. - if issubclass(origin, datetime.timedelta): - return - - if dataclasses.is_dataclass(origin): - self.prep_dataclass(origin, recursion_level=recursion_level + 1) - return - - if origin is bytes: - return - - raise TypeError( - f"Attr '{attrname}' on {cls.__name__} contains" - f" type '{anntype}'" - f' which is not supported by dataclassio.' - ) def prep_union( self, cls: type, attrname: str, anntype: Any, recursion_level: int diff --git a/dist/ba_data/python/efro/dataclassio/templatemultitype.py b/dist/ba_data/python/efro/dataclassio/templatemultitype.py index 9e91853..36889c1 100644 --- a/dist/ba_data/python/efro/dataclassio/templatemultitype.py +++ b/dist/ba_data/python/efro/dataclassio/templatemultitype.py @@ -1,23 +1,21 @@ # Released under the MIT License. See LICENSE for details. # -"""Template for an IOMultitype setup. +"""Template for a multi-type class setup. To use this template, simply copy the contents of this module somewhere -and then replace 'TemplateMultiType' with 'YourType'. +and then replace 'TemplateMultiType' with 'MyAwesomeTypeName' or +whatnot. """ from __future__ import annotations -from typing import TYPE_CHECKING, assert_never, override +from typing import assert_never, override from enum import Enum from dataclasses import dataclass from efro.dataclassio import ioprepped, IOMultiType -if TYPE_CHECKING: - pass - class TemplateMultiTypeTypeID(Enum): """Type ID for each of our subclasses.""" diff --git a/dist/ba_data/python/efro/debug.py b/dist/ba_data/python/efro/debug.py index a62ee87..2d87280 100644 --- a/dist/ba_data/python/efro/debug.py +++ b/dist/ba_data/python/efro/debug.py @@ -10,6 +10,7 @@ For this reason, these methods should NEVER be called in production code. Enable them only for debugging situations and be aware that their use may itself cause problems. The same is true for the gc module itself. """ + from __future__ import annotations import os diff --git a/dist/ba_data/python/efro/error.py b/dist/ba_data/python/efro/error.py index 022d824..d294404 100644 --- a/dist/ba_data/python/efro/error.py +++ b/dist/ba_data/python/efro/error.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Common errors and related functionality.""" + from __future__ import annotations from typing import TYPE_CHECKING, override diff --git a/dist/ba_data/python/efro/logging.py b/dist/ba_data/python/efro/logging.py index 3b431cd..5fe1876 100644 --- a/dist/ba_data/python/efro/logging.py +++ b/dist/ba_data/python/efro/logging.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Logging functionality.""" + from __future__ import annotations import sys diff --git a/dist/ba_data/python/efro/message/_receiver.py b/dist/ba_data/python/efro/message/_receiver.py index efb9947..1763b58 100644 --- a/dist/ba_data/python/efro/message/_receiver.py +++ b/dist/ba_data/python/efro/message/_receiver.py @@ -118,14 +118,14 @@ class MessageReceiver: # Return types can be a single type or a union of types. if isinstance(ret, (_GenericAlias, types.UnionType)): targs = get_args(ret) - if not all(isinstance(a, (type, type(None))) for a in targs): + if not all(isinstance(a, type | None) for a in targs): raise TypeError( f'expected only types for "return" annotation;' f' got {targs}.' ) responsetypes = targs else: - if not isinstance(ret, (type, type(None))): + if not isinstance(ret, type | None): raise TypeError( f'expected one or more types for' f' "return" annotation; got a {type(ret)}.' diff --git a/dist/ba_data/python/efro/terminal.py b/dist/ba_data/python/efro/terminal.py index 0ccfadb..796d693 100644 --- a/dist/ba_data/python/efro/terminal.py +++ b/dist/ba_data/python/efro/terminal.py @@ -1,6 +1,7 @@ # Released under the MIT License. See LICENSE for details. # """Functionality related to terminal IO.""" + from __future__ import annotations import sys diff --git a/dist/ba_data/python/efro/threadpool.py b/dist/ba_data/python/efro/threadpool.py index 5a763b6..685263b 100644 --- a/dist/ba_data/python/efro/threadpool.py +++ b/dist/ba_data/python/efro/threadpool.py @@ -10,6 +10,8 @@ import threading from typing import TYPE_CHECKING, ParamSpec from concurrent.futures import ThreadPoolExecutor +from efro.util import strip_exception_tracebacks + if TYPE_CHECKING: from typing import Any, Callable from concurrent.futures import Future @@ -83,5 +85,8 @@ class ThreadPoolExecutorEx(ThreadPoolExecutor): self.no_wait_count -= 1 try: fut.result() - except Exception: + except Exception as exc: logger.exception('Error in work submitted via submit_no_wait().') + # We're done with this exception, so strip its traceback to + # avoid reference cycles. + strip_exception_tracebacks(exc) diff --git a/dist/ba_data/python/efro/util.py b/dist/ba_data/python/efro/util.py index aa2cd7b..74a7d2f 100644 --- a/dist/ba_data/python/efro/util.py +++ b/dist/ba_data/python/efro/util.py @@ -162,6 +162,20 @@ def utc_this_minute() -> datetime.datetime: ) +def utc_this_second() -> datetime.datetime: + """Get offset-aware beginning of current second in the utc time zone.""" + now = datetime.datetime.now(datetime.UTC) + return datetime.datetime( + year=now.year, + month=now.month, + day=now.day, + hour=now.hour, + minute=now.minute, + second=now.second, + tzinfo=now.tzinfo, + ) + + def empty_weakref[T](objtype: type[T]) -> weakref.ref[T]: """Return an invalidated weak-reference for the specified type.""" # At runtime, all weakrefs are the same; our type arg is just @@ -348,36 +362,39 @@ def dispatchmethod[ArgT, RetT]( """ from functools import singledispatch, update_wrapper - origwrapper: Any = singledispatch(func) - - # Pull this out so hopefully origwrapper can die, - # otherwise we reference origwrapper in our wrapper. - dispatch = origwrapper.dispatch - - # All we do here is recreate the end of functools.singledispatch - # where it returns a wrapper except instead of the wrapper using the - # first arg to the function ours uses the second (to skip 'self'). - # This was made against Python 3.7; we should probably check up on - # this in later versions in case anything has changed. - # (or hopefully they'll add this functionality to their version) - # NOTE: sounds like we can use functools singledispatchmethod in 3.8 - def wrapper(*args: Any, **kw: Any) -> Any: - if not args or len(args) < 2: - raise TypeError( - f'{funcname} requires at least ' '2 positional arguments' - ) - - return dispatch(args[1].__class__)(*args, **kw) - - funcname = getattr(func, '__name__', 'dispatchmethod method') - wrapper.register = origwrapper.register # type: ignore - wrapper.dispatch = dispatch # type: ignore - wrapper.registry = origwrapper.registry # type: ignore # pylint: disable=protected-access - wrapper._clear_cache = origwrapper._clear_cache # type: ignore - update_wrapper(wrapper, func) - # pylint: enable=protected-access - return cast(DispatchMethodWrapper, wrapper) + # pylint: disable=no-else-return + + if TYPE_CHECKING: + return cast(DispatchMethodWrapper, None) + else: + origwrapper: Any = singledispatch(func) + + # Pull this out so hopefully origwrapper can die, + # otherwise we reference origwrapper in our wrapper. + dispatch = origwrapper.dispatch + + # All we do here is recreate the end of functools.singledispatch + # where it returns a wrapper except instead of the wrapper using the + # first arg to the function ours uses the second (to skip 'self'). + # This was made against Python 3.7; we should probably check up on + # this in later versions in case anything has changed. + # (or hopefully they'll add this functionality to their version) + # NOTE: sounds like we can use functools singledispatchmethod in 3.8 + def wrapper(*args: Any, **kw: Any) -> Any: + if not args or len(args) < 2: + raise TypeError( + f'{funcname} requires at least ' '2 positional arguments' + ) + return dispatch(args[1].__class__)(*args, **kw) + + funcname = getattr(func, '__name__', 'dispatchmethod method') + wrapper.register = origwrapper.register + wrapper.dispatch = dispatch + wrapper.registry = origwrapper.registry + wrapper._clear_cache = origwrapper._clear_cache + update_wrapper(wrapper, func) + return cast(DispatchMethodWrapper, wrapper) def valuedispatch[ValT, RetT]( @@ -579,7 +596,7 @@ def asserttype_o[T](obj: Any, typ: type[T]) -> T | None: failures are not expected. Otherwise use checktype. """ assert isinstance(typ, type), 'only actual types accepted' - assert isinstance(obj, (typ, type(None))) + assert isinstance(obj, typ | None) return obj @@ -602,7 +619,7 @@ def checktype_o[T](obj: Any, typ: type[T]) -> T | None: on failure. Use asserttype for more efficient (but less safe) equivalent. """ assert isinstance(typ, type), 'only actual types accepted' - if not isinstance(obj, (typ, type(None))): + if not isinstance(obj, typ | None): raise TypeError(f'Expected a {typ} or None; got a {type(obj)}.') return obj @@ -628,7 +645,7 @@ def warntype_o[T](obj: Any, typ: type[T]) -> T | None: not what is expected. """ assert isinstance(typ, type), 'only actual types accepted' - if not isinstance(obj, (typ, type(None))): + if not isinstance(obj, typ | None): import logging logging.warning( @@ -823,7 +840,10 @@ def set_canonical_module_names(module_globals: dict[str, Any]) -> None: def timedelta_str( - timeval: datetime.timedelta | float, *, maxparts: int = 2, decimals: int = 0 + timeval: datetime.timedelta | float | int, + *, + maxparts: int = 2, + decimals: int = 0, ) -> str: """Return a simple human readable time string for a length of time. @@ -840,7 +860,7 @@ def timedelta_str( """ # pylint: disable=too-many-locals - if isinstance(timeval, float): + if isinstance(timeval, float | int): timevalfin = datetime.timedelta(seconds=timeval) else: timevalfin = timeval @@ -1008,7 +1028,8 @@ def weighted_choice[T](*args: tuple[T, float]) -> T: items: tuple[T] weights: tuple[float] items, weights = zip(*args) - return random.choices(items, weights=weights)[0] + val: T = random.choices(items, weights=weights)[0] + return val def prune_empty_dirs(prunedir: str) -> None: diff --git a/dist/bombsquad_headless b/dist/bombsquad_headless index bb17ac30964991127c0aa060ffd17fe0982f9743..b324e251ed61706b73b5c8f710582f955262c951 100644 GIT binary patch delta 3158598 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%0DehqG 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

`9 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�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

jM+* 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

YE`U166ogbu*i8tG#sFThQUQRk`?lVWT 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‡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¥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

FlxeF_i-X21;vbrOxNp;O*fN3zv)LU`$;ma-dq1 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

LGQ9ArK(2O_u+0%C~n z8ujTktIRbos4_1{yS7J-mBdsNMIQr~=E^vEDRPP59AW56H6joGR5?r|;Dl6pj%WHp z^-QC`fh0G3*PkzK{d5ia;xq9x+IdDoso=t=(H;nJF@?{2Vk&P~IahsI3-|71KQYy8 z^?rsdW^NgqL)1P*?L|Fkxva0vA6`Bqf1n#i@RqLx!ygbB0G2|L^}3q1gO(5GsCLz# zoFgkBVAC8a<^6e5%DJmmj~Iby!i_nmvW9_HhUO|mp{m4yENgMoQ&Uu{Rnw)I+qgBS4vral`5qtnw3^D$X8rSmZC(;%;hmn4~QZ&CqwttGWUN%?bPgDTFoqr zs}=KontFi4uq#Df%hIn(;XnM26_Dq^$c2G>zncP+n}M6MYeV%T*I9G6s*_8+B61xo zAcdw8B3q1H2yg6)WEJuL;`|dA7drJtE>*jitU{{teE{2*9BQX(E_HaO=2Giss#B@y zvVnLXN|BY-dxdJ>X0o%!S=C2!EiEqfmYm`G%I?2`I0Ce4#_YJ%%Q;U(z!cRmGZ(;& z!_bxxht|HZ$Dz(zV3-L;@qDsM+vBxth7uaL{_kWdbCFx*{-~vgQ!xEW@bl%lFH89+izyRT)BKhSJ6?iM!HzHg#OgpF z4I#@@XV96d$yP%U>*_$3SW9gW`DUWwTUSwJZw1(ofLVKax^!RMr%cTeLj$Cx;!_)( z7NvKSsfNiTb24Vic7NjmS*qVI7|PJrW~dB6rJ*Q-HJXj}yVbtFhO^VqYc%omHT;Og zlHW=P_%Ee4X7)ZmT{YDbauhu;SAG2YU4h7={sdL=@8&`AMQF89{P1(D17(US zvb%mDz9V9zMm&B7a+Jn+dO|fuEX->4pG?tIV;X^?O850u3~0ZqY$uQ)*$RJ$Rz}k7 zoW!?3H#KNcl(IHQtnrf(G9Hnk*^gwAe$%1Bmd-ZaUGI}chHU`!X?Hr_Eba8-o)#Zz zS$gCwZQ%13bxe17=)LP8mdDEmpzFI^E$rmXU63j=Vsb&V=k?l_Ol)w3+ zBYtI=P&Wy!?eGy;oZ4aZIMs|>=fI51(6nL3Y49H{<_X!_>tPJE6`Z1^Mm;&%YDdd) z)sFEni`|aRWheYVjGhIn%?MHq4<>6GWlfeE75)Zoj&#^Qf$z*U)hpvcIh!N)w;+Sb z=-&K$hv>e3hH9FCVA)o^yG@mrD6o($@l3oxgXY8A`?11*Oj4WntMR<=OI%L9e-ge_ zX{x5fo3k%XA-XR7kC&#}y_bPrb8Nbt^wbzxcpGn90MPHGI#fes_YNeJtga)!QYC&D zJRK7>)JNlvw(8voj4cKPPiI{5@GomvKM@BB{e4R5@k=kT`}UO$$a~#nDSnd$Fdo`j zRsQxbQv-t$R3ndj1sGmUP{|8lmwuZo?v3RWUzsW=Cy!EV>)A}y)>X6;)Yc+fZDon$ zvUAE6&*0UfjYfQ!3X@JB@{?Lw^B{$_va-Z{jcE@tMWIB?dmOgZKB^^qy#RG5`mYl7 z$`^d!B7dKWM>lXE`)yxu{rmAeG0zm(wi&Xp*)>T_CJAsWMk~~83t6)`-J2!)X3&ci z`{e5tuwu<}WOms1tr&a@_iDPqxEO7bVg8tk7h!i)DofEZ&r~KcW;|u+J!zseU)lMp z`HDaRtyDEradxDv(00wKe&iso;Iaj1(J*8nUoKT=v#cwe?TP*qHMSShSO3@;bvRFpt zwH>A!>c~_WYBT(qhG9iN+XL59YH5gDhY=7&IgQ#p&T6TD4ycyu0!^&LuuRcSW10;n zUgMofNqz|zhNhPND3m1Fbp;YE!Gq>->dicpD1UPVkEhDdO-S3H1PU5~?fxzVfg*M~ zKA$T0T*4h326F{fTIX$ z6|k^uQ3$}}84v&6%a31qk2@_p^N}A+WqfPPR_L8HTFU0H$)@AMA57H^FOoD(eo2y= zcOyThb$4Yu%oVOENsQ2_Z<5$DmdEZ<9e5MOvpR5= z*fORNWt%H5jm4~HU!WfyB>#kaUMmmhRX&^iJ&HpHys}7EzHxy^e=>RNdhjnlnL-Sw zhp7{ze?oFa{v_R$#&0K_uu?zHu&IVZDS0 z)e$XYY4G@UAGMMTjzJ~Af zc8%#Ob&S|Vk?P@NZpGvHE-&w*0u2cRF&S*)>9 zr=q^#5Zj zm1v?qA0xYpZJ?$;cB7WX1_CbEvRI%2={g3HtO3Vs!07}WtO0v#zV^jwx zS4)c4pplNGl{8>k$4q@Rpr<2Hrvcx?5Ofo)m_A5VOQ=ytB&pBG&X5S#LZoGq#d(cf zeE~7CzZ6L9SFNd@)Qr@C8#G`vWl&ZFrfI-P0(xq|aT;(S0pIsi^Xz4%q?-9n1tyCG z4Ju7|Nh7VT0Xq`^VGUSD1&WIGtH|mqfoF<70qXOyTSWY+f?DH$BRb(-mwb7thbTBT zOjcrU%P^N?Bou|cS5w098V-V_`>|+ZeS&AouT+C7(rFqE48%P z|CK6GtVfPy>^a)=LhX4Ro+IoDJ33tA~bzEQAIDdp(!O! zcH-^a8B5*(GBQ#mA`X$)@f64k>!5`7{gn)OaEdksIe`Qco3ehURBobGyw99#azol zAQxj1;vIsuOvfV6*H(*cYvrB)OSt5XZU_j4gJub8y;sLG4YrT1BK7tmSdn!~OQ?Kt zQAMoP5C*=d5G(8YpeshfCyKC=@%R{mTg{K*F2+!|pP$9iw-MYT)W;vR$6D&+BJHuZ z`k16WMyijkpQTqR%)01m1UIQJ^TNqjV~AUM_34uO6rw&|QJ9`Iy7NF}yA`s-&#CZCmH&eJ^t7?e?c(p86=k<->{B13ROA8m=?nGg zp!yV}KKG4H33`j>IX>o(aji$yfauA5xcS}*(e+C;2HAj8Aq(044pRTA++Z(EeddjN{foX2BTI`8ze1HJM%h5)`RuY$S(AhWc$CikzGa7(l7m>k&Vz5 zUhzrR{j`$tJiIvTm>h8)D_G{Jj};6qF<&N_BfiD=0%Gu`mnw&m=pSz!embTd{rueD zI5Z={T<$!!qT0uqtCaEr+Bo!VTXJJ_;7(A-&H6JW+pQ`PG&?tjHV!Uk3@sWgF1Izp zm+|TvmaK7*wj<;-SK0B&h_QfM@>gI~-)qCj;9a)cJUr7MTw}I1nd&x&vQKrJOF!9e zDH=lD?0~#53^zw~FHi&b3s?)nRSr0^1ti?NXt3Owd<>PuN0gcE_Pm5z1e%qxP^iZ> zJc@-K_~H`GtIu~D4$Z?%@PSkU?q5P$l``9{jz&WABDd<+$5gi(NJ7e*^poutZbi&G z6{3D7Ev9=+4~q{kSdxVmp8b!khZiN{(_>1qXS$jx^<}Lm;^PVAAL>&}^=Y2^)LMPo zUQbfCEgsLidb9e;Uclm7!hQf}yR8Kc{Xu~QmE4WcsczHgDb%g03UpC(j8~t^s5v&r zQ)d6FMpKH+LXLE@-8unEf7xywv{Yt)>Dd}-x~~r#sb}t$N%>rHmn@bRm9^65e~*#0 zj7{I_$0Bq-)p&9GUX#1an5vD_`Ubla%Z^Dr&!1KBt8Ov5#H60eIVb$usEeDJcw7EV z;nf4!2-mFyFQs}DGxCEgPUBoCR5#RBbn`%9U7nhQz>>qm%O}@ zW>Q##Op4WWt>r&P(lR!|A;iSAJD!9L+oKV>iy?{BE~HU5n5t4cOGQ@4X>=2p8X^+x z=#9rEx;LR|L`3K+8af#^)whxOdW4U}IEwI|cJ^zAYLvSdp=p>y=v;`U74G!{gCn!s z^M=H&p)cFfD{6(gWXFd6d||;CpgIn!{>I#lUl(KXSVp<7v9tB46~;FN zG4IOb!9jSmm%EK=Pb>saVWOvZx6)=e75^G89-~nOEN>jr`3`CK-|aNT z9nt{~>9P*#%19ecGR{+AyZ~E}Qx}C(q0;`w3cprqB^LKWt!--NP;10+S7W#fZ>3tc zGdxDpGS-nEw=BE$CY8KT6PY<;2bi(07vb5pB-#1jb6~pDyHs7z?cU6o*S(##Vxt zMSU&rM(g5cW$L0+-i#?lCjTdjKPk^P=npmKvn#NgMXtdSQYn0QzROQlU>4t-H>5PH zn!?iNDF2)CX@1l6Qz0zd^^5mcAB%pn}|4iL1tGqN(#_JePVb@z}k^HYP||Ds_1C-Ntd2bgAH~o6_hP`7uB{> zA3ZGr(`sWc=Xp3Q8kagIIBeGEg2uT=>hn*LY^8qCx%3rv*bZHh#;1rhF7=hr^XB!~ zKP?t!O5Xe$5Cn$+%u!QSzzYCSwG@V7QWf?qV0QPTek7)yxoN%(PP5)sFwPyum)B<< zbWQo6^;v>`L7nuvQS6l7{l;-wMpIrOnpLULqZW#qb!wo!^US1A^WnM;vU?4c_H{Mh zIhq9o7E>RuRMVs(l8?t^c1Nr6CDF{cP-T^5T{XTtnw8VF;5VaLhoBHDrO(9^?+kI~ znyGQ-`hVeDO^2WdTGy+SJRycP!7XabVwj?vkiI{LUDN4$rl&SydR_SY!!rNFm0ss( zQ~N=4$V|PQ-PrJv9&)ltam#Gj!m^wG?X1CnYRq2gUsmV4Vv${`^sBMVU#A<%|7^nY z>8B~Xt6v_%&&9FV`t=ofMm)qEpZ23lRDkMBEmc?sU~y?)!E})WF4>F{ zyJTkDtYBIB*Hqwg$&Wsme9@@#PglGV2ZjVv*?$21UL_sOpR{02{A!eWouAg;HMN^d z3|81&&92dPP8t{e6Ut*+Vid7m;rm*mjSt{&TCy62ulYk1v)f1SCcH)~)~ci~6b<@H z>PwtKx+Z347-zo>*|M?~)9E5PZ_Qd`A-MUBHtF!N;>Vszw5`o ztrQ!tu1=dj=j9{l8dC=Qyv`r;yh=joJ6+bSe{^Gyr-~Dzh;eqR4Yqb$oahjflZ`Ui*f10z2$43oZ6yu@%e zO@Be3zH~U7rPHT*aNi_0LFd62C$UNm&MuS=Gd~}ynxk?SA#@-6J1<`h`X>(qa&2%) zUzi4Vol4ssw6e84D9Ya_v2FpImxa5eUW_*v{Uy%q<$mI`!Fa5GMTE(VOL@{r=BP+q3Ch|5TDHQ&DAhx8EoSxn^_quCT4<56SS zR{i*oJYWJVm98Jl=IHd(3-bBn(9hxRjxFPu;ydOwGOE`#IC|_oY6h)nWhGK{=MToQ zZ2f`veCv30Zo~NH@hq}uG54RqLQNlD!T#A;`lVigralkiQWNOQ zz>Sg9r+2*91lB}9`xW0dfek6+2jaN21e_qms7-gm5-RKMGYs_Q9BE8nUTY$YOm4UU z#`J%lmmi-UTMT;10aFY{J=n39_WXOcBtP&5_TEUDnxpEcg6HX%i*B1D>~0_p+~m-?&Po$Oa(_t}M9T%`Z#V6+Fw>0bu>7d-ysOOQ*+OWEnb?`~2S_tY$macMO%Kb3i;0l^zAso>)}l2TV*mM@w9co`GAD_LNPn!~Yhr4#hwU34C9{f33}Uso~_ z)C}oEE0UTjuJd}xSuI_8?z@Vu)$g^W?_0%w)#E<(MQd4j@%n?% z8S7pej}lj`mb58{>O9a zi#D)+hH?{*;nkEr8B{}oT{F;BGQ!``M58~7XINv!SU53*`+vvknChM*OS`Q-9*gcj zYAF4H2;cIc!SnuOeB^g5w$SNIlIUgzKmHwy)|=0AyvbTJ*|WR4WY;qrj*9kx6~;XTeHiz?Jl;J0j}4Jos_^A&yv8}qVWE!*(%DbWQ4Fwy|f zi?5II+$~IL{43glwRZ{s)tt>{`4`OB@$g!SlR+gN2! zmrOM;nw8J_l{eeQdgy1J;5)XlnYwDc>UK6>&olTI{OW?ZX$LE(e|MZW*})p}T}xczlQt-N_VX;H|v; z8Mr4s{|n=y9bi0&WU{$*iAqge>tq@it-8s7*oh(i%5>=WnF0PCZ|>T0kx1Z$+i7HY6LfF;1OaE(`POxieC-F;COm3ElQM|S65qFt%01YJQH zW9Uw+F$jX6VQuo;;w~<@pTZo`tv#x^E)`Hi8~E87(+10K4n1Mz)S|(7?u`CDHT*eN9{oTNXD)i3=&7p=Gn%4Z_`x4o zg!$^lrg<% z(d7vALyz4G47K-CT{p(QiT81Wx^>?N0FZHr7M&>#WKZ0lg^EhOsXChTMkcnuvv{a7lyy17?OtN{Q$K+Gj#X-T>RX zLs+zM5yR{6W?$6WeF%MiYF6Ux-^O^N%TyP=#13*aWF3t?+c;doR~&L8Mke77R@Y!* zKE!wLX660*fy%OvS~AW8VeT|5TQ_l`c(8}(?q-V7Mz(aO<;)c;JkwGNaBVRRy@ND< zK}*y@0Oh(PzrBZfmWlAdM) zrf{*BRnt%1&HeW=lj5p2z^6Z;rp%Kg<5CS>EE$J2ASp=o0RL(qM))ZQ_~CtQJ$j^0``K(v9Utsx({wF)_XF%kNC;R^G0BLu zV~b&>kmb!?YazcsK8w&VuxN_VOv|ta?Fx3t0H}59#~U*-D-M zuiZTH5UZ=-w40|MVzmptYz}PpPM&>;UDszE;Oh@FU!S?Vkm&)r_KI)u$b7TKD1QDh zt5UiqaB*oxgUO+Er!3VGnNUgJG($EM)4h(cc)k9?_q@kZ7O7wHJzss4jVQRaDUiuq zd5;6^ddP%5|5c*#&VMUWeY>iJey3ETK$|AWB9!+%&idkR>y%n9VhGMF!})CtHAs9>;&pV8bg71aszM)fs4qq^rZTT*l1YN;-Kj4~yfY zPq5(H{lem0j>+JaHo?y_U_nur#p+5lIUp85OQX)T1yJ-*TGL`J_`{!>ccmc+YKyJ2 z4~>BunaWVf&d?L15ikVB{F?!;a`dOBX!`{%_(WgKN#;{}9iFX@dX_QZ)Q{75vz*_` zN1tSMicE(Nw8`ck8_s8(VWEclwM~3u(~4e(*sXbdMx&bk9-%1P+Jw4rmdWZDxx7W? z8rV3T56EOeB|9_@cj=$nD$-ayx)^1LXWqPX#b86vT3U94wy4>8CZa@Zc3+?1pE6ms z>MmM-XBvgO9PU?@0&Fg_3o{m%JAfwuJ{^tKYAts>^X{iGsQM;C%YDaYP1r@q$(p;4 zA3nvZ7mMDEcs8n^{Ls2v4Y2k)%_H|6n|7gfDVM}}u~>6R%Tf!vzIX!LHV z6vX+AQ>=2a#hV;*n$=LtsfjhGmdJ@L=2^obi>JrA?`c-I*q!ejcrV6iyi00mQmpwd zk3UMN@xI8eE)al?(?f#&Mr)mKeLSBGyH5tvl{&*N-!vcI${|UCsv8 z(~ehz%fy+x2IKP0r*WyJgK@P74aF>~U&5-W93CCcw`L>HiAdbYW~_Sun?~e`J9g*- zRQ2Uc?2gIKs1o=s9nf5b0u8J}mE<93Sc@VDzES<4!55nMj0#uv(P0>OhSg?`z-{Ge zk5KH;AmFY)ujBq_vC^dH_0F<74GVxEKJ{b%<&=yued5zxgVo)Vv{l8>sKlC$vdz#= zN{`ZTWwYDMuVT>$_49+X$k@2mpC35ODwgO9sVpmgQcI=*)j0kNaKpn2_%P8qR-y1p zFZB)5WB5GiIp(jwwvi7x$L7(j>KqnkOg!j3tDt|ojyFBes@KU}N5hna;9`k&ex@mV zBLvY)(l*<^CfnAFOC5rXWgU0Xuu|FbOu(Glnq+rNpEV|g z8T+$gq4RT%uC`}{AbUjVg7PpWSNr!DF*2qEDwMT7W?}R6A7Q{bNEmzQ8eZZe2ClJd zc%6$ZsC2nC_CD~C`fVPq4?O=BAAJ$)5TkzP^)Iom)!NW_q+q5L5h8@yg4*P@wkVkN zO+i#8F7qhK_@kehm##Ixdx-@VXb2M8*a|9>q+5fpG%4P7S5eTNiY&XipLR95NYkJz zF-F3c^Et?E8-$|Na?qNiN<;v4X+<8-C{@OrU%$+Jnif~EA#lN8?=pR|m&@1!T~J}s zXaR2TS)5Dw*~1?oV;5^EA84tu*wt!dX_7uz{(wn}uI1IQu*!yUxH!Dm6&C3A!)lvC z29;#z8ou-j3l0cEzHkwDYdyk?EgLYDfo_*Cvr>(U11~Q4{Z}5-|CDEuO&&P|ZXeUG zeOr8wDWnvSzsjnGpMuGa#np){I($kBXoP*Jfcl7}7)?s_JQe0sKb&v7%DU(ytMUTZ z*oeAY>cL)nmQeed);t*h+|~htUvK&~b~=IHFd;b7*zqzFjf3kOy#Sf!F|S@Y|M430 z(T}gfv#(*b)U^t)`wMGY=twK_01Q+4;;OMB{NA9(eYwwd)=_`45>L9$dK!k-3Fp_Y zqlKnNhOfNA8tdOxdRs&|;Lg>Kr!|LJO_cr^nOn<0#i01ipk~cLQFSq5z z?V#~bU{M)UJeP8Dn}r)16=J;fudHd|c^D~SVQ(ig81^d*E8$y{M$I&2GKQQMG3N`o zaAl!aK>X;%7@(x}cgIM}I6DpBB(${Ojm8u=`;KvT3(Vpv@IHW4*)d^#`i-u8I;JKw z7S|E}Uq+s#-r-3E1E6uuX=&3-fq*x(*$1mSyGs+er$4AHtvCNl8HgR)A%)tm~tuDiP%&HpB$J}EB^fONI zd-oVKRI3`k@;;km7+xiur`~53Obg~ChIW@<@ItJMh^RtZW70$GgCSx#zjU9~NUm!p z+oZ^Qu+h#g1=EDBaj>5lIhPPo%__i=`XQ}$0hyL$jM%K{_FCHV#0Jc=RCY*5{a_`| zvIJoGXk}ak8fvb2MG+7a(wfpb&h7==`~c(Au?zUw2P~{uqcoyXPdJ<1KF#Na9%8bM zx0qW#VZnyudd8C;Vr{xh8ejX6Rc2$MZ9L5g<8d$-wj>teXF|ikjKokt>lbkN@-- z-Sx0}vHV=$vX%66WBJ>@Wozr^N_F&y^7+^&Sl?d<_?mtyKD!_Ab5y+Lvx@(DPAnhX zA9(!o{$*?HXX8Gn!DY*Oex_bV{SI$8OKGk=Wwi{SfUG+J#P}UB0GXvo(TvSLIT9!E zzn)^qetx!U$EPX(pB-z=w%c*Fq>^^roTA#XYKmsZ)w5JP{`rqdwWI#(EPnS9E9bgn zmS)HZ>L|tlPXQI_V?ALd`zD-a5C~yiheIMT@GNe5#!Mw^0*Brs8a9uaMNui%h0iEd zz9g?ISP}jCnY^B0we<~Ws)k$sfv*u*D*bt;%H4RTjl1EYc@P8kRoCiNRAs=;;KU`u}4pZ}*(l&~KW`Q=hYt!u?I) zzcB$O;`P1>J{JO&{yjPTZVH6Ra-1A4os`F`d>b63pOVKDzYVTlzz3P6j^}Qpf$7!N2524_=8%z{T|IC-4m~*(RMYZ}J!G zt>2f-xBtby)Ya#@SFCh_%;Ly?aC+HS%tz<>?dPU0u_?ceU5}uD{4;Nw$NCtW`GxcE z^H}xbQ>UU7vzwt z8#}Z^VWIG=V$(1AyrQ{mT%~O^z{Zk}v_pM_Dce@cX;%+R8IE~{+Of=%nfYfJ< z=F{F{8FkZWRav8XGzhT{_V*-;kd1i*R&EqtVHkOtdDVHFB>fxB!g*}fvKUG@hY}pd zR$Ye50^4{1W#rS|p{%cl@;&cZBSY;`d3=|yj8Dm`$S)ynm`lzsbOuXE%%WU*kHO>7 zKhZSIZa!mZV~EzesUc!JKP_s{{h|$#M3tB!2#HJb_m{&7zK&d@Bd41py$4zCK(&ZBNj&Z!teu7NVgInih_5Jvw5UdJusD!5 z0ux7f7h}pgh$+r=B`f1Qm1zbnzU8;VMq*THkcl6=^4x#0T3w3|_{ho{>X!`X=8x

5(QKTD{S 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

5j>*F~U}G)I1G!J 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
&j#JOIIBYcU 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

#kDn5I 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