langs and async task support improvements

This commit is contained in:
Eric 2024-01-16 12:30:39 -08:00
parent f11d4ac261
commit 7182a29c03
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
12 changed files with 177 additions and 94 deletions

98
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "bb60812044af0a8d1bdefee759ff2522", "build/assets/ba_data/data/langdata.json": "29a60e77c26b1f397617f8d8c8d652f9",
"build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88", "build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88",
"build/assets/ba_data/data/languages/belarussian.json": "a112dfca3e188387516788bd8229c5b0", "build/assets/ba_data/data/languages/belarussian.json": "a112dfca3e188387516788bd8229c5b0",
"build/assets/ba_data/data/languages/chinese.json": "93f3ca9f90d86dc7c8d0923f5f11ef46", "build/assets/ba_data/data/languages/chinese.json": "93f3ca9f90d86dc7c8d0923f5f11ef46",
@ -429,23 +429,23 @@
"build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa",
"build/assets/ba_data/data/languages/czech.json": "c9d518a324870066b987b8f412881dd3", "build/assets/ba_data/data/languages/czech.json": "c9d518a324870066b987b8f412881dd3",
"build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e",
"build/assets/ba_data/data/languages/dutch.json": "5cbf1a68a9d93dee00dbc27f834d878a", "build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343",
"build/assets/ba_data/data/languages/english.json": "1c4037fea1066d39d6eced419f314f35", "build/assets/ba_data/data/languages/english.json": "1c4037fea1066d39d6eced419f314f35",
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
"build/assets/ba_data/data/languages/filipino.json": "0031cbb8eb6a638a94fb43c5d892346c", "build/assets/ba_data/data/languages/filipino.json": "0031cbb8eb6a638a94fb43c5d892346c",
"build/assets/ba_data/data/languages/french.json": "8bc35eb4b20a0b30c3348bcc9a3844a6", "build/assets/ba_data/data/languages/french.json": "cc8ac601f5443dd539893728db983f5c",
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
"build/assets/ba_data/data/languages/gibberish.json": "b461539243e8efe3137137b886256ba7", "build/assets/ba_data/data/languages/gibberish.json": "b461539243e8efe3137137b886256ba7",
"build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3",
"build/assets/ba_data/data/languages/hindi.json": "8848f6b0caec0fcf9d85bc6e683809ec", "build/assets/ba_data/data/languages/hindi.json": "8848f6b0caec0fcf9d85bc6e683809ec",
"build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e",
"build/assets/ba_data/data/languages/indonesian.json": "408fb026e84c24a8dd7a43cb2b794541", "build/assets/ba_data/data/languages/indonesian.json": "9103845242b572aa8ba48e24f81ddb68",
"build/assets/ba_data/data/languages/italian.json": "f550810b6866ea9bcf1985b7228f8cff", "build/assets/ba_data/data/languages/italian.json": "f550810b6866ea9bcf1985b7228f8cff",
"build/assets/ba_data/data/languages/korean.json": "03fd99d5e1155e81053fc028f69df982", "build/assets/ba_data/data/languages/korean.json": "03fd99d5e1155e81053fc028f69df982",
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
"build/assets/ba_data/data/languages/persian.json": "9728d631cf7d9ad3b209ae1244bb59c0", "build/assets/ba_data/data/languages/persian.json": "9728d631cf7d9ad3b209ae1244bb59c0",
"build/assets/ba_data/data/languages/polish.json": "3a90b2d9e2c59305580c96f8098fc839", "build/assets/ba_data/data/languages/polish.json": "3a90b2d9e2c59305580c96f8098fc839",
"build/assets/ba_data/data/languages/portuguese.json": "0274cb9a4b7d2bd49c8eb8120144a1bf", "build/assets/ba_data/data/languages/portuguese.json": "b52164747c6308fc9d054eb6c0ff3c54",
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826", "build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
"build/assets/ba_data/data/languages/russian.json": "30d5f3d2415088e1fb6558fcd6ccfa98", "build/assets/ba_data/data/languages/russian.json": "30d5f3d2415088e1fb6558fcd6ccfa98",
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
@ -4060,50 +4060,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "cd19dfdf480de6e73949db674e1b02d2", "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c1f5b6a9fe5aee5baab40248a00eb606",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "8c08cdda59e731a3830624000de5ca7f", "build/prefab/full/linux_arm64_gui/release/ballisticakit": "88888a9139b8a047d1dde25ae0aa9ea6",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "14685eca62b8540cc2a268883d0ebc5d", "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "e51014b672283258ba29f546f3a8833e",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "f81876d7827a10be412306c52b03fa08", "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "811973441c2d7998445182b2ab4bcc24",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "b8370845743ebba86ed6eaa6ee1d79d5", "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "01e0fe6152b79211acec7e88a99c6579",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "cdf04825dedae8fb2c26502ec2a505db", "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "9e2b7acbcd3892af6be5f85bfe328c2c",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "4036493f98646b58de8bf425bee227cb", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2f54025a53bb947c89eee520131eae52",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1cf36c63f68ecaa954fb9c48a132725e", "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "b9df392dca06e52b958ea3c9b676ae6a",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b757a940c5157197a0138e12e308f859", "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f2ed10e0b5956ce8ef5b87c3e0c75eea",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "92a07f83fceeddf3b29cfe2ead57f7e3", "build/prefab/full/mac_arm64_gui/release/ballisticakit": "e1c27e7ecb5272f92e6cfdb91b0750d3",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "90002c085c66be4af378d4b3fc8e0260", "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "67827bd210a484f7d93974b581b95a85",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "eeb363d0d48e68f5f2ac2e536a26aeeb", "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "c03d44f4096cbffe0d1b3391a7b09555",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "e119b480fc7e542f33ceb16e8c04585f", "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "a78c8b08a19dc23d1881eee37fdbcfdd",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "6e657aa09d052765ed891789ec60dfb2", "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "ca2caba96a855ac6fa7459855bfa49bb",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "2d4eab8ea8399defd1afdbe548216e9c", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9521bca3d6dc02e896fa01ab0ccdfd0c",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "b03bb9d5d1eb695a11843f64f24906ef", "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "31762c816772ba2c0516c26589428c08",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "163fbc40b479ef1db1c753f7beb73c0f", "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ab72b100f5c1eaaac6264b8f662fabb7",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "37291abd76871f4556348f77e12dd363", "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "edf145cc7855aced80f60766a9420df5",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "acca6904f2f2f952ecae99922c602b9d", "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "4d4e6e57f179666e8f5a50352b9cda9b",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "3c2dfd9cf26e77a0b803ed43c85df113", "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "20babca2eb9cc062f583ecea557a945e",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "3af5cf00e5eb30d55030e8705b83353a", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "8ccecbffbaa9886636741cca293d2893",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "be337c05f72235b5b486277bb1a9c259", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "42679aef4dd8b35b39a2c968ff20ed45",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "3af5cf00e5eb30d55030e8705b83353a", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "8ccecbffbaa9886636741cca293d2893",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "be337c05f72235b5b486277bb1a9c259", "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "42679aef4dd8b35b39a2c968ff20ed45",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "17c7d0041bc7c84077bf6692b16e3988", "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "b2c2c33149201227ba96459dbeeba012",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "4affbfea91e8a33ab62da763ffc07ddd", "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "2b27b84fe8305b7f3829aa28ab5e5705",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "17c7d0041bc7c84077bf6692b16e3988", "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "b2c2c33149201227ba96459dbeeba012",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "4affbfea91e8a33ab62da763ffc07ddd", "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "2b27b84fe8305b7f3829aa28ab5e5705",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "58656b49d34e6c650983fbf79b5c41ae", "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "f6b49cee7baf1ee49598b803566d9914",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "3ce5652e0ff5d277e256f517dec4eb61", "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "a15dc59a2de8a8d32b32f07fe25d41b1",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "58656b49d34e6c650983fbf79b5c41ae", "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "f6b49cee7baf1ee49598b803566d9914",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "3ce5652e0ff5d277e256f517dec4eb61", "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "a15dc59a2de8a8d32b32f07fe25d41b1",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "b94fff3a719003c1d8f5dd16dffdb3fc", "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "80fd9070d92797ff6e26c0a5493dcb42",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "5d68e1957febe6053815bbee3f068e76", "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "07c2b1098c1c08d2e28934a6f0e1fcf2",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "85bbca447ca8a1d0fad984afc6f0700a", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "724d8dcd34fb6c2c0109906d44a4fb12",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "5d68e1957febe6053815bbee3f068e76", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "07c2b1098c1c08d2e28934a6f0e1fcf2",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "7f2ed141a475e051d3350d571ef6cb0c", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "698b55a6c11f38e5c28587a7039e6175",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "93fb764531ae16a30d4886eb183c3681", "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "753db5761ce823966fcef472b73e06d1",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "750cd7ef428f4faf65ccbeff50c21f8e", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "b1e41720089a0d7724337071442238c9",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "104cf85df9f1f7ffbf4de5997f7c6879", "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "37d3e9fa31a003dd9609f476d4165d12",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "af85fb387d755b152c42f8dfb0891ad7", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "105f4dc0399235e4a9c25c3977febec8",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "01ce8e0619b342e4cc2cc5f18f81a727", "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "820c04dd9965698a86e4f5efffdb729d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "f8aae2e04f95f4cfb863791da36ff931", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "070727ad10a727b22beef6ee736c7a5f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "66252d58a1be97db8523bd0bf8098a16", "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "6d2969401a8a022e28f4680b01004a50",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.33 (build 21757, api 8, 2024-01-06) ### 1.7.33 (build 21760, api 8, 2024-01-16)
- Stress test input-devices are now a bit smarter; they won't press any buttons - Stress test input-devices are now a bit smarter; they won't press any buttons
while UIs are up (this could cause lots of chaos if it happened). while UIs are up (this could cause lots of chaos if it happened).
- Added a 'Show Demos When Idle' option in advanced settings. If enabled, the - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the

View File

@ -49,9 +49,6 @@
<file path="$PROJECT_DIR$/../src/external/python-android-debug" /> <file path="$PROJECT_DIR$/../src/external/python-android-debug" />
<file path="$PROJECT_DIR$/../src/external/python-apple" /> <file path="$PROJECT_DIR$/../src/external/python-apple" />
<file path="$PROJECT_DIR$/../src/external/python-apple-debug" /> <file path="$PROJECT_DIR$/../src/external/python-apple-debug" />
<file path="$PROJECT_DIR$/../src/external/sdl-1.2.14_ef" />
<file path="$PROJECT_DIR$/../src/external/sdl2-ef_android" />
<file path="$PROJECT_DIR$/../src/external/sdl2-ef_ios" />
<file path="$PROJECT_DIR$/../src/external/tremor" /> <file path="$PROJECT_DIR$/../src/external/tremor" />
<file path="$PROJECT_DIR$/../src/external/windows" /> <file path="$PROJECT_DIR$/../src/external/windows" />
<file path="$PROJECT_DIR$/../src/meta" /> <file path="$PROJECT_DIR$/../src/meta" />

View File

@ -1,12 +1,13 @@
# Released under the MIT License. See LICENSE for details. # Released under the MIT License. See LICENSE for details.
# #
# pylint: disable=too-many-lines
"""Functionality related to the high level state of the app.""" """Functionality related to the high level state of the app."""
from __future__ import annotations from __future__ import annotations
import os import os
import logging import logging
from enum import Enum from enum import Enum
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, TypeVar
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from functools import cached_property from functools import cached_property
@ -26,7 +27,7 @@ from babase._devconsole import DevConsoleSubsystem
if TYPE_CHECKING: if TYPE_CHECKING:
import asyncio import asyncio
from typing import Any, Callable, Coroutine from typing import Any, Callable, Coroutine, Generator, Awaitable
from concurrent.futures import Future from concurrent.futures import Future
import babase import babase
@ -42,6 +43,8 @@ if TYPE_CHECKING:
# __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__ # __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__
T = TypeVar('T')
class App: class App:
"""A class for high level app functionality and state. """A class for high level app functionality and state.
@ -199,7 +202,8 @@ class App:
self._called_on_running = False self._called_on_running = False
self._subsystem_registration_ended = False self._subsystem_registration_ended = False
self._pending_apply_app_config = False self._pending_apply_app_config = False
self._aioloop: asyncio.AbstractEventLoop | None = None self._asyncio_loop: asyncio.AbstractEventLoop | None = None
self._asyncio_tasks: set[asyncio.Task] = set()
self._asyncio_timer: babase.AppTimer | None = None self._asyncio_timer: babase.AppTimer | None = None
self._config: babase.AppConfig | None = None self._config: babase.AppConfig | None = None
self._pending_intent: AppIntent | None = None self._pending_intent: AppIntent | None = None
@ -239,18 +243,68 @@ class App:
return _babase.app_is_active() return _babase.app_is_active()
@property @property
def aioloop(self) -> asyncio.AbstractEventLoop: def asyncio_loop(self) -> asyncio.AbstractEventLoop:
"""The logic thread's asyncio event loop. """The logic thread's asyncio event loop.
This allow async tasks to be run in the logic thread. This allow async tasks to be run in the logic thread.
Generally you should call App.create_async_task() to schedule
async code to run instead of using this directly. That will
handle retaining the task and logging errors automatically.
Only schedule tasks onto asyncio_loop yourself when you intend
to hold on to the returned task and await its results. Releasing
the task reference can lead to subtle bugs such as unreported
errors and garbage-collected tasks disappearing before their
work is done.
Note that, at this time, the asyncio loop is encapsulated Note that, at this time, the asyncio loop is encapsulated
and explicitly stepped by the engine's logic thread loop and and explicitly stepped by the engine's logic thread loop and
thus things like asyncio.get_running_loop() will not return this thus things like asyncio.get_running_loop() will unintuitively
loop from most places in the logic thread; only from within a *not* return this loop from most places in the logic thread;
task explicitly created in this loop. only from within a task explicitly created in this loop.
Hopefully this situation will be improved in the future with a
unified event loop.
""" """
assert self._aioloop is not None assert _babase.in_logic_thread()
return self._aioloop assert self._asyncio_loop is not None
return self._asyncio_loop
def create_async_task(
self,
coro: Generator[Any, Any, T] | Coroutine[Any, Any, T],
*,
name: str | None = None,
) -> None:
"""Create a fully managed async task.
This will automatically retain and release a reference to the task
and log any exceptions that occur in it. If you need to await a task
or otherwise need more control, schedule a task directly using
App.asyncio_loop.
"""
assert _babase.in_logic_thread()
# Hold a strong reference to the task until it is done.
# Otherwise it is possible for it to be garbage collected and
# disappear midway if the caller does not hold on to the
# returned task, which seems like a great way to introduce
# hard-to-track bugs.
task = self.asyncio_loop.create_task(coro, name=name)
self._asyncio_tasks.add(task)
task.add_done_callback(self._on_task_done)
# return task
def _on_task_done(self, task: asyncio.Task) -> None:
# Report any errors that occurred.
try:
exc = task.exception()
if exc is not None:
logging.error(
"Error in async task '%s'.", task.get_name(), exc_info=exc
)
except Exception:
logging.exception('Error reporting async task error.')
self._asyncio_tasks.remove(task)
@property @property
def config(self) -> babase.AppConfig: def config(self) -> babase.AppConfig:
@ -594,7 +648,7 @@ class App:
_env.on_app_state_initing() _env.on_app_state_initing()
self._aioloop = _asyncio.setup_asyncio() self._asyncio_loop = _asyncio.setup_asyncio()
self.health_monitor = AppHealthMonitor() self.health_monitor = AppHealthMonitor()
# __FEATURESET_APP_SUBSYSTEM_CREATE_BEGIN__ # __FEATURESET_APP_SUBSYSTEM_CREATE_BEGIN__
@ -874,8 +928,8 @@ class App:
) )
# Now kick off any async shutdown task(s). # Now kick off any async shutdown task(s).
assert self._aioloop is not None assert self._asyncio_loop is not None
self._shutdown_task = self._aioloop.create_task(self._shutdown()) self._shutdown_task = self._asyncio_loop.create_task(self._shutdown())
def _on_shutdown_complete(self) -> None: def _on_shutdown_complete(self) -> None:
"""(internal)""" """(internal)"""

View File

@ -229,9 +229,7 @@ class AdsSubsystem:
await asyncio.sleep(1.0) await asyncio.sleep(1.0)
payload.run(fallback=True) payload.run(fallback=True)
_fallback_task = babase.app.aioloop.create_task( babase.app.create_async_task(add_fallback_task())
add_fallback_task()
)
self.show_ad('between_game', on_completion_call=payload.run) self.show_ad('between_game', on_completion_call=payload.run)
else: else:
babase.pushcall(call) # Just run the callback without the ad. babase.pushcall(call) # Just run the callback without the ad.

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be # Build number and version of the ballistica binary we expect to be
# using. # using.
TARGET_BALLISTICA_BUILD = 21757 TARGET_BALLISTICA_BUILD = 21760
TARGET_BALLISTICA_VERSION = '1.7.33' TARGET_BALLISTICA_VERSION = '1.7.33'

View File

@ -5,9 +5,13 @@
from __future__ import annotations from __future__ import annotations
import time import time
from typing import TYPE_CHECKING
import bauiv1 as bui import bauiv1 as bui
if TYPE_CHECKING:
from typing import Any
class PromoCodeWindow(bui.Window): class PromoCodeWindow(bui.Window):
"""Window for entering promo codes.""" """Window for entering promo codes."""
@ -167,9 +171,6 @@ class PromoCodeWindow(bui.Window):
if not self._root_widget or self._root_widget.transitioning_out: if not self._root_widget or self._root_widget.transitioning_out:
return return
plus = bui.app.plus
assert plus is not None
bui.containerwidget( bui.containerwidget(
edit=self._root_widget, transition=self._transition_out edit=self._root_widget, transition=self._transition_out
) )
@ -179,11 +180,22 @@ class PromoCodeWindow(bui.Window):
AdvancedSettingsWindow(transition='in_left').get_root_widget(), AdvancedSettingsWindow(transition='in_left').get_root_widget(),
from_window=self._root_widget, from_window=self._root_widget,
) )
plus.add_v1_account_transaction(
{ code: Any = bui.textwidget(query=self._text_field)
'type': 'PROMO_CODE', assert isinstance(code, str)
'expire_time': time.time() + 5,
'code': bui.textwidget(query=self._text_field), bui.app.create_async_task(_run_code(code))
}
)
plus.run_v1_account_transactions() async def _run_code(code: str) -> None:
plus = bui.app.plus
assert plus is not None
plus.add_v1_account_transaction(
{
'type': 'PROMO_CODE',
'expire_time': time.time() + 5,
'code': code,
}
)
plus.run_v1_account_transactions()

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21757; const int kEngineBuildNumber = 21760;
const char* kEngineVersion = "1.7.33"; const char* kEngineVersion = "1.7.33";
const int kEngineApiVersion = 8; const int kEngineApiVersion = 8;

View File

@ -31,7 +31,7 @@ class DirectoryManifest:
files: Annotated[dict[str, DirectoryManifestFile], IOAttrs('f')] files: Annotated[dict[str, DirectoryManifestFile], IOAttrs('f')]
_empty_hash: str | None = None # _empty_hash: str | None = None
@classmethod @classmethod
def create_from_disk(cls, path: Path) -> DirectoryManifest: def create_from_disk(cls, path: Path) -> DirectoryManifest:
@ -92,12 +92,12 @@ class DirectoryManifest:
) )
break # 1 error is enough for now. break # 1 error is enough for now.
@classmethod # @classmethod
def get_empty_hash(cls) -> str: # def get_empty_hash(cls) -> str:
"""Return the hash for an empty file.""" # """Return the hash for an empty file."""
if cls._empty_hash is None: # if cls._empty_hash is None:
import hashlib # import hashlib
sha = hashlib.sha256() # sha = hashlib.sha256()
cls._empty_hash = sha.hexdigest() # cls._empty_hash = sha.hexdigest()
return cls._empty_hash # return cls._empty_hash

View File

@ -70,6 +70,13 @@ class IOExtendedData:
Can be overridden to migrate old data formats to new, etc. Can be overridden to migrate old data formats to new, etc.
""" """
def did_input(self) -> None:
"""Called on a class instance after created from data.
Can be useful to correct values from the db, etc. in the
type-safe form.
"""
def _is_valid_for_codec(obj: Any, codec: Codec) -> bool: def _is_valid_for_codec(obj: Any, codec: Codec) -> bool:
"""Return whether a value consists solely of json-supported types. """Return whether a value consists solely of json-supported types.

View File

@ -64,11 +64,23 @@ class _Inputter(Generic[T]):
# For special extended data types, call their 'will_output' callback. # For special extended data types, call their 'will_output' callback.
tcls = self._cls tcls = self._cls
if issubclass(tcls, IOExtendedData): if issubclass(tcls, IOExtendedData):
is_ext = True
tcls.will_input(values) tcls.will_input(values)
else:
is_ext = False
out = self._dataclass_from_input(self._cls, '', values) out = self._dataclass_from_input(self._cls, '', values)
assert isinstance(out, self._cls) assert isinstance(out, self._cls)
if is_ext:
# mypy complains that we're no longer returning a T
# if we operate on out directly.
out2 = out
assert isinstance(out2, IOExtendedData)
out2.did_input()
return out return out
def _value_from_input( def _value_from_input(

View File

@ -174,17 +174,20 @@ def empty_weakref(objtype: type[T]) -> weakref.ref[T]:
# Just create an object and let it die. Is there a cleaner way to do this? # Just create an object and let it die. Is there a cleaner way to do this?
# return weakref.ref(_EmptyObj()) # type: ignore # return weakref.ref(_EmptyObj()) # type: ignore
# Sharing a single ones seems at least a bit better.
return _g_empty_weak_ref # type: ignore return _g_empty_weak_ref # type: ignore
def data_size_str(bytecount: int) -> str: def data_size_str(bytecount: int, compact: bool = False) -> str:
"""Given a size in bytes, returns a short human readable string. """Given a size in bytes, returns a short human readable string.
This should be 6 or fewer chars for most all sane file sizes. In compact mode this should be 6 or fewer chars for most all
sane file sizes.
""" """
# pylint: disable=too-many-return-statements # pylint: disable=too-many-return-statements
if bytecount <= 999: if bytecount <= 999:
return f'{bytecount} B' suffix = 'B' if compact else 'bytes'
return f'{bytecount} {suffix}'
kbytecount = bytecount / 1024 kbytecount = bytecount / 1024
if round(kbytecount, 1) < 10.0: if round(kbytecount, 1) < 10.0:
return f'{kbytecount:.1f} KB' return f'{kbytecount:.1f} KB'
@ -623,7 +626,7 @@ def check_non_optional(obj: T | None) -> T:
Use assert_non_optional for a more efficient (but less safe) equivalent. Use assert_non_optional for a more efficient (but less safe) equivalent.
""" """
if obj is None: if obj is None:
raise TypeError('Got None value in check_non_optional.') raise ValueError('Got None value in check_non_optional.')
return obj return obj