From 33e6893c3ffa2f623fff3724b984dfdd750cbc5c Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Tue, 19 Nov 2024 19:04:56 -0800 Subject: [PATCH] latest server work --- .efrocachemap | 74 ++++++------- CHANGELOG.md | 2 +- .../ba_data/python/baclassic/_appmode.py | 11 +- src/assets/ba_data/python/baenv.py | 2 +- src/assets/ba_data/python/baplus/_cloud.py | 26 ++++- src/ballistica/shared/ballistica.cc | 2 +- tools/bacommon/cloud.py | 48 ++++++++ tools/bacommon/loggercontrol.py | 104 +++++++++++++++++- tools/bacommon/logging.py | 6 +- 9 files changed, 221 insertions(+), 54 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index cb76b18a..49087158 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,7 +421,7 @@ "build/assets/ba_data/audio/zoeOw.ogg": "b2d705c31c9dcc1efdc71394764c3beb", "build/assets/ba_data/audio/zoePickup01.ogg": "e9366dc2d2b8ab8b0c4e2c14c02d0789", "build/assets/ba_data/audio/zoeScream01.ogg": "903e0e45ee9b3373e9d9ce20c814374e", - "build/assets/ba_data/data/langdata.json": "f0e95ed70483f267a089d3e9b0368637", + "build/assets/ba_data/data/langdata.json": "54a0a77dc0adb7ed5dd76cd175741fc7", "build/assets/ba_data/data/languages/arabic.json": "4a6fc46285d6289ee14a7ccd9e801ac4", "build/assets/ba_data/data/languages/belarussian.json": "1004e5ea10b8deaef517fd37e9309521", "build/assets/ba_data/data/languages/chinese.json": "3c5e0a568008780f2e7258bf74b54efd", @@ -4099,42 +4099,42 @@ "build/assets/windows/Win32/ucrtbased.dll": "bfd1180c269d3950b76f35a63655e9e1", "build/assets/windows/Win32/vc_redist.x86.exe": "15a5f1f876503885adbdf5b3989b3718", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ecce51fae568b9707c40a39fbf3a3c5f", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "55e2a22a34a9be909e26c994fb8ea04e", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5e7ad42b0231a8e9ed021b1c389da269", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "9d0fc45c65d34d595af470cf83694bf5", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "63159906ae9af2b667bd70effd4dabe7", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "bff1c5b6386348a6182707f2b3cdae62", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "fa4e52fa3d0d9e18d6700bd8057b196d", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "0158103f20133191f92dbd5f9f4db6b5", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0b28e5294e7f5e75265fdf23b9aacf73", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "3db1de36fc4bc7779a96abe5d5e08af5", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ca92fc0dbae8d0257eafcedbd7253f71", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "5e4d1ff3c9f1eae795ff22d378ac00f9", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "3053e0bada8af66f14dd057f92149219", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "7a1b405aa133401a170f07e5eefe9117", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "94bf374b52eeee75056f2df342fcbc6e", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ec4d6375e15add5f09eff1548b270084", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "1d372863f6743d0e402252625039347a", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "d33f46eee6acbbb23ced2fde0b3c8617", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "1d372863f6743d0e402252625039347a", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "d33f46eee6acbbb23ced2fde0b3c8617", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "dff40e5da979f86971b81a82753b35c7", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "3e3b687f20740625087efd9b206605f8", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "dff40e5da979f86971b81a82753b35c7", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "3e3b687f20740625087efd9b206605f8", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "3c0e995c26af01aed002e720b2498302", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "e8df0adda61c64e63b8755d909f0113b", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "3c0e995c26af01aed002e720b2498302", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "e8df0adda61c64e63b8755d909f0113b", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "0d6db8516440603342edae1efed0cd52", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "a2f95c8bb1fd261bbc2d47b7559e7d4e", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b81c189c2c6a79e92dbfe3d0dd5c6adf", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "673f2b052879488544dc1d0b6e46ae27", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "5cbaad5b761638f0c23505504739790b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "121bc8047b8f0b20cdc7139a92fcb50b", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "3fc2c917f416dad9e4c2413a96da5702", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "667d6372dbd8862fd9542ee4b3d1ae88", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d80015d5c99619938a2e627d53ac5864", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "aff410422f7d29bda3dfcec42f7dc737", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "e7ed11250d1f4d1d27e669557f25b8ec", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "862efb702f9380faad0a18b8508005da", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "f40c265219d3506bb58d246e792eb67c", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a50c6ed069c6251a1df383cb5992c16c", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "e2cccc17a9908efeed257c034f2c15fd", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "fc2130ec257a107c32f4a0e64cb5d571", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d55ae00e13b66a3e3a541a376f0b2359", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "5779299c37221ada7cba971e83ec7d81", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b9ee0d4ff328e4e47968a58ded05d46d", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d264fcfea3483ddbac19df6e89ef98ba", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9b130271daeb479f98c03a15f9834a23", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b32b31e25d2fda4e8463578ec287b0f5", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8094b1d13e3c5680762a6984fffe3da3", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "ecb1c290a5a071a11f858551b06f482a", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "9f68628128b83900865751c347964c77", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "0ad4775fc4ff5cd2e3b63ecf7823daa4", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "9f68628128b83900865751c347964c77", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "0ad4775fc4ff5cd2e3b63ecf7823daa4", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "087b7eec0a029b66b957bce579c9ebbd", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "46a360165efa06de3e5d562c5daddddb", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "087b7eec0a029b66b957bce579c9ebbd", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "46a360165efa06de3e5d562c5daddddb", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "28b13d45428184f0715565c54f23b115", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "41f933cc9a7c6cb748ff2fb0d5237b4d", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "28b13d45428184f0715565c54f23b115", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "41f933cc9a7c6cb748ff2fb0d5237b4d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "07f4205482e7e90e60f36acd7424f52a", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ddfe00fe33cebfed592c06fe52866995", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "48c0fdc7b606eb211b48ceaaefa06431", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "3e0d9bf058c59087006df668a8cedbfc", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "621e2598aa8cca9af188b838f103695b", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "847204a7d32dbbf21858f7de32ed2836", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "13983ea5c18d7cde170d5bb7758aee2f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "8bfe1218083ab60808e234142525778f", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad", "src/ballistica/base/mgen/pyembed/binding_base.inc": "3a583e7e03bd4907b21adc3bf5729d15", diff --git a/CHANGELOG.md b/CHANGELOG.md index 70b67428..b2a1572b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.37 (build 22102, api 9, 2024-11-14) +### 1.7.37 (build 22103, api 9, 2024-11-19) - Bumping api version to 9. As you'll see below, there's some UI changes that will require a bit of work for any UI mods to adapt to. If your mods don't touch UI stuff at all you can simply bump your api version and call it a day. diff --git a/src/assets/ba_data/python/baclassic/_appmode.py b/src/assets/ba_data/python/baclassic/_appmode.py index ee6e765e..c45c2221 100644 --- a/src/assets/ba_data/python/baclassic/_appmode.py +++ b/src/assets/ba_data/python/baclassic/_appmode.py @@ -157,20 +157,21 @@ class ClassicAppMode(AppMode): """Update subscriptions/etc. for a new primary account state.""" assert in_logic_thread() - if bool(True): + # Test subscription. + if bool(False): assert app.plus is not None if account is None: self._test_sub = None else: with account: - self._test_sub = app.plus.cloud.subscribe( - self._on_sub_update + self._test_sub = app.plus.cloud.subscribe_test( + self._on_sub_test_update ) else: self._test_sub = None - def _on_sub_update(self, val: Any) -> None: - print(f'GOT SUB UPDATE: {val}') + def _on_sub_test_update(self, val: int | None) -> None: + print(f'GOT SUB TEST UPDATE: {val}') def _root_ui_menu_press(self) -> None: from babase import push_back_press diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index e8a07cd1..52c304f1 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -53,7 +53,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 22102 +TARGET_BALLISTICA_BUILD = 22103 TARGET_BALLISTICA_VERSION = '1.7.37' diff --git a/src/assets/ba_data/python/baplus/_cloud.py b/src/assets/ba_data/python/baplus/_cloud.py index 285f9b26..a3a83aff 100644 --- a/src/assets/ba_data/python/baplus/_cloud.py +++ b/src/assets/ba_data/python/baplus/_cloud.py @@ -5,6 +5,7 @@ from __future__ import annotations import logging +from functools import partial from typing import TYPE_CHECKING, overload import babase @@ -174,13 +175,32 @@ class CloudSubsystem(babase.AppSubsystem): 'Cloud functionality is not present in this build.' ) - def subscribe( - self, updatecall: Callable[[Any], None] + def subscribe_test( + self, updatecall: Callable[[int | None], None] ) -> babase.CloudSubscription: """Subscribe to some data.""" from bacommon.cloud import TestCloudSubscriptionRequest - return self._subscribe(TestCloudSubscriptionRequest(), updatecall) + assert babase.in_logic_thread() + + return self._subscribe( + TestCloudSubscriptionRequest(), + partial(self._on_sub_value_test, updatecall), + ) + + @staticmethod + def _on_sub_value_test( + cb: Callable[[int | None], None], + invalue: bacommon.cloud.CloudSubscriptionValue, + ) -> None: + from bacommon.cloud import TestCloudSubscriptionValue + + assert babase.in_logic_thread() + + # Make sure we got the type we expected for this sub and pass it + # to the user callback. + assert isinstance(invalue, TestCloudSubscriptionValue) + cb(invalue.value) def _subscribe( self, diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index c4622f70..75d47f22 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int { namespace ballistica { // These are set automatically via script; don't modify them here. -const int kEngineBuildNumber = 22102; +const int kEngineBuildNumber = 22103; const char* kEngineVersion = "1.7.37"; const int kEngineApiVersion = 9; diff --git a/tools/bacommon/cloud.py b/tools/bacommon/cloud.py index 6d71c36f..4975e16f 100644 --- a/tools/bacommon/cloud.py +++ b/tools/bacommon/cloud.py @@ -369,3 +369,51 @@ class TestCloudSubscriptionRequest(CloudSubscriptionRequest): @classmethod def get_type_id(cls) -> CloudSubscriptionRequestTypeID: return CloudSubscriptionRequestTypeID.TEST + + +class CloudSubscriptionValueTypeID(Enum): + """Type ID for each of our subclasses.""" + + TEST = 'test' + + +class CloudSubscriptionValue(IOMultiType[CloudSubscriptionValueTypeID]): + """Top level class for our multitype.""" + + @override + @classmethod + def get_type_id(cls) -> CloudSubscriptionValueTypeID: + # 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: CloudSubscriptionValueTypeID + ) -> type[CloudSubscriptionValue]: + """Return the subclass for each of our type-ids.""" + # pylint: disable=cyclic-import + out: type[CloudSubscriptionValue] + + t = CloudSubscriptionValueTypeID + if type_id is t.TEST: + out = TestCloudSubscriptionValue + else: + # Important to make sure we provide all types. + assert_never(type_id) + return out + + +@ioprepped +@dataclass +class TestCloudSubscriptionValue(CloudSubscriptionValue): + """Just a test.""" + + value: Annotated[int | None, IOAttrs('v')] + + @override + @classmethod + def get_type_id(cls) -> CloudSubscriptionValueTypeID: + return CloudSubscriptionValueTypeID.TEST diff --git a/tools/bacommon/loggercontrol.py b/tools/bacommon/loggercontrol.py index e34fd143..e07e8117 100644 --- a/tools/bacommon/loggercontrol.py +++ b/tools/bacommon/loggercontrol.py @@ -11,7 +11,7 @@ from dataclasses import dataclass, field from efro.dataclassio import ioprepped, IOAttrs if TYPE_CHECKING: - from typing import Self + from typing import Self, Sequence @ioprepped @@ -23,17 +23,64 @@ class LoggerControlConfig: set to NOTSET. """ - # Logger names mapped to log-level values (from system logging module). + # Logger names mapped to log-level values (from system logging + # module). levels: Annotated[dict[str, int], IOAttrs('l', store_default=False)] = ( field(default_factory=dict) ) - def apply(self) -> None: - """Apply the config to all Python loggers.""" + def apply( + self, + *, + warn_unexpected_loggers: bool = False, + warn_missing_loggers: bool = False, + ignore_log_prefixes: list[str] | None = None, + ) -> None: + """Apply the config to all Python loggers. + + If 'warn_unexpected_loggers' is True, warnings will be issues for + any loggers not explicitly covered by the config. This is useful + to help ensure controls for all possible loggers are present in + a UI/etc. + + If 'warn_missing_loggers' is True, warnings will be issued for + any loggers present in the config that are not found at apply time. + This can be useful for pruning settings for no longer used loggers. + + Warnings for any log names beginning with any strings in + 'ignore_log_prefixes' will be suppressed. This can allow + ignoring loggers associated with submodules for a given package + and instead presenting only a top level logger (or none at all). + """ + if ignore_log_prefixes is None: + ignore_log_prefixes = [] + existinglognames = ( set(['root']) | logging.root.manager.loggerDict.keys() ) + # First issue any warnings they want. + if warn_unexpected_loggers: + for logname in sorted(existinglognames): + if logname not in self.levels and not any( + logname.startswith(pre) for pre in ignore_log_prefixes + ): + logging.warning( + 'Found a logger not covered by LoggerControlConfig:' + " '%s'.", + logname, + ) + if warn_missing_loggers: + for logname in sorted(self.levels.keys()): + if logname not in existinglognames and not any( + logname.startswith(pre) for pre in ignore_log_prefixes + ): + logging.warning( + 'Logger covered by LoggerControlConfig does not exist:' + ' %s.', + logname, + ) + # First, update levels for all existing loggers. for logname in existinglognames: logger = logging.getLogger(logname) @@ -47,6 +94,48 @@ class LoggerControlConfig: if logname not in existinglognames: logging.getLogger(logname).setLevel(level) + def sanity_check_effective_levels(self) -> None: + """Checks existing loggers to make sure they line up with us. + + This can be called periodically to ensure that a control-config + is properly driving log levels and that nothing else is changing + them behind our back. + """ + + existinglognames = ( + set(['root']) | logging.root.manager.loggerDict.keys() + ) + for logname in existinglognames: + logger = logging.getLogger(logname) + if logger.getEffectiveLevel() != self.get_effective_level(logname): + logging.error( + 'loggercontrol effective-level sanity check failed;' + ' expected logger %s to have effective level %s' + ' but it has %s.', + logname, + logging.getLevelName(self.get_effective_level(logname)), + logging.getLevelName(logger.getEffectiveLevel()), + ) + + def get_effective_level(self, logname: str) -> int: + """Given a log name, predict its level if this config is applied.""" + splits = logname.split('.') + + splen = len(splits) + for i in range(splen): + subname = '.'.join(splits[: splen - i]) + thisval = self.levels.get(subname) + if thisval is not None and thisval != logging.NOTSET: + return thisval + + # Haven't found anything; just return root value. + thisval = self.levels.get('root') + return ( + logging.DEBUG + if thisval is None + else logging.DEBUG if thisval == logging.NOTSET else thisval + ) + def would_make_changes(self) -> bool: """Return whether calling apply would change anything.""" @@ -94,7 +183,12 @@ class LoggerControlConfig: def apply_diff( self, diffconfig: LoggerControlConfig ) -> LoggerControlConfig: - """Apply a diff config to ourself.""" + """Apply a diff config to ourself. + + Note that values that resolve to NOTSET are left intact in the + output config. This is so all loggers expected by either the + base or diff config to exist can be created if desired/etc. + """ cls = type(self) # Create a new config (with an indepenent levels dict copy). diff --git a/tools/bacommon/logging.py b/tools/bacommon/logging.py index 81f9baf3..120b96ee 100644 --- a/tools/bacommon/logging.py +++ b/tools/bacommon/logging.py @@ -13,7 +13,11 @@ if TYPE_CHECKING: def get_base_logger_control_config_client() -> LoggerControlConfig: - """Return the logger-control-config used by the ballistica client.""" + """Return the logger-control-config used by the ballistica client. + + This should remain consistent since local logger configurations + are stored relative to this. + """ # By default, go with WARNING on everything to keep things mostly # clean but show INFO for ba.lifecycle to get basic app