more client-server work

This commit is contained in:
Eric Froemling 2024-11-22 12:05:30 -08:00
parent 69aaf6d4f9
commit ab25bd573f
No known key found for this signature in database
28 changed files with 200 additions and 191 deletions

74
.efrocachemap generated
View File

@ -4099,48 +4099,48 @@
"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": "f2b4a48180ab14d238b41e1530381393",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "e89a3f4680e8800f94a47ba00fda82e9",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9e58df7e8dc622d0e07bcc2e5e01980b",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "76e0ee141fc138b015e466b876ca5c40",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "dc69ff22b10a69bd68551921e80e6d4f",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "382f41634994e64aef25cbd89ad30608",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "99b67d89e72156fecf82728f3ca9023e",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "9e123048c9a937623bf8a9049fe52a68",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "0bb1ebf96216318b97f624ca01515319",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "fe741b2e775639b715245a6397ce0f01",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "463e5220f0987196df4b74433eb6b533",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "fcdcc5a4214eff648234f0f6ad8db286",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "71eb60bca0efb35b5519359f32701ef0",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "4409110d1107f9ec6ea314574b963092",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "8287610eeae417260ef3891d09526366",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "07783dd9ef83a4417d9e7b8769e704e1",
"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": "d31f476fe2587f891662739d5cf66498",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "42d34950f26b92cf25b190868f53a20f",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "98912594ab71b0f9f64a24e8234b7a6a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "7475905e88c2a39f34c4bd216b9efffd",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d9ceb775128672c17f00e2b2c01c6e4e",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "5546313b197639b7ec6d02a69297ef26",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4f0e09828aaa10b9a5ad9693ecc9d269",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "028fdd9f3d6434b2779f94eafc6f82f1",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "31d6ac3cce2b7d2a38555ad54e6f1b42",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "021d06fb3c8b2963306ebe0602b7c91b",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "41c85f9bdc2e042e502ce23c4faf082d",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "6b3e752d93ee5aa06a738c58f96e3e98",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4928e07ec24903103f69cf25f1969dce",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "6a70b3e614c3fa0869af93c2620997b4",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "987153b6539715573fe87b8f6675366d",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "130bbcc6e253ea27d580bbec0da23ffb",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d0ca3125ba2aa6933dc1ed74856e67e4",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "f582343e05c4316af68950f33d9189ea",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "cb8a142b86c07e3e19b27339f7760697",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1e8480010c07972b2b97f8f0dd5a557e",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "a6201b97f6d36164843c12fb064e4e14",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "d999ef97283b39c844f848d6fa0f56ce",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "22aad71eb4295c6d9d0bf216014a78a7",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "b1f33f4492547b97b9f5f42b3be83524",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "9d953b981a1ccf4623a6947ee9bafde7",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b7d3fd701b31ec1b624606e1ca42e4bb",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "9d953b981a1ccf4623a6947ee9bafde7",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "b7d3fd701b31ec1b624606e1ca42e4bb",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "2141f1d64ea3eadac63e6e95c517b751",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "5d04a19962d612f977200e27b194f560",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "2141f1d64ea3eadac63e6e95c517b751",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "5d04a19962d612f977200e27b194f560",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "d0a989e1650ba8e19ac7f661355ca7cd",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "a2ebc84706ed89c1558f3171e985a959",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "d0a989e1650ba8e19ac7f661355ca7cd",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "a2ebc84706ed89c1558f3171e985a959",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "365ff249753d35076b02ae97b2aaa203",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "eb0ec0c8e8ea0f87a91980909252330f",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b525d2fd7b406faf76846aae763c4c24",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "851b26948af977fc31285e5ebd443f6a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "790cc46a5ad2478eb11148a3748db84a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "7d70ea7fd9992b3f54372ce0126418c2",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "bdcedd07d700c15dda2f9cd616d50db3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "4d79e3979dbe6c45eb7a2921a0a116bb",
"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",
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "f0f9dc33ecd4ef7a384f131d62c96c97",
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
"src/ballistica/core/mgen/pyembed/binding_core.inc": "02bf828e423d0fced4d87aa74f25cbdc",
"src/ballistica/core/mgen/pyembed/binding_core.inc": "aa91582493f32d54825d0c8bc007a902",
"src/ballistica/core/mgen/pyembed/env.inc": "f015d726b44d2922112fc14d9f146d8b",
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",

View File

@ -1,4 +1,4 @@
### 1.7.37 (build 22105, api 9, 2024-11-19)
### 1.7.37 (build 22106, api 9, 2024-11-22)
- 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.

View File

@ -22,6 +22,7 @@
"ba_data/python/babase/__pycache__/_general.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_hooks.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_language.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_logging.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_login.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_math.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_meta.cpython-312.opt-1.pyc",
@ -52,6 +53,7 @@
"ba_data/python/babase/_general.py",
"ba_data/python/babase/_hooks.py",
"ba_data/python/babase/_language.py",
"ba_data/python/babase/_logging.py",
"ba_data/python/babase/_login.py",
"ba_data/python/babase/_math.py",
"ba_data/python/babase/_meta.py",

View File

@ -185,6 +185,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/_general.py \
$(BUILD_DIR)/ba_data/python/babase/_hooks.py \
$(BUILD_DIR)/ba_data/python/babase/_language.py \
$(BUILD_DIR)/ba_data/python/babase/_logging.py \
$(BUILD_DIR)/ba_data/python/babase/_login.py \
$(BUILD_DIR)/ba_data/python/babase/_math.py \
$(BUILD_DIR)/ba_data/python/babase/_meta.py \
@ -464,6 +465,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_general.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_hooks.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_language.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_logging.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_login.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_math.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_meta.cpython-312.opt-1.pyc \

View File

@ -17,15 +17,14 @@ a more focused way.
# dependency loops. The exception is TYPE_CHECKING blocks and
# annotations since those aren't evaluated at runtime.
import logging
from efro.util import set_canonical_module_names
import _babase
from _babase import (
add_clean_frame_callback,
allows_ticket_sales,
android_get_external_files_dir,
app_instance_uuid,
appname,
appnameupper,
apptime,
@ -114,6 +113,7 @@ from _babase import (
unlock_all_input,
update_internal_logger_levels,
user_agent_string,
user_ran_commands,
Vec3,
workspaces_in_use,
)
@ -172,10 +172,9 @@ from babase._general import (
get_type_name,
)
from babase._language import Lstr, LanguageSubsystem
from babase._logging import balog, lifecyclelog
from babase._login import LoginAdapter, LoginInfo
# noinspection PyProtectedMember
# (PyCharm inspection bug?)
from babase._mgen.enums import (
Permission,
SpecialChar,
@ -190,8 +189,6 @@ from babase._plugin import PluginSpec, Plugin, PluginSubsystem
from babase._stringedit import StringEditAdapter, StringEditSubsystem
from babase._text import timestring
# Our standard set of loggers.
balog = logging.getLogger('ba')
_babase.app = app = App()
app.postinit()
@ -213,6 +210,7 @@ __all__ = [
'AppIntentDefault',
'AppIntentExec',
'AppMode',
'app_instance_uuid',
'appname',
'appnameupper',
'AppModeSelector',
@ -287,6 +285,7 @@ __all__ = [
'is_point_in_box',
'is_xcode_build',
'LanguageSubsystem',
'lifecyclelog',
'lock_all_input',
'LoginAdapter',
'LoginInfo',
@ -356,6 +355,7 @@ __all__ = [
'unlock_all_input',
'update_internal_logger_levels',
'user_agent_string',
'user_ran_commands',
'utf8_all',
'Vec3',
'vec3validate',

View File

@ -24,6 +24,7 @@ from babase._appintent import AppIntentDefault, AppIntentExec
from babase._stringedit import StringEditSubsystem
from babase._devconsole import DevConsoleSubsystem
from babase._appconfig import AppConfig
from babase._logging import lifecyclelog
if TYPE_CHECKING:
import asyncio
@ -871,7 +872,7 @@ class App:
def _apply_app_config(self) -> None:
assert _babase.in_logic_thread()
_babase.lifecyclelog('apply-app-config')
lifecyclelog.info('apply-app-config')
# If multiple apply calls have been made, only actually apply
# once.
@ -903,7 +904,7 @@ class App:
if self._native_shutdown_complete_called:
if self.state is not self.State.SHUTDOWN_COMPLETE:
self.state = self.State.SHUTDOWN_COMPLETE
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
self._on_shutdown_complete()
# Shutdown trumps all. Though we can't start shutting down until
@ -913,7 +914,7 @@ class App:
# Entering shutdown state:
if self.state is not self.State.SHUTTING_DOWN:
self.state = self.State.SHUTTING_DOWN
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
self._on_shutting_down()
elif self._native_suspended:
@ -930,7 +931,7 @@ class App:
if self._initial_sign_in_completed and self._meta_scan_completed:
if self.state != self.State.RUNNING:
self.state = self.State.RUNNING
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
if not self._called_on_running:
self._called_on_running = True
self._on_running()
@ -939,7 +940,7 @@ class App:
elif self._init_completed:
if self.state is not self.State.LOADING:
self.state = self.State.LOADING
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
if not self._called_on_loading:
self._called_on_loading = True
self._on_loading()
@ -948,7 +949,7 @@ class App:
elif self._native_bootstrapping_completed:
if self.state is not self.State.INITING:
self.state = self.State.INITING
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
if not self._called_on_initing:
self._called_on_initing = True
self._on_initing()
@ -957,7 +958,7 @@ class App:
elif self._native_start_called:
if self.state is not self.State.NATIVE_BOOTSTRAPPING:
self.state = self.State.NATIVE_BOOTSTRAPPING
_babase.lifecyclelog(f'app-state is now {self.state.name}')
lifecyclelog.info('app-state is now %s', self.state.name)
else:
# Only logical possibility left is NOT_STARTED, in which
# case we should not be getting called.
@ -1068,10 +1069,10 @@ class App:
# Spin and wait for anything blocking shutdown to complete.
starttime = _babase.apptime()
_babase.lifecyclelog('shutdown-suppress-wait begin')
lifecyclelog.info('shutdown-suppress-wait begin')
while _babase.shutdown_suppress_count() > 0:
await asyncio.sleep(0.001)
_babase.lifecyclelog('shutdown-suppress-wait end')
lifecyclelog.info('shutdown-suppress-wait end')
duration = _babase.apptime() - starttime
if duration > 1.0:
logging.warning(
@ -1084,7 +1085,7 @@ class App:
import asyncio
# Kick off a short fade and give it time to complete.
_babase.lifecyclelog('fade-and-shutdown-graphics begin')
lifecyclelog.info('fade-and-shutdown-graphics begin')
_babase.fade_screen(False, time=0.15)
await asyncio.sleep(0.15)
@ -1093,19 +1094,19 @@ class App:
_babase.graphics_shutdown_begin()
while not _babase.graphics_shutdown_is_complete():
await asyncio.sleep(0.01)
_babase.lifecyclelog('fade-and-shutdown-graphics end')
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.
_babase.lifecyclelog('fade-and-shutdown-audio begin')
lifecyclelog.info('fade-and-shutdown-audio begin')
_babase.audio_shutdown_begin()
await asyncio.sleep(0.15)
while not _babase.audio_shutdown_is_complete():
await asyncio.sleep(0.01)
_babase.lifecyclelog('fade-and-shutdown-audio end')
lifecyclelog.info('fade-and-shutdown-audio end')
def _threadpool_no_wait_done(self, fut: Future) -> None:
try:

View File

@ -0,0 +1,11 @@
# Released under the MIT License. See LICENSE for details.
#
"""Logging functionality."""
from __future__ import annotations
import logging
# Our standard set of loggers.
balog = logging.getLogger('ba')
lifecyclelog = logging.getLogger('ba.lifecycle')

View File

@ -3,6 +3,7 @@
"""Contains ClassicAppMode."""
from __future__ import annotations
import os
import logging
from functools import partial
from typing import TYPE_CHECKING, override
@ -157,8 +158,8 @@ class ClassicAppMode(AppMode):
"""Update subscriptions/etc. for a new primary account state."""
assert in_logic_thread()
# Test subscription.
if bool(False):
# For testing subscription functionality.
if os.environ.get('BA_SUBSCRIPTION_TEST') == '1':
assert app.plus is not None
if account is None:
self._test_sub = None

View File

@ -53,7 +53,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 22105
TARGET_BALLISTICA_BUILD = 22106
TARGET_BALLISTICA_VERSION = '1.7.37'
@ -216,7 +216,7 @@ def configure(
# (including cached history) to the os-specific output location.
# This means anything printed or logged at this point forward should
# be visible on all platforms.
log_handler = _setup_logging(launch_time) if setup_logging else None
log_handler = _create_log_handler(launch_time) if setup_logging else None
# Load the raw app-config dict.
app_config = _read_app_config(os.path.join(config_dir, 'config.json'))
@ -311,7 +311,7 @@ def _calc_data_dir(data_dir: str | None) -> str:
return data_dir
def _setup_logging(launch_time: float) -> LogHandler:
def _create_log_handler(launch_time: float) -> LogHandler:
from efro.logging import setup_logging, LogLevel
log_handler = setup_logging(
@ -336,7 +336,8 @@ def _set_log_levels(app_config: dict) -> None:
get_base_logger_control_config_client().apply()
return
# Make sure data is expected types/values.
# Make sure data is expected types/values since this is user
# editable.
valid_levels = {
logging.NOTSET,
logging.DEBUG,

View File

@ -5,7 +5,6 @@
from __future__ import annotations
import logging
from functools import partial
from typing import TYPE_CHECKING, overload
import babase
@ -179,35 +178,6 @@ class CloudSubsystem(babase.AppSubsystem):
self, updatecall: Callable[[int | None], None]
) -> babase.CloudSubscription:
"""Subscribe to some data."""
from bacommon.cloud import TestCloudSubscriptionRequest
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,
request: bacommon.cloud.CloudSubscriptionRequest,
updatecall: Callable[[Any], None],
) -> babase.CloudSubscription:
"""Subscribe to some cloud data."""
raise NotImplementedError(
'Cloud functionality is not present in this build.'
)

View File

@ -14,6 +14,7 @@ from bacommon.login import LoginType
import bacommon.cloud
import bauiv1 as bui
from bauiv1lib.connectivity import wait_for_connectivity
# These days we're directing people to the web based account settings
# for V2 account linking and trying to get them to disconnect remaining
@ -1180,19 +1181,17 @@ class AccountSettingsWindow(bui.MainWindow):
self._do_manage_account_press(WebLocation.ACCOUNT_DELETE_SECTION)
def _do_manage_account_press(self, weblocation: WebLocation) -> None:
# If we're still waiting for our master-server connection,
# keep the user informed of this instead of rushing in and
# failing immediately.
wait_for_connectivity(
on_connected=lambda: self._do_manage_account(weblocation)
)
def _do_manage_account(self, weblocation: WebLocation) -> None:
plus = bui.app.plus
assert plus is not None
# Preemptively fail if it looks like we won't be able to talk to
# the server anyway.
if not plus.cloud.connected:
bui.screenmessage(
bui.Lstr(resource='internal.unavailableNoConnectionText'),
color=(1, 0, 0),
)
bui.getsound('error').play()
return
bui.screenmessage(bui.Lstr(resource='oneMomentText'))
# We expect to have a v2 account signed in if we get here.
@ -1427,8 +1426,6 @@ class AccountSettingsWindow(bui.MainWindow):
bui.apptimer(0.1, bui.WeakCall(self._update))
def _sign_in_press(self, login_type: str | LoginType) -> None:
from bauiv1lib.connectivity import wait_for_connectivity
# If we're still waiting for our master-server connection,
# keep the user informed of this instead of rushing in and
# failing immediately.
@ -1522,9 +1519,6 @@ class AccountSettingsWindow(bui.MainWindow):
bui.apptimer(0.1, bui.WeakCall(self._update))
def _v2_proxy_sign_in_press(self) -> None:
# pylint: disable=cyclic-import
from bauiv1lib.connectivity import wait_for_connectivity
# If we're still waiting for our master-server connection, keep
# the user informed of this instead of rushing in and failing
# immediately.

View File

@ -89,7 +89,7 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
assert(g_core == nullptr);
g_core = core::CoreFeatureSet::Import();
g_core->LifecycleLog("_babase exec begin");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_babase exec begin");
// This locks in a baenv configuration.
g_core->ApplyBaEnvConfig();
@ -133,7 +133,7 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
assert(!g_base->base_native_import_completed_);
g_base->base_native_import_completed_ = true;
g_core->LifecycleLog("_babase exec end");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_babase exec end");
}
void BaseFeatureSet::OnReachedEndOfBaBaseImport() {
@ -206,7 +206,8 @@ void BaseFeatureSet::StartApp() {
called_start_app_ = true;
assert(!app_started_); // Shouldn't be possible.
g_core->LifecycleLog("start-app begin (main thread)");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"start-app begin (main thread)");
LogVersionInfo_();
@ -246,7 +247,8 @@ void BaseFeatureSet::StartApp() {
python->objs().Get(BasePython::ObjID::kAppPushApplyAppConfigCall).Call();
}
g_core->LifecycleLog("start-app end (main thread)");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"start-app end (main thread)");
// Make some noise if this takes more than a few seconds. If we pass 5
// seconds or so we start to trigger App-Not-Responding reports which
@ -410,7 +412,8 @@ void BaseFeatureSet::OnAppShutdownComplete() {
assert(g_base);
// Flag our own event loop to exit (or ask the OS to if they're managing).
g_core->LifecycleLog("app exiting (main thread)");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"app exiting (main thread)");
if (app_adapter->ManagesMainThreadEventLoop()) {
app_adapter->DoExitMainThreadEventLoop();
} else {

View File

@ -37,7 +37,8 @@ void Logic::OnMainThreadStartApp() {
void Logic::OnAppStart() {
assert(g_base->InLogicThread());
g_core->LifecycleLog("on-app-start begin (logic thread)");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"on-app-start begin (logic thread)");
// Our thread should not be holding the GIL here at the start (and
// probably will not have any Python state at all). So here we set both
@ -73,7 +74,8 @@ void Logic::OnAppStart() {
}
g_base->python->OnAppStart();
g_core->LifecycleLog("on-app-start end (logic thread)");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"on-app-start end (logic thread)");
}
void Logic::OnGraphicsReady() {
@ -118,7 +120,8 @@ void Logic::CompleteAppBootstrapping_() {
assert(!app_bootstrapping_complete_);
app_bootstrapping_complete_ = true;
g_core->LifecycleLog("app native bootstrapping complete");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"app native bootstrapping complete");
// Let the assets system know it can start loading stuff now that
// we have a screen and thus know texture formats/etc.

View File

@ -855,31 +855,31 @@ static PyMethodDef PyEmitLogDef = {
// ------------------------------ lifecyclelog ---------------------------------
static auto PyLifecycleLog(PyObject* self, PyObject* args, PyObject* keywds)
-> PyObject* {
BA_PYTHON_TRY;
static const char* kwlist[] = {"message", nullptr};
const char* message;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
const_cast<char**>(kwlist), &message)) {
return nullptr;
}
// static auto PyLifecycleLog(PyObject* self, PyObject* args, PyObject* keywds)
// -> PyObject* {
// BA_PYTHON_TRY;
// static const char* kwlist[] = {"message", nullptr};
// const char* message;
// if (!PyArg_ParseTupleAndKeywords(args, keywds, "s",
// const_cast<char**>(kwlist), &message)) {
// return nullptr;
// }
g_core->LifecycleLog(message);
// g_core->LifecycleLog(message);
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
// Py_RETURN_NONE;
// BA_PYTHON_CATCH;
// }
static PyMethodDef PyLifecycleLogDef = {
"lifecyclelog", // name
(PyCFunction)PyLifecycleLog, // method
METH_VARARGS | METH_KEYWORDS, // flags
// static PyMethodDef PyLifecycleLogDef = {
// "lifecyclelog", // name
// (PyCFunction)PyLifecycleLog, // method
// METH_VARARGS | METH_KEYWORDS, // flags
"lifecyclelog(message: str) -> None\n"
"\n"
"(internal)",
};
// "lifecyclelog(message: str) -> None\n"
// "\n"
// "(internal)",
// };
// ----------------------------- v1_cloud_log ----------------------------------
@ -1722,7 +1722,7 @@ auto PythonMethodsBase1::GetMethods() -> std::vector<PyMethodDef> {
PyMacMusicAppPlayPlaylistDef,
PyMacMusicAppGetPlaylistsDef,
PyIsOSPlayingMusicDef,
PyLifecycleLogDef,
// PyLifecycleLogDef,
PyExecArgDef,
PyOnAppRunningDef,
PyOnInitialAppModeSetDef,

View File

@ -30,7 +30,7 @@ void ClassicFeatureSet::OnModuleExec(PyObject* module) {
assert(g_core == nullptr);
g_core = core::CoreFeatureSet::Import();
g_core->LifecycleLog("_baclassic exec begin");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_baclassic exec begin");
// Create our feature-set's C++ front-end.
assert(g_classic == nullptr);
@ -54,7 +54,7 @@ void ClassicFeatureSet::OnModuleExec(PyObject* module) {
assert(g_scene_v1 == nullptr);
g_scene_v1 = scene_v1::SceneV1FeatureSet::Import();
g_core->LifecycleLog("_baclassic exec end");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_baclassic exec end");
}
ClassicFeatureSet::ClassicFeatureSet()

View File

@ -78,15 +78,8 @@ void CoreFeatureSet::DoImport_(const CoreConfig& config) {
g_core = new CoreFeatureSet(config);
g_core->PostInit_();
// Slightly hacky: have to report our begin time after the fact since core
// didn't exist before. Can at least add an offset to give an accurate
// time though.
auto seconds_since_actual_start =
static_cast<seconds_t>(CorePlatform::GetCurrentMillisecs()
- start_millisecs)
/ 1000.0;
g_core->LifecycleLog("core import begin", -seconds_since_actual_start);
g_core->LifecycleLog("core import end");
// We can't report core import begin since core didn't exist at that point.
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "core import end");
}
CoreFeatureSet::CoreFeatureSet(CoreConfig config)
@ -308,24 +301,24 @@ auto CoreFeatureSet::SoftImportBase() -> BaseSoftInterface* {
return g_base_soft;
}
void CoreFeatureSet::LifecycleLog(const char* msg, double offset_seconds) {
// Early out to avoid work if we won't show anyway.
if (!LogLevelEnabled(LogName::kBaLifecycle, LogLevel::kDebug)) {
return;
}
// void CoreFeatureSet::LifecycleLog(const char* msg, double offset_seconds) {
// // Early out to avoid work if we won't show anyway.
// if (!LogLevelEnabled(LogName::kBaLifecycle, LogLevel::kDebug)) {
// return;
// }
// We're now showing relative timestamps in more places so trying without
// adding that to the message...
if (explicit_bool(false)) {
// We include time-since-start as part of the message here.
char buffer[128];
snprintf(buffer, sizeof(buffer), "%s @ %.3fs.", msg,
g_core->GetAppTimeSeconds() + offset_seconds);
Log(LogName::kBaLifecycle, LogLevel::kDebug, buffer);
} else {
Log(LogName::kBaLifecycle, LogLevel::kDebug, msg);
}
}
// // We're now showing relative timestamps in more places so trying without
// // adding that to the message...
// if (explicit_bool(false)) {
// // We include time-since-start as part of the message here.
// char buffer[128];
// snprintf(buffer, sizeof(buffer), "%s @ %.3fs.", msg,
// g_core->GetAppTimeSeconds() + offset_seconds);
// Log(LogName::kBaLifecycle, LogLevel::kDebug, buffer);
// } else {
// Log(LogName::kBaLifecycle, LogLevel::kDebug, msg);
// }
// }
void CoreFeatureSet::Log(LogName name, LogLevel level, char* msg) {
// Avoid touching the Python layer if the log will get ignored there

View File

@ -97,7 +97,7 @@ class CoreFeatureSet {
}
/// Log a boot-related message (only if core_config.lifecycle_log is true).
void LifecycleLog(const char* msg, double offset_seconds = 0.0);
// void LifecycleLog(const char* msg, double offset_seconds = 0.0);
/// Base path of build src dir so we can attempt to remove it from any
/// source file paths we print.

View File

@ -187,6 +187,8 @@ void CorePython::EnablePythonLoggingCalls() {
assert(objs().Exists(ObjID::kLoggerRootLogCall));
assert(objs().Exists(ObjID::kLoggerBa));
assert(objs().Exists(ObjID::kLoggerBaLogCall));
assert(objs().Exists(ObjID::kLoggerBaApp));
assert(objs().Exists(ObjID::kLoggerBaAppLogCall));
assert(objs().Exists(ObjID::kLoggerBaAudio));
assert(objs().Exists(ObjID::kLoggerBaAudioLogCall));
assert(objs().Exists(ObjID::kLoggerBaDisplayTime));
@ -260,6 +262,7 @@ void CorePython::UpdateInternalLoggerLevels(LogLevel* log_levels) {
std::pair<LogName, ObjID> pairs[] = {
{LogName::kRoot, ObjID::kLoggerRoot},
{LogName::kBa, ObjID::kLoggerBa},
{LogName::kBaApp, ObjID::kLoggerBaApp},
{LogName::kBaAudio, ObjID::kLoggerBaAudio},
{LogName::kBaGraphics, ObjID::kLoggerBaGraphics},
{LogName::kBaDisplayTime, ObjID::kLoggerBaDisplayTime},
@ -331,7 +334,8 @@ void CorePython::VerifyPythonEnvironment() {
void CorePython::MonolithicModeBaEnvConfigure() {
assert(g_buildconfig.monolithic_build());
assert(g_core);
g_core->LifecycleLog("baenv.configure() begin");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo,
"baenv.configure() begin");
auto gil{Python::ScopedInterpreterLock()};
@ -389,7 +393,7 @@ void CorePython::MonolithicModeBaEnvConfigure() {
if (result.ValueIsString()) {
FatalError("Environment setup failed:\n" + result.ValueAsString());
}
g_core->LifecycleLog("baenv.configure() end");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "baenv.configure() end");
}
void CorePython::LoggingCall(LogName logname, LogLevel loglevel,
@ -434,6 +438,10 @@ void CorePython::LoggingCall(LogName logname, LogLevel loglevel,
logcallobj = ObjID::kLoggerBaLogCall;
handled = true;
break;
case LogName::kBaApp:
logcallobj = ObjID::kLoggerBaAppLogCall;
handled = true;
break;
case LogName::kBaAudio:
logcallobj = ObjID::kLoggerBaAudioLogCall;
handled = true;

View File

@ -34,6 +34,8 @@ class CorePython {
kLoggerRootLogCall,
kLoggerBa,
kLoggerBaLogCall,
kLoggerBaApp,
kLoggerBaAppLogCall,
kLoggerBaAudio,
kLoggerBaAudioLogCall,
kLoggerBaDisplayTime,

View File

@ -48,7 +48,7 @@ void SceneV1FeatureSet::OnModuleExec(PyObject* module) {
assert(g_core == nullptr);
g_core = core::CoreFeatureSet::Import();
g_core->LifecycleLog("_bascenev1 exec begin");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_bascenev1 exec begin");
// Create our feature-set's C++ front-end.
assert(g_scene_v1 == nullptr);
@ -68,7 +68,7 @@ void SceneV1FeatureSet::OnModuleExec(PyObject* module) {
assert(g_base == nullptr);
g_base = base::BaseFeatureSet::Import();
g_core->LifecycleLog("_bascenev1 exec end");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_bascenev1 exec end");
}
SceneV1FeatureSet::SceneV1FeatureSet() : python{new SceneV1Python()} {

View File

@ -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 = 22105;
const int kEngineBuildNumber = 22106;
const char* kEngineVersion = "1.7.37";
const int kEngineApiVersion = 9;

View File

@ -287,6 +287,7 @@ enum class PyExcType : uint8_t {
enum class LogName : uint8_t {
kRoot,
kBa,
kBaApp,
kBaDisplayTime,
kBaLifecycle,
kBaAudio,

View File

@ -32,7 +32,7 @@ void UIV1FeatureSet::OnModuleExec(PyObject* module) {
// Various ballistica functionality will fail if this has not been done.
g_core = core::CoreFeatureSet::Import();
g_core->LifecycleLog("_bauiv1 exec begin");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_bauiv1 exec begin");
// Create our feature-set's C++ front-end.
assert(g_ui_v1 == nullptr);
@ -52,7 +52,7 @@ void UIV1FeatureSet::OnModuleExec(PyObject* module) {
assert(g_base == nullptr); // Should be getting set once here.
g_base = base::BaseFeatureSet::Import();
g_core->LifecycleLog("_bauiv1 exec end");
g_core->Log(LogName::kBaLifecycle, LogLevel::kInfo, "_bauiv1 exec end");
}
auto UIV1FeatureSet::Import() -> UIV1FeatureSet* {

View File

@ -27,6 +27,8 @@ values = [
logging.getLogger('root').log, # kLoggerRootLogCall
logging.getLogger('ba'), # kLoggerBa
logging.getLogger('ba').log, # kLoggerBaLogCall
logging.getLogger('ba.app'), # kLoggerBaApp
logging.getLogger('ba.app').log, # kLoggerBaAppLogCall
logging.getLogger('ba.audio'), # kLoggerBaAudio
logging.getLogger('ba.audio').log, # kLoggerBaAudioLogCall
logging.getLogger('ba.displaytime'), # kLoggerBaDisplayTime

View File

@ -325,12 +325,14 @@ class BSPrivatePartyResponse(Response):
datacode: Annotated[str | None, IOAttrs('d')]
# MOVE THIS
class CloudSubscriptionRequestTypeID(Enum):
"""Type ID for each of our subclasses."""
TEST = 'test'
# MOVE THIS
class CloudSubscriptionRequest(IOMultiType[CloudSubscriptionRequestTypeID]):
"""Top level class for our multitype."""
@ -360,6 +362,7 @@ class CloudSubscriptionRequest(IOMultiType[CloudSubscriptionRequestTypeID]):
return out
# MOVE THIS
@ioprepped
@dataclass
class TestCloudSubscriptionRequest(CloudSubscriptionRequest):
@ -371,14 +374,16 @@ class TestCloudSubscriptionRequest(CloudSubscriptionRequest):
return CloudSubscriptionRequestTypeID.TEST
# MOVE THIS
class CloudSubscriptionValueTypeID(Enum):
"""Type ID for each of our subclasses."""
TEST = 'test'
# MOVE THIS
class CloudSubscriptionValue(IOMultiType[CloudSubscriptionValueTypeID]):
"""Top level class for our multitype."""
"""Top level class for subscription values."""
@override
@classmethod

View File

@ -20,8 +20,8 @@ def get_base_logger_control_config_client() -> LoggerControlConfig:
"""
# By default, go with WARNING on everything to keep things mostly
# clean but show INFO for ba.lifecycle to get basic app
# startup/shutdown messages.
# clean but show INFO for ba.app to get basic app startup messages
# and whatnot.
return LoggerControlConfig(
levels={'root': logging.WARNING, 'ba.lifecycle': logging.INFO}
levels={'root': logging.WARNING, 'ba.app': logging.INFO}
)

View File

@ -251,6 +251,11 @@ def is_asyncio_streams_communication_error(exc: BaseException) -> bool:
if 'SSL: WRONG_VERSION_NUMBER' in excstr:
return True
# Also getting this sometimes which sounds like corrupt SSL data
# or something.
if 'SSL: BAD_RECORD_TYPE' in excstr:
return True
# And seeing this very rarely; assuming its just data corruption?
if 'SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC' in excstr:
return True

View File

@ -169,21 +169,26 @@ def data_size_str(bytecount: int, compact: bool = False) -> str:
class DirtyBit:
"""Manages whether a thing is dirty and regulates attempts to clean it.
"""Manages whether a thing is dirty and regulates cleaning it.
To use, simply set the 'dirty' value on this object to True when
some update is needed, and then check the 'should_update' value to
regulate when the actual update should occur. Set 'dirty' back to
False after a successful update.
If 'use_lock' is True, an asyncio Lock will be created and
incorporated into update attempts to prevent simultaneous updates
(should_update will only return True when the lock is unlocked).
Note that It is up to the user to lock/unlock the lock during the
actual update attempt.
If a value is passed for 'auto_dirty_seconds', the dirtybit will
flip itself back to dirty after being clean for the given amount of
time.
To use, simply set the 'dirty' value on this object to True when some
action is needed, and then check the 'should_update' value to regulate
when attempts to clean it should be made. Set 'dirty' back to False after
a successful update.
If 'use_lock' is True, an asyncio Lock will be created and incorporated
into update attempts to prevent simultaneous updates (should_update will
only return True when the lock is unlocked). Note that It is up to the user
to lock/unlock the lock during the actual update attempt.
If a value is passed for 'auto_dirty_seconds', the dirtybit will flip
itself back to dirty after being clean for the given amount of time.
'min_update_interval' can be used to enforce a minimum update
interval even when updates are successful (retry_interval only applies
when updates fail)
interval even when updates are successful (retry_interval only
applies when updates fail)
"""
def __init__(