subsystems cleanup

This commit is contained in:
Eric 2023-06-26 13:16:38 -07:00
parent 1e6b59d586
commit c13b937c79
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
22 changed files with 339 additions and 280 deletions

150
.efrocachemap generated
View File

@ -421,7 +421,7 @@
"build/assets/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/74/be/fe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/48/ab/8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/2b/46/8aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/cf/c0/8614c5b5ccbd2d26d77a09726eb6",
"build/assets/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/3c/43/4b7614cd5d9db1c57a77a64271f6",
"build/assets/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/83/87/06fc7255ebf8a895ad37d2dfa13d",
"build/assets/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/57/68/d03a19b9035cfae7cdc5377d889a",
"build/assets/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/25/f1/d88c72fbeeb121340244bc935df4",
@ -946,11 +946,11 @@
"build/assets/ba_data/meshes/zoeUpperArm.bob": "https://files.ballistica.net/cache/ba1/a8/a8/81010ac1ee9ec5ca872d5c5e853a",
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "https://files.ballistica.net/cache/ba1/95/b2/502f74c70f934927f67cd505c3ad",
"build/assets/ba_data/python-site-packages/_yaml/__init__.py": "https://files.ballistica.net/cache/ba1/b0/9d/1968d73a04d6cf20e4e79657a6e7",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "https://files.ballistica.net/cache/ba1/00/29/e4b90bb9e91a381dcd3992ed5b8d",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "https://files.ballistica.net/cache/ba1/63/37/efa17f5b457b793332df33904162",
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "https://files.ballistica.net/cache/ba1/ef/02/e73f8581609df189a9f61aca365b",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/5a/0e/670d05eeca037e593b8c2bf6bff4",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "https://files.ballistica.net/cache/ba1/6a/c2/9a6bccca11cd2ed7e16e27dfccec",
"build/assets/ba_data/python-site-packages/certifi/core.py": "https://files.ballistica.net/cache/ba1/1b/50/5388f1475fabd1b60031f985271c",
"build/assets/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/6f/99/83cb2f859c5d1680af80aa15716b",
"build/assets/ba_data/python-site-packages/typing_extensions.py": "https://files.ballistica.net/cache/ba1/11/61/88cec81052958f4f98239d4bf3ca",
"build/assets/ba_data/python-site-packages/yaml/__init__.py": "https://files.ballistica.net/cache/ba1/55/7c/37ea8dbd4fa4d6dac97f399b6fdd",
"build/assets/ba_data/python-site-packages/yaml/composer.py": "https://files.ballistica.net/cache/ba1/ce/f8/71e1f5f99ba2a7c44941b70afb06",
"build/assets/ba_data/python-site-packages/yaml/constructor.py": "https://files.ballistica.net/cache/ba1/8a/15/e361e34b79491c81553bb3534062",
@ -2598,20 +2598,20 @@
"build/assets/pylib-android/_pyio.py": "https://files.ballistica.net/cache/ba1/a6/e8/8d66fbca88b13213cdd2177390b8",
"build/assets/pylib-android/_sitebuiltins.py": "https://files.ballistica.net/cache/ba1/8b/5e/3f6e73917962fa014ad2c4a55e61",
"build/assets/pylib-android/_strptime.py": "https://files.ballistica.net/cache/ba1/ff/69/9c3f7647db7621bb88c43cc282d3",
"build/assets/pylib-android/_sysconfigdata__linux_aarch64-linux-android.py": "https://files.ballistica.net/cache/ba1/aa/10/553aeca80a3710aa8f89f7fc3ac1",
"build/assets/pylib-android/_sysconfigdata__linux_arm-linux-androideabi.py": "https://files.ballistica.net/cache/ba1/ad/f1/41818ec9b47e366cd72361921dbc",
"build/assets/pylib-android/_sysconfigdata__linux_i686-linux-android.py": "https://files.ballistica.net/cache/ba1/c2/5c/b3bfba5ffbaadf288ea860d400a5",
"build/assets/pylib-android/_sysconfigdata__linux_x86_64-linux-android.py": "https://files.ballistica.net/cache/ba1/5b/ee/5962b42890b6758cea433e67376d",
"build/assets/pylib-android/_sysconfigdata_d_linux_aarch64-linux-android.py": "https://files.ballistica.net/cache/ba1/7b/ee/c8b9c2e67865226a6a1fbe5d244f",
"build/assets/pylib-android/_sysconfigdata_d_linux_arm-linux-androideabi.py": "https://files.ballistica.net/cache/ba1/37/a5/4b085a7f6cdfa03b3c6c887979ba",
"build/assets/pylib-android/_sysconfigdata_d_linux_i686-linux-android.py": "https://files.ballistica.net/cache/ba1/6f/ec/8a10cf682d5bf05bb6a7ab811d08",
"build/assets/pylib-android/_sysconfigdata_d_linux_x86_64-linux-android.py": "https://files.ballistica.net/cache/ba1/81/1d/8202416f4ba308e6a011139115e6",
"build/assets/pylib-android/_sysconfigdata__linux_aarch64-linux-android.py": "https://files.ballistica.net/cache/ba1/3d/04/00e723f4dad156512d4229270993",
"build/assets/pylib-android/_sysconfigdata__linux_arm-linux-androideabi.py": "https://files.ballistica.net/cache/ba1/50/6b/3106270f7f7ae33e195d1f5caa55",
"build/assets/pylib-android/_sysconfigdata__linux_i686-linux-android.py": "https://files.ballistica.net/cache/ba1/f3/8a/2b60f9cbf0524885e5c1c99164c1",
"build/assets/pylib-android/_sysconfigdata__linux_x86_64-linux-android.py": "https://files.ballistica.net/cache/ba1/d6/7f/056bcaf3d491d68254c206067d19",
"build/assets/pylib-android/_sysconfigdata_d_linux_aarch64-linux-android.py": "https://files.ballistica.net/cache/ba1/e4/32/2948686ce1d4b37a1a3f8000e2dc",
"build/assets/pylib-android/_sysconfigdata_d_linux_arm-linux-androideabi.py": "https://files.ballistica.net/cache/ba1/a4/d1/4baa8cfc0019363742349449942b",
"build/assets/pylib-android/_sysconfigdata_d_linux_i686-linux-android.py": "https://files.ballistica.net/cache/ba1/2a/d6/c96209fd69a4eef4a7d730cd16e8",
"build/assets/pylib-android/_sysconfigdata_d_linux_x86_64-linux-android.py": "https://files.ballistica.net/cache/ba1/bf/6c/e8f2788661352014e973351f35cf",
"build/assets/pylib-android/_threading_local.py": "https://files.ballistica.net/cache/ba1/4a/96/88e3987d7d692db46feb9214945e",
"build/assets/pylib-android/_weakrefset.py": "https://files.ballistica.net/cache/ba1/e4/fa/8532ace46dfbc35149c41ea497f7",
"build/assets/pylib-android/abc.py": "https://files.ballistica.net/cache/ba1/a9/66/1fcfe6c12211ec1b16391247947c",
"build/assets/pylib-android/abc.py": "https://files.ballistica.net/cache/ba1/a0/da/a1ed187eee8690c1e8438b97da90",
"build/assets/pylib-android/aifc.py": "https://files.ballistica.net/cache/ba1/1b/91/34c72b1e542417bee5bf345a1d0a",
"build/assets/pylib-android/antigravity.py": "https://files.ballistica.net/cache/ba1/6d/56/bedf73be574cb6d7117caf5d334c",
"build/assets/pylib-android/argparse.py": "https://files.ballistica.net/cache/ba1/2d/c7/f53a0390532cfabb416e25e72035",
"build/assets/pylib-android/argparse.py": "https://files.ballistica.net/cache/ba1/e2/2c/ac9b12c09592929d57eb982fc554",
"build/assets/pylib-android/ast.py": "https://files.ballistica.net/cache/ba1/3a/aa/1b0e56b21b28155707c54bc225a8",
"build/assets/pylib-android/asynchat.py": "https://files.ballistica.net/cache/ba1/2e/f3/a0ce322332fabbf8fad4e133c6a3",
"build/assets/pylib-android/asyncio/__init__.py": "https://files.ballistica.net/cache/ba1/ed/f0/e79e2b8b85c08f09fd14668e4822",
@ -2633,26 +2633,26 @@
"build/assets/pylib-android/asyncio/protocols.py": "https://files.ballistica.net/cache/ba1/b8/aa/105b79d24f88c7a2c2cdbc8e7814",
"build/assets/pylib-android/asyncio/queues.py": "https://files.ballistica.net/cache/ba1/f6/3b/e54780730992e2377c51ac373126",
"build/assets/pylib-android/asyncio/runners.py": "https://files.ballistica.net/cache/ba1/f1/84/754fba961e4ea6e77a9aec633afc",
"build/assets/pylib-android/asyncio/selector_events.py": "https://files.ballistica.net/cache/ba1/f7/ee/7809d8b807ccda22db7870f508ac",
"build/assets/pylib-android/asyncio/sslproto.py": "https://files.ballistica.net/cache/ba1/3a/63/9532c92e12c9bf06fd131a6fc419",
"build/assets/pylib-android/asyncio/selector_events.py": "https://files.ballistica.net/cache/ba1/a1/08/fbd3a49f967da245f39cebf7694e",
"build/assets/pylib-android/asyncio/sslproto.py": "https://files.ballistica.net/cache/ba1/2e/c1/b21e523055147d94c8c634154aab",
"build/assets/pylib-android/asyncio/staggered.py": "https://files.ballistica.net/cache/ba1/f5/05/6f0a56b73b477a9fa65e71145366",
"build/assets/pylib-android/asyncio/streams.py": "https://files.ballistica.net/cache/ba1/e9/c6/09b92b4e9bd3383cf4004c6186c6",
"build/assets/pylib-android/asyncio/subprocess.py": "https://files.ballistica.net/cache/ba1/a5/ff/69004c02e2f47d0077a77803c06b",
"build/assets/pylib-android/asyncio/subprocess.py": "https://files.ballistica.net/cache/ba1/ed/b8/d98278300b6c99f36cd08643c743",
"build/assets/pylib-android/asyncio/taskgroups.py": "https://files.ballistica.net/cache/ba1/51/62/e5b1806d9b647383d34ba1b21b56",
"build/assets/pylib-android/asyncio/tasks.py": "https://files.ballistica.net/cache/ba1/23/45/50593cd4928e6ee2c9591b6928ca",
"build/assets/pylib-android/asyncio/threads.py": "https://files.ballistica.net/cache/ba1/7b/bf/81d424901524510e07b5d20e4a50",
"build/assets/pylib-android/asyncio/timeouts.py": "https://files.ballistica.net/cache/ba1/c7/cb/81c7ee938bc47ff75342befc872a",
"build/assets/pylib-android/asyncio/transports.py": "https://files.ballistica.net/cache/ba1/04/59/8090d813bb363cea9bf714b97c3f",
"build/assets/pylib-android/asyncio/trsock.py": "https://files.ballistica.net/cache/ba1/30/5d/016a93b3e5224cb45af43fdc52b9",
"build/assets/pylib-android/asyncio/unix_events.py": "https://files.ballistica.net/cache/ba1/9c/e0/da3a12b544df9c10fd3b3e0b2f37",
"build/assets/pylib-android/asyncio/unix_events.py": "https://files.ballistica.net/cache/ba1/cb/b9/68f7c1e4f87f23b187d7140839f1",
"build/assets/pylib-android/asyncio/windows_events.py": "https://files.ballistica.net/cache/ba1/95/46/37d8416216d656011178dbcedbb4",
"build/assets/pylib-android/asyncio/windows_utils.py": "https://files.ballistica.net/cache/ba1/4e/fb/ef16e6692c9424804d9bdc496761",
"build/assets/pylib-android/asyncore.py": "https://files.ballistica.net/cache/ba1/af/21/d495fa6ccc47b51ca8a8a382ea1c",
"build/assets/pylib-android/base64.py": "https://files.ballistica.net/cache/ba1/5f/8b/bbfda4b9145b1968cb9badf8325b",
"build/assets/pylib-android/bdb.py": "https://files.ballistica.net/cache/ba1/ae/cf/5370ea25c5decdf8dfa07caf0bfc",
"build/assets/pylib-android/bdb.py": "https://files.ballistica.net/cache/ba1/1e/26/c626405bfc06b1e7231183eb928a",
"build/assets/pylib-android/bisect.py": "https://files.ballistica.net/cache/ba1/9b/70/437e327d5176da41192567ad0064",
"build/assets/pylib-android/bz2.py": "https://files.ballistica.net/cache/ba1/cd/6a/5f2491bc52afd8fc180097371473",
"build/assets/pylib-android/cProfile.py": "https://files.ballistica.net/cache/ba1/d5/ef/924a68c0f747ad727a6326ad8e5a",
"build/assets/pylib-android/cProfile.py": "https://files.ballistica.net/cache/ba1/9e/9c/07ac3b9e4195a62b74e4f2b9489f",
"build/assets/pylib-android/calendar.py": "https://files.ballistica.net/cache/ba1/4e/f3/d6d85d44e36212e5d784051c80b6",
"build/assets/pylib-android/cgi.py": "https://files.ballistica.net/cache/ba1/09/0c/5cfc8b4b92a730beec975159bd2a",
"build/assets/pylib-android/cgitb.py": "https://files.ballistica.net/cache/ba1/2b/cf/f1cec7f3a3a9c96de7a55ebb4ea3",
@ -2691,7 +2691,7 @@
"build/assets/pylib-android/curses/has_key.py": "https://files.ballistica.net/cache/ba1/c7/4b/8d6db329fbbd872b7b91bfa94624",
"build/assets/pylib-android/curses/panel.py": "https://files.ballistica.net/cache/ba1/8f/36/fdade9588f8a4362d2cc057a6eff",
"build/assets/pylib-android/curses/textpad.py": "https://files.ballistica.net/cache/ba1/94/aa/9ebc47a6068d4461652346646dbb",
"build/assets/pylib-android/dataclasses.py": "https://files.ballistica.net/cache/ba1/13/28/e12f8255b856ced026e75a623671",
"build/assets/pylib-android/dataclasses.py": "https://files.ballistica.net/cache/ba1/fe/be/ea138bff21dbed88762be772514e",
"build/assets/pylib-android/datetime.py": "https://files.ballistica.net/cache/ba1/5d/cf/d7f3b1a4db8214c1442164ac999c",
"build/assets/pylib-android/decimal.py": "https://files.ballistica.net/cache/ba1/f5/7d/255d45b5d1d7d8e13c41a283c3e4",
"build/assets/pylib-android/difflib.py": "https://files.ballistica.net/cache/ba1/6b/3c/8fd541b2b8d0320727025cd25275",
@ -2848,7 +2848,7 @@
"build/assets/pylib-android/encodings/utf_8_sig.py": "https://files.ballistica.net/cache/ba1/8f/35/42863ef311d8b970a37c0d66b0de",
"build/assets/pylib-android/encodings/uu_codec.py": "https://files.ballistica.net/cache/ba1/4e/f8/a65413574c017a96b97fc1638ba6",
"build/assets/pylib-android/encodings/zlib_codec.py": "https://files.ballistica.net/cache/ba1/13/88/fb103fdf395451bfc8a2d60933a9",
"build/assets/pylib-android/enum.py": "https://files.ballistica.net/cache/ba1/93/e4/c39acfbbebdc9c4f3d204f17e496",
"build/assets/pylib-android/enum.py": "https://files.ballistica.net/cache/ba1/62/a3/41268ae3fef3c4affc625c2e68d2",
"build/assets/pylib-android/filecmp.py": "https://files.ballistica.net/cache/ba1/76/48/fdc6d0fc8bae7429d5e4081cf353",
"build/assets/pylib-android/fileinput.py": "https://files.ballistica.net/cache/ba1/c3/de/f1041e6b12dd5f1906c9dbbd1101",
"build/assets/pylib-android/fnmatch.py": "https://files.ballistica.net/cache/ba1/a1/bc/67633695d4defd4c0886428c5363",
@ -2869,15 +2869,15 @@
"build/assets/pylib-android/html/entities.py": "https://files.ballistica.net/cache/ba1/85/61/b405414160a08f613bdfd89e161b",
"build/assets/pylib-android/html/parser.py": "https://files.ballistica.net/cache/ba1/c2/ff/6801a3ef6a2863d37b899615efb8",
"build/assets/pylib-android/http/__init__.py": "https://files.ballistica.net/cache/ba1/1d/ab/578aab89ead7171ef10638e88a5d",
"build/assets/pylib-android/http/client.py": "https://files.ballistica.net/cache/ba1/d0/b3/7013d5f9794a8311c3545ee5416d",
"build/assets/pylib-android/http/client.py": "https://files.ballistica.net/cache/ba1/a3/f2/cd21f8ce7a4ee1b47f0b19fb57f7",
"build/assets/pylib-android/http/cookiejar.py": "https://files.ballistica.net/cache/ba1/f3/24/a21e7c17f40e4d5c78139875811c",
"build/assets/pylib-android/http/cookies.py": "https://files.ballistica.net/cache/ba1/93/19/b95b505a644b9a112b4c7a7678c3",
"build/assets/pylib-android/http/server.py": "https://files.ballistica.net/cache/ba1/a0/6b/26669fc0eb0ef81b819fe8a6602d",
"build/assets/pylib-android/http/server.py": "https://files.ballistica.net/cache/ba1/4b/28/6e2b5e6112af17e097539eadd9d7",
"build/assets/pylib-android/imghdr.py": "https://files.ballistica.net/cache/ba1/01/1d/27a98acf3774279a584525614ba3",
"build/assets/pylib-android/imp.py": "https://files.ballistica.net/cache/ba1/34/bd/1d1620eb0d42f9ef9bbbb11cafae",
"build/assets/pylib-android/importlib/__init__.py": "https://files.ballistica.net/cache/ba1/2f/6c/1fb453d61417245cd196311a9b52",
"build/assets/pylib-android/importlib/_abc.py": "https://files.ballistica.net/cache/ba1/72/0f/8056e5cd852156378b532ddbbb7c",
"build/assets/pylib-android/importlib/_bootstrap.py": "https://files.ballistica.net/cache/ba1/da/9d/e7a6d6839a7185147f35f2040de7",
"build/assets/pylib-android/importlib/_bootstrap.py": "https://files.ballistica.net/cache/ba1/6f/48/19e9443e3fda3c28c62f15a8238c",
"build/assets/pylib-android/importlib/_bootstrap_external.py": "https://files.ballistica.net/cache/ba1/aa/2d/5aab23ea30219b7a42d2b7d27201",
"build/assets/pylib-android/importlib/abc.py": "https://files.ballistica.net/cache/ba1/c9/69/7e928ff17089dc6aea96f5b33003",
"build/assets/pylib-android/importlib/machinery.py": "https://files.ballistica.net/cache/ba1/6a/05/6c561b4ea8eb5457761c8a9fd704",
@ -2899,7 +2899,7 @@
"build/assets/pylib-android/importlib/resources/simple.py": "https://files.ballistica.net/cache/ba1/ae/95/788edf31cbfffd53db748d76f0b9",
"build/assets/pylib-android/importlib/simple.py": "https://files.ballistica.net/cache/ba1/f3/4f/28cd359ecaf9fd6cf18a4dca2c33",
"build/assets/pylib-android/importlib/util.py": "https://files.ballistica.net/cache/ba1/09/c3/a96d1265db211f32b73a5f76e1ac",
"build/assets/pylib-android/inspect.py": "https://files.ballistica.net/cache/ba1/5a/32/1fd388139d2beff15f4306b1fb95",
"build/assets/pylib-android/inspect.py": "https://files.ballistica.net/cache/ba1/36/5d/413e26b3a77118e51987cfd2eb1f",
"build/assets/pylib-android/io.py": "https://files.ballistica.net/cache/ba1/4a/3a/b68b3f38d3dcf9282f4839fe5d84",
"build/assets/pylib-android/ipaddress.py": "https://files.ballistica.net/cache/ba1/b9/83/1cf9058885b35a2411b4cbada972",
"build/assets/pylib-android/json/__init__.py": "https://files.ballistica.net/cache/ba1/e8/b0/00d2bf8c53b55a72bc3053800596",
@ -2911,7 +2911,7 @@
"build/assets/pylib-android/linecache.py": "https://files.ballistica.net/cache/ba1/27/12/c31a3a6d7625d437029a6b7470c9",
"build/assets/pylib-android/locale.py": "https://files.ballistica.net/cache/ba1/42/f3/f48fed6a16da350de46aa85b446a",
"build/assets/pylib-android/logging/__init__.py": "https://files.ballistica.net/cache/ba1/6e/5d/6f80af880857f5eb29b038512c6d",
"build/assets/pylib-android/logging/config.py": "https://files.ballistica.net/cache/ba1/ff/06/97c60f90420c32c697a30bfdfe90",
"build/assets/pylib-android/logging/config.py": "https://files.ballistica.net/cache/ba1/f8/11/372496ec5ae34e8047f0280686be",
"build/assets/pylib-android/logging/handlers.py": "https://files.ballistica.net/cache/ba1/ab/38/81444783ab84f3859e022b356989",
"build/assets/pylib-android/lzma.py": "https://files.ballistica.net/cache/ba1/d7/38/8640aa6af4c64fdc821471930f57",
"build/assets/pylib-android/mailbox.py": "https://files.ballistica.net/cache/ba1/d9/db/3c7510e38484ade3d88446b8f231",
@ -2920,27 +2920,27 @@
"build/assets/pylib-android/modulefinder.py": "https://files.ballistica.net/cache/ba1/3f/c0/74c018de1dd15ab2e309be199dea",
"build/assets/pylib-android/netrc.py": "https://files.ballistica.net/cache/ba1/9a/86/9ca83b316ab5a19a0a2cf22efaf3",
"build/assets/pylib-android/nntplib.py": "https://files.ballistica.net/cache/ba1/49/26/aa991bd4b96b9318d6242135abf9",
"build/assets/pylib-android/ntpath.py": "https://files.ballistica.net/cache/ba1/36/55/7dc9fdcd9eeeab4d46c1a364bd5a",
"build/assets/pylib-android/ntpath.py": "https://files.ballistica.net/cache/ba1/57/ea/cdf2824f306ae2b03d5818294c94",
"build/assets/pylib-android/nturl2path.py": "https://files.ballistica.net/cache/ba1/93/76/24c4b6f213b652addea66296ccc4",
"build/assets/pylib-android/numbers.py": "https://files.ballistica.net/cache/ba1/0c/dc/b42317422500d514ec67d496a06e",
"build/assets/pylib-android/opcode.py": "https://files.ballistica.net/cache/ba1/18/cb/a8b1d09ec6fcccfe20e5b13db980",
"build/assets/pylib-android/operator.py": "https://files.ballistica.net/cache/ba1/61/e1/97bc43df97ec39ae3e5e59b11c19",
"build/assets/pylib-android/optparse.py": "https://files.ballistica.net/cache/ba1/5f/65/f891612b68c71a2846da86254285",
"build/assets/pylib-android/os.py": "https://files.ballistica.net/cache/ba1/36/f9/692131ffb9ba4db510de31afc651",
"build/assets/pylib-android/pathlib.py": "https://files.ballistica.net/cache/ba1/3e/8b/893cbe95729cdb6d0cc796e89e19",
"build/assets/pylib-android/pdb.py": "https://files.ballistica.net/cache/ba1/da/4c/484348d4b2009479dadd878f20b0",
"build/assets/pylib-android/pathlib.py": "https://files.ballistica.net/cache/ba1/09/5e/c821fec243124d0a286b4de3848a",
"build/assets/pylib-android/pdb.py": "https://files.ballistica.net/cache/ba1/11/7b/0d24ccb89edc5f183c94f6722f70",
"build/assets/pylib-android/pickle.py": "https://files.ballistica.net/cache/ba1/e6/f9/f53d29988454690ccde3279c7c38",
"build/assets/pylib-android/pickletools.py": "https://files.ballistica.net/cache/ba1/85/b3/0fba86d32dfc4a588300dedf5f01",
"build/assets/pylib-android/pipes.py": "https://files.ballistica.net/cache/ba1/2d/d7/96bdbb87982034234fec50d4526c",
"build/assets/pylib-android/pkgutil.py": "https://files.ballistica.net/cache/ba1/37/2a/540a2f2f3a324d5ff8e137579aad",
"build/assets/pylib-android/pkgutil.py": "https://files.ballistica.net/cache/ba1/8e/3f/dfcb6c90dc50245aee89c49eb515",
"build/assets/pylib-android/platform.py": "https://files.ballistica.net/cache/ba1/07/2a/4f8d700c73429d420ca8f5f3a90d",
"build/assets/pylib-android/plistlib.py": "https://files.ballistica.net/cache/ba1/8a/a9/836b7a69628873b25811c4d5fffa",
"build/assets/pylib-android/poplib.py": "https://files.ballistica.net/cache/ba1/82/9d/c4df5d8e082ad414d499ec4678bd",
"build/assets/pylib-android/posixpath.py": "https://files.ballistica.net/cache/ba1/2a/6b/3f940f89b0819ee002b6b82b0318",
"build/assets/pylib-android/pprint.py": "https://files.ballistica.net/cache/ba1/b4/e9/efe35d05b6126d41da36eda47754",
"build/assets/pylib-android/profile.py": "https://files.ballistica.net/cache/ba1/4c/08/16d9278d2a33e28835fcd291fb62",
"build/assets/pylib-android/profile.py": "https://files.ballistica.net/cache/ba1/a9/f1/1f8aa6a2905706a5fc9273d6c981",
"build/assets/pylib-android/pstats.py": "https://files.ballistica.net/cache/ba1/c5/88/4aaae199265ab0c3849d053bc996",
"build/assets/pylib-android/pty.py": "https://files.ballistica.net/cache/ba1/1d/e2/d1bfbdc54a770de7b3010d322620",
"build/assets/pylib-android/pty.py": "https://files.ballistica.net/cache/ba1/c9/7b/51147360cf7fd92c364ab8068a2b",
"build/assets/pylib-android/py_compile.py": "https://files.ballistica.net/cache/ba1/77/2b/429c589d2e005e8bd79b12f55a92",
"build/assets/pylib-android/pyclbr.py": "https://files.ballistica.net/cache/ba1/bf/19/89a2c73108005e874a640760476a",
"build/assets/pylib-android/pydoc.py": "https://files.ballistica.net/cache/ba1/0f/8a/4b2f4a9d23e429c01660a4290bd8",
@ -2960,7 +2960,7 @@
"build/assets/pylib-android/selectors.py": "https://files.ballistica.net/cache/ba1/98/e0/d83849452cbc2cc1381555bd5024",
"build/assets/pylib-android/shelve.py": "https://files.ballistica.net/cache/ba1/3e/56/9c07c863ecbd7f35a6c382d1785a",
"build/assets/pylib-android/shlex.py": "https://files.ballistica.net/cache/ba1/08/73/fac90a491702950816ead0e59dd0",
"build/assets/pylib-android/shutil.py": "https://files.ballistica.net/cache/ba1/65/1b/e1edc2110d483c96fbe26f40665d",
"build/assets/pylib-android/shutil.py": "https://files.ballistica.net/cache/ba1/ed/25/b38eacc66c9059651e6666ec1869",
"build/assets/pylib-android/signal.py": "https://files.ballistica.net/cache/ba1/11/4e/f47b1798fca6f56ac8a250974b3e",
"build/assets/pylib-android/site.py": "https://files.ballistica.net/cache/ba1/2a/99/f7de2702aa8411d35acbb91fe926",
"build/assets/pylib-android/smtpd.py": "https://files.ballistica.net/cache/ba1/06/02/b6a39c4e37133303bee16c3e28a4",
@ -2980,12 +2980,12 @@
"build/assets/pylib-android/string.py": "https://files.ballistica.net/cache/ba1/c0/72/d3a2d0337386d3235ba72f292752",
"build/assets/pylib-android/stringprep.py": "https://files.ballistica.net/cache/ba1/6a/56/35711a838f76fee7b52537bf8b45",
"build/assets/pylib-android/struct.py": "https://files.ballistica.net/cache/ba1/4f/d2/88bd6537effd1d5edbba9d44dde2",
"build/assets/pylib-android/subprocess.py": "https://files.ballistica.net/cache/ba1/76/c5/0ab326efee3ecd6b54b3a9d0bd94",
"build/assets/pylib-android/subprocess.py": "https://files.ballistica.net/cache/ba1/4d/65/22342cab21c558e60b2f50c5cedc",
"build/assets/pylib-android/sunau.py": "https://files.ballistica.net/cache/ba1/a0/34/779289fef0b2221345f40e042680",
"build/assets/pylib-android/symtable.py": "https://files.ballistica.net/cache/ba1/0c/d4/a624b2e3304664f43189ed9e3bf7",
"build/assets/pylib-android/sysconfig.py": "https://files.ballistica.net/cache/ba1/9f/fa/d6cfff49bc09fe36a33a5446c59d",
"build/assets/pylib-android/tabnanny.py": "https://files.ballistica.net/cache/ba1/84/61/4c63ead0ab71527cecdf3de68f1a",
"build/assets/pylib-android/tarfile.py": "https://files.ballistica.net/cache/ba1/76/bf/209364cd327ee75e9dac3211c882",
"build/assets/pylib-android/tarfile.py": "https://files.ballistica.net/cache/ba1/a6/df/d478cf3917a29020944bff1a6f2d",
"build/assets/pylib-android/telnetlib.py": "https://files.ballistica.net/cache/ba1/1a/74/6e1fc988b9f5c12b9fd5a97c00ea",
"build/assets/pylib-android/tempfile.py": "https://files.ballistica.net/cache/ba1/43/60/07fbe6821c864a53861bd73b4d43",
"build/assets/pylib-android/textwrap.py": "https://files.ballistica.net/cache/ba1/3e/b1/6a40553205dc96be5cb9039f3c8c",
@ -2998,22 +2998,22 @@
"build/assets/pylib-android/tomllib/_parser.py": "https://files.ballistica.net/cache/ba1/f9/a4/dc92c44403f970e94c2e494a7358",
"build/assets/pylib-android/tomllib/_re.py": "https://files.ballistica.net/cache/ba1/0e/50/9117e16c41c491615e06bb98861d",
"build/assets/pylib-android/tomllib/_types.py": "https://files.ballistica.net/cache/ba1/07/be/9616d6f5e401fd31fbeea619fc97",
"build/assets/pylib-android/trace.py": "https://files.ballistica.net/cache/ba1/c8/60/164b4f4317299db04e29070a163d",
"build/assets/pylib-android/traceback.py": "https://files.ballistica.net/cache/ba1/bb/2d/c63a0bcd438697904573807bd392",
"build/assets/pylib-android/trace.py": "https://files.ballistica.net/cache/ba1/3d/86/98a2c3ec03dc0f394a2f48c2ffbc",
"build/assets/pylib-android/traceback.py": "https://files.ballistica.net/cache/ba1/91/f6/7818e621e3b2f5bf583ed6863ef8",
"build/assets/pylib-android/tracemalloc.py": "https://files.ballistica.net/cache/ba1/e4/d1/0d2bee7773566e46797a939e5cbf",
"build/assets/pylib-android/tty.py": "https://files.ballistica.net/cache/ba1/27/1c/7d61005a0a3c2c0952efc60dcb6d",
"build/assets/pylib-android/types.py": "https://files.ballistica.net/cache/ba1/78/f8/942c08dbfc9c582f1bb8d5206639",
"build/assets/pylib-android/typing.py": "https://files.ballistica.net/cache/ba1/c0/7f/a037183494716cd57a7c9ac05d78",
"build/assets/pylib-android/typing.py": "https://files.ballistica.net/cache/ba1/89/e0/654fda4fd2a09e93391179859cf0",
"build/assets/pylib-android/urllib/__init__.py": "https://files.ballistica.net/cache/ba1/34/0c/83beff7dcff8f5c7b87cd43cedaf",
"build/assets/pylib-android/urllib/error.py": "https://files.ballistica.net/cache/ba1/b7/dd/e0483ff647eb87162d6e19c04fa0",
"build/assets/pylib-android/urllib/parse.py": "https://files.ballistica.net/cache/ba1/d4/72/83907682d432b511b85dd1e32572",
"build/assets/pylib-android/urllib/request.py": "https://files.ballistica.net/cache/ba1/e8/9a/853d76344f1ca197926d49b3b9e6",
"build/assets/pylib-android/urllib/parse.py": "https://files.ballistica.net/cache/ba1/dc/73/5bb3e0b069762ad988c1b55ce6e3",
"build/assets/pylib-android/urllib/request.py": "https://files.ballistica.net/cache/ba1/09/b8/666fe8319542f7247bb9f8573806",
"build/assets/pylib-android/urllib/response.py": "https://files.ballistica.net/cache/ba1/c8/53/7707a4b1e493c0ec4489ab523c93",
"build/assets/pylib-android/urllib/robotparser.py": "https://files.ballistica.net/cache/ba1/5a/76/16bdf398c166f953ad48c25506eb",
"build/assets/pylib-android/uu.py": "https://files.ballistica.net/cache/ba1/93/26/8d78026ebde74a1ccd14024ae59f",
"build/assets/pylib-android/uu.py": "https://files.ballistica.net/cache/ba1/7c/b7/95ca0c9e914550e6245dfe53c53e",
"build/assets/pylib-android/uuid.py": "https://files.ballistica.net/cache/ba1/75/5d/75cad456d0c3ab0c67f0276cca32",
"build/assets/pylib-android/warnings.py": "https://files.ballistica.net/cache/ba1/e5/f0/b4cbc35aae8d4b89a856b189b626",
"build/assets/pylib-android/wave.py": "https://files.ballistica.net/cache/ba1/cb/12/5197ba1b7955bbee4ebde9f385ce",
"build/assets/pylib-android/wave.py": "https://files.ballistica.net/cache/ba1/72/7a/8dacad95625ea14554b7d655ce2e",
"build/assets/pylib-android/weakref.py": "https://files.ballistica.net/cache/ba1/dd/14/612f02ca8acd723f633b6fff0adf",
"build/assets/pylib-android/webbrowser.py": "https://files.ballistica.net/cache/ba1/81/85/b8d83c5311ddea5d88a1cfb89c3c",
"build/assets/pylib-android/xdrlib.py": "https://files.ballistica.net/cache/ba1/ee/12/e9067ab4904da935b8d2213426d8",
@ -3043,7 +3043,7 @@
"build/assets/pylib-android/xmlrpc/client.py": "https://files.ballistica.net/cache/ba1/8f/2c/ad71c1c87031be073184e71aa405",
"build/assets/pylib-android/xmlrpc/server.py": "https://files.ballistica.net/cache/ba1/31/47/663bd28b952eef0e1316b94bacc6",
"build/assets/pylib-android/zipapp.py": "https://files.ballistica.net/cache/ba1/d9/2e/a793f092af6383a6383678cf7b73",
"build/assets/pylib-android/zipfile.py": "https://files.ballistica.net/cache/ba1/21/cd/b798a8f660aa3ec322ce59bddac9",
"build/assets/pylib-android/zipfile.py": "https://files.ballistica.net/cache/ba1/2c/d1/a57574daf0ec6456dc2d0858952d",
"build/assets/pylib-android/zipimport.py": "https://files.ballistica.net/cache/ba1/6d/3b/32a7258f670eb71daf3a8492a4f1",
"build/assets/pylib-android/zoneinfo/__init__.py": "https://files.ballistica.net/cache/ba1/0d/f5/e8a66015e2fe2d77f2e4a5dea1ff",
"build/assets/pylib-android/zoneinfo/_common.py": "https://files.ballistica.net/cache/ba1/5b/52/bdac4156dcbac96743fa99468bf2",
@ -3064,7 +3064,7 @@
"build/assets/pylib-apple/_pyio.py": "https://files.ballistica.net/cache/ba1/a6/e8/8d66fbca88b13213cdd2177390b8",
"build/assets/pylib-apple/_sitebuiltins.py": "https://files.ballistica.net/cache/ba1/8b/5e/3f6e73917962fa014ad2c4a55e61",
"build/assets/pylib-apple/_strptime.py": "https://files.ballistica.net/cache/ba1/ff/69/9c3f7647db7621bb88c43cc282d3",
"build/assets/pylib-apple/_sysconfigdata__darwin_darwin.py": "https://files.ballistica.net/cache/ba1/c8/9e/dcdc08ac22a30cac42dad0f099e6",
"build/assets/pylib-apple/_sysconfigdata__darwin_darwin.py": "https://files.ballistica.net/cache/ba1/1d/eb/8b4ea385ac52e2fc30eb5b7486d9",
"build/assets/pylib-apple/_sysconfigdata__ios_iphoneos.py": "https://files.ballistica.net/cache/ba1/5b/fc/ed73a12261ecc310bffce6786cd2",
"build/assets/pylib-apple/_sysconfigdata__ios_iphoneos_arm64.py": "https://files.ballistica.net/cache/ba1/13/cd/af0612cecdfdea79507be605b5fa",
"build/assets/pylib-apple/_sysconfigdata__ios_iphonesimulator.py": "https://files.ballistica.net/cache/ba1/f9/c9/55d9c5c9cf5a0a026d084a1f9519",
@ -3075,7 +3075,7 @@
"build/assets/pylib-apple/_sysconfigdata__tvos_appletvsimulator.py": "https://files.ballistica.net/cache/ba1/a3/c8/8367fb568e377ef2a72f0e9c2394",
"build/assets/pylib-apple/_sysconfigdata__tvos_appletvsimulator_arm64.py": "https://files.ballistica.net/cache/ba1/bf/5e/3b80c0bd0f6e8d00372d4f6f1ae5",
"build/assets/pylib-apple/_sysconfigdata__tvos_appletvsimulator_x86_64.py": "https://files.ballistica.net/cache/ba1/48/28/cee78f35df83a94a308919080918",
"build/assets/pylib-apple/_sysconfigdata_d_darwin_darwin.py": "https://files.ballistica.net/cache/ba1/1c/01/95f871b00015f14a9fabd2e1f645",
"build/assets/pylib-apple/_sysconfigdata_d_darwin_darwin.py": "https://files.ballistica.net/cache/ba1/9e/b9/1d9cd5328d59ceb9047d210beaba",
"build/assets/pylib-apple/_sysconfigdata_d_ios_iphoneos.py": "https://files.ballistica.net/cache/ba1/5b/fc/ed73a12261ecc310bffce6786cd2",
"build/assets/pylib-apple/_sysconfigdata_d_ios_iphoneos_arm64.py": "https://files.ballistica.net/cache/ba1/11/62/2b9e1d51ef4a4225099acb1e8200",
"build/assets/pylib-apple/_sysconfigdata_d_ios_iphonesimulator.py": "https://files.ballistica.net/cache/ba1/f9/c9/55d9c5c9cf5a0a026d084a1f9519",
@ -4068,26 +4068,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/2d/ef/5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/b0/8a/55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/86/5b/2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/05/39/9f392f63f9383e8ef3457d08f362",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/ea/05/7ea22ed9c5f1f514b9e39d90cde6",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/46/1c/bd65d52f0848387e56a536a346a5",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/40/b8/fa9aeee2292fde22215797faa75b",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/78/b0/3d856abf820b6410d2729246b3c2",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/a1/85/9ca2209cd2baf659b4e2b40b79fd",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/3b/e4/d49571e34cf479114d9cf4742737",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/e7/b8/53a5666e993663054202393e589b",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/8f/6a/9b8d0b4b6dd97f4d5d4b48f5b84d",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/48/1d/c9762e55356a288aebfefecbd43e",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/14/9f/91b6ce7c3282ae203703618627a9",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/78/71/d5ab66d0f577a746e05f44d753bd",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/33/67/e32865d5160bb26183b8b4257a88",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/85/ba/98322913ba70e71e3858ee7916e5",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/12/37/ca8d54ec589bc95dd9030a635035",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9f/b7/fdec2c3c131abe175e716698605e",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/08/59/d701c12712effe14b89ea37c013f",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/99/01/8c49ac6d34dc7219ccf047794437",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/51/ae/49b7723adac6c2e763d03bf27b16",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/32/18/35d3b785547afc61cfb6b3ba3504",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/7a/5c/7f2aaa9051adf632dc957f61ef55",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/ae/11/e739a151be864da4c87c15c155fa",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/bc/0c/f1a578e5329a81a91618b03f7029",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/32/e1/c608186cfa17d5ebc93e676166bd",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/0f/b0/bfd562781cf6ae1b0224d76e7c3b",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/f3/a9/1b6cce29b356c2317b6f1126ba9b",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/67/ac/03c3e7d5499a978e2af2099aae55",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/22/c0/4b32851978bf97cccd4c45f71a43",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/90/28/e0d6e0de8df08e0537816c8838a0",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/3d/c5/ffa0a2051e467d002bc272316da6",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9f/fe/5e9e6873b520b720754ab1794b3c",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/62/8f/4ffeb86197612d84f648141e5dd4",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/b6/ca/46a742136cc8824e171de4c8e683",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/c0/d6/18ad1186b589cd30d0f252b0b542",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/12/df/24c41de1b3bab9d010b17969c69f",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/75/c2/8f3635450156521401ff37c6070c",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/8e/df/6d1d1ef0ed45c6a81f60e7dbc3a5",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/bf/1e/d1bf7b259d98fd464889aa755c22",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/46/1b/20394315126f1f9aa200bd736ad7",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/25/36/a159b2c628f6cbbbcc7aa8f90b12",
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/be/19/b5458933dfc7371d91ecfcd2e06f",
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4e/48/123b806cbe6ddb3d9a8368bbb4f8",
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/be/19/b5458933dfc7371d91ecfcd2e06f",
@ -4104,18 +4104,18 @@
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/7e/fa/291fd7e935502ced7e99b8c8f7f0",
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/e1/cb/7e8440699e59e8646da25aa5782b",
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/7e/fa/291fd7e935502ced7e99b8c8f7f0",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/5c/4e/26f72e68d55dcf12d62b1274b7ad",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/c3/61/d40dfab20f59da7155b942632066",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/a9/f7/ddae4d7e7e59f0b9db4eee09d226",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/4a/a4/c9c09853640eb5a5f5a0ce4cf71c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/9d/42/a7bc0e69180e2e45e5b5b93cc49c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/9a/a7/5e31d7b317e4544feff2eabad4a5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/3b/74/84e7f0fb207da9a99a0c71b12a2e",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/2e/dc/4406fedd025a80037e395097ee19",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/66/17/448c77d6413f25555e40055d154b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/56/b0/7ce3384cfb63d3a224e317c69fa8",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/b6/73/847160ecfbbbea758f130c03abb8",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/dc/e6/e052a9115ca83686c6634d2c26ff",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/2e/56/390279b063b7f8455cf7f1656608",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/3a/d7/a0329b38db9b594c36ff88a884c9",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/a5/9b/0802a9d6604fffc0136ac95a5be3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/e9/74/5d6a32e3a161a2f5597aa9336b79",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/f8/85/fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/48/4b/e6974f0a4d14be8213dc00d971c3",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/3e/7a/203e2a5d2b5bb42cfe3fd2fe16c2",
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "https://files.ballistica.net/cache/ba1/41/38/52cb9a73efef37404cec22fca18e",
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "https://files.ballistica.net/cache/ba1/c2/f2/cb8d052d76a1f4abe163cab2276e",
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "https://files.ballistica.net/cache/ba1/3c/eb/412513963f0818ab39c58bf292e3",
"src/ballistica/core/mgen/pyembed/binding_core.inc": "https://files.ballistica.net/cache/ba1/9d/0a/3c9636138e35284923e0c8311c69",
"src/ballistica/core/mgen/pyembed/env.inc": "https://files.ballistica.net/cache/ba1/8b/e4/6e5818f360d10b7b0224a9e91d07",

View File

@ -1,6 +1,9 @@
### 1.7.21 (build 21143, api 8, 2023-06-25)
### 1.7.21 (build 21147, api 8, 2023-06-26)
- Fixed an issue where server builds would not always include collision meshes.
- Upgraded Python to 3.11.4 on Android builds.
- Cleaned up the language subsystem and the process for applying app-config
changes a bit. Please holler if you see weirdness in either.
### 1.7.20 (build 21140, api 8, 2023-06-22)
@ -360,8 +363,8 @@
use log calls instead of prints. The environment vars to enable them are now
`BA_DEBUG_LOG_CONNECTIVITY` and `BA_DEBUG_LOG_V2_TRANSPORT`. Set either to '1'
to enable debug logging.
- (build 21125) Fixed a bug where feature-sets would not have their
DoApplyConfig callbacks called in C++, which was causing the server-mode
- (build 21125) Fixed a bug where app-modes would not have their
DoApplyAppConfig callbacks called in C++, which was causing the server-mode
`idle_exit_minutes` value to be ignored. Servers should now properly exit
after being idle for this length of time.
- (build 21126) Reworked the efrocache system used by public builds for

View File

@ -21,14 +21,14 @@ with specific naming conventions:
in this directory called `featureset_foo_bar.py`.
- **Python Package**: If feature set `foo_bar` provides a Python package, it
should be a directory named `bafoobar` ('ba' prefix, name with spaces removed)
that lives under [Python source files](../../src/assets/ba_data/python).
that lives under [src/assets/ba_data/python](../../src/assets/ba_data/python).
- **Native Code**: If feature set `foo_bar` provides a native component (C++
code or otherwise) it should live in a directory named `foo_bar` (unmodified
feature set name) under [native source files](../../src/ballistica).
feature set name) under [src/ballistica](../../src/ballistica).
- **Meta Package**: If feature set `foo_bar` provides a meta package (that is,
code or data used to generate other source code), it should be a directory
named `bafoobarmeta` ('ba' prefix, name with spaces removed, 'meta' suffix)
that lives under [meta source files](../../src/meta).
that lives under [src/meta](../../src/meta).
- **Test Package**: If feature set `foo_bar` provides a set of tests, it should
be a directory named `test_foo_bar` ('test_' prefix, unmodified feature set
name) under [tests](../../tests).

View File

@ -54,8 +54,8 @@ class App:
# pylint: disable=too-many-public-methods
plugins: PluginSubsystem
lang: LanguageSubsystem
# log_handler: LogHandler
health_monitor: AppHealthMonitor
class State(Enum):
@ -247,6 +247,7 @@ class App:
self._called_on_app_running = False
self._app_paused = False
self._subsystem_registration_ended = False
self._pending_apply_app_config = False
# Config.
self.config_file_healthy = False
@ -281,7 +282,6 @@ class App:
self.components = AppComponentSubsystem()
self.meta = MetadataSubsystem()
self.lang = LanguageSubsystem()
self.net = NetworkSubsystem()
self.workspaces = WorkspaceSubsystem()
self._pending_intent: AppIntent | None = None
@ -297,7 +297,7 @@ class App:
self._asyncio_timer: babase.AppTimer | None = None
def postinit(self) -> None:
"""Called after we are inited and assigned to babase.app."""
"""Called after we've been inited and assigned to babase.app."""
if os.environ.get('BA_RUNNING_WITH_DUMMY_MODULES') == '1':
return
@ -306,6 +306,7 @@ class App:
# some of this stuff accesses babase.app and that doesn't
# exist yet as of our __init__() call.
self.lang = LanguageSubsystem()
self.plugins = PluginSubsystem()
def register_subsystem(self, subsystem: AppSubsystem) -> None:
@ -622,6 +623,39 @@ class App:
# plugin hasn't already told it to do something.
self.set_intent(AppIntentDefault())
def push_apply_app_config(self) -> None:
"""Internal. Use app.config.apply() to apply app config changes."""
# To be safe, let's run this by itself in the event loop.
# This avoids potential trouble if this gets called mid-draw or
# something like that.
self._pending_apply_app_config = True
_babase.pushcall(self._apply_app_config, raw=True)
def _apply_app_config(self) -> None:
assert _babase.in_logic_thread()
_babase.lifecyclelog('apply-app-config')
# If multiple apply calls have been made, only actually apply once.
if not self._pending_apply_app_config:
return
_pending_apply_app_config = False
# Inform all app subsystems in the same order they were inited.
# Operate on a copy here because subsystems may still be able to
# be added at this point.
for subsystem in self._subsystems.copy():
try:
subsystem.do_apply_app_config()
except Exception:
logging.exception(
'Error in do_apply_app_config for subsystem %s.', subsystem
)
# Let the native layer do its thing.
_babase.do_apply_app_config()
class DefaultAppModeSelector(AppModeSelector):
"""Decides which app modes to use to handle intents.

View File

@ -10,6 +10,8 @@ import _babase
if TYPE_CHECKING:
from typing import Any
_g_pending_apply = False # pylint: disable=invalid-name
class AppConfig(dict):
"""A special dict that holds the game's persistent configuration values.
@ -74,8 +76,12 @@ class AppConfig(dict):
return _babase.get_appconfig_builtin_keys()
def apply(self) -> None:
"""Apply config values to the running app."""
_babase.apply_config()
"""Apply config values to the running app.
This call is thread-safe and asynchronous; changes will happen
in the next logic event loop cycle.
"""
_babase.app.push_apply_app_config()
def commit(self) -> None:
"""Commits the config to local storage.

View File

@ -47,3 +47,6 @@ class AppSubsystem:
def on_app_shutdown(self) -> None:
"""Called when the app is shutting down."""
def do_apply_app_config(self) -> None:
"""Called when the app config should be applied."""

View File

@ -9,6 +9,7 @@ import logging
from typing import TYPE_CHECKING, overload
import _babase
from babase._appsubsystem import AppSubsystem
if TYPE_CHECKING:
from typing import Any, Sequence
@ -16,44 +17,21 @@ if TYPE_CHECKING:
import babase
class LanguageSubsystem:
"""Wraps up language related app functionality.
class LanguageSubsystem(AppSubsystem):
"""Language functionality for the app.
Category: **App Classes**
To use this class, access the single instance of it at 'ba.app.lang'.
Access the single instance of this class at 'babase.app.lang'.
"""
def __init__(self) -> None:
self.language_target: AttrDict | None = None
self.language_merged: AttrDict | None = None
self.default_language = self._get_default_language()
super().__init__()
self.default_language: str = self._get_default_language()
def _can_display_language(self, language: str) -> bool:
"""Tell whether we can display a particular language.
On some platforms we don't have unicode rendering yet
which limits the languages we can draw.
"""
# We don't yet support full unicode display on windows or linux :-(.
if (
language
in {
'Chinese',
'ChineseTraditional',
'Persian',
'Korean',
'Arabic',
'Hindi',
'Vietnamese',
'Thai',
'Tamil',
}
and not _babase.can_display_full_unicode()
):
return False
return True
self._language: str | None = None
self._language_target: AttrDict | None = None
self._language_merged: AttrDict | None = None
@property
def locale(self) -> str:
@ -67,62 +45,16 @@ class LanguageSubsystem:
assert isinstance(env['locale'], str)
return env['locale']
def _get_default_language(self) -> str:
languages = {
'ar': 'Arabic',
'be': 'Belarussian',
'zh': 'Chinese',
'hr': 'Croatian',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'eo': 'Esperanto',
'fil': 'Filipino',
'fr': 'French',
'de': 'German',
'el': 'Greek',
'hi': 'Hindi',
'hu': 'Hungarian',
'id': 'Indonesian',
'it': 'Italian',
'ko': 'Korean',
'ms': 'Malay',
'fa': 'Persian',
'pl': 'Polish',
'pt': 'Portuguese',
'ro': 'Romanian',
'ru': 'Russian',
'sr': 'Serbian',
'es': 'Spanish',
'sk': 'Slovak',
'sv': 'Swedish',
'ta': 'Tamil',
'th': 'Thai',
'tr': 'Turkish',
'uk': 'Ukrainian',
'vec': 'Venetian',
'vi': 'Vietnamese',
}
# Special case for Chinese: map specific variations to traditional.
# (otherwise will map to 'Chinese' which is simplified)
if self.locale in ('zh_HANT', 'zh_TW'):
language = 'ChineseTraditional'
else:
language = languages.get(self.locale[:2], 'English')
if not self._can_display_language(language):
language = 'English'
return language
@property
def language(self) -> str:
"""The name of the language the game is running in.
"""The current active language for the app.
This can be selected explicitly by the user or may be set
automatically based on babase.App.locale or other factors.
automatically based on locale or other factors.
"""
assert isinstance(_babase.app.config, dict)
return _babase.app.config.get('Lang', self.default_language)
if self._language is None:
raise RuntimeError('App language is not yet set.')
return self._language
@property
def available_languages(self) -> list[str]:
@ -164,13 +96,14 @@ class LanguageSubsystem:
print_change: bool = True,
store_to_config: bool = True,
) -> None:
"""Set the active language used for the game.
"""Set the active app language.
Pass None to use OS default language.
"""
# pylint: disable=too-many-locals
# pylint: disable=too-many-statements
# pylint: disable=too-many-branches
assert _babase.in_logic_thread()
cfg = _babase.app.config
cur_language = cfg.get('Lang', None)
@ -215,38 +148,36 @@ class LanguageSubsystem:
with open(lmodfile, encoding='utf-8') as infile:
lmodvalues = json.loads(infile.read())
except Exception:
from babase import _error
_error.print_exception('Exception importing language:', language)
logging.exception("Error importing language '%s'.", language)
_babase.screenmessage(
"Error setting language to '"
+ language
+ "'; see log for details",
f"Error setting language to '{language}'; see log for details.",
color=(1, 0, 0),
)
switched = False
lmodvalues = None
self._language = language
# Create an attrdict of *just* our target language.
self.language_target = AttrDict()
langtarget = self.language_target
self._language_target = AttrDict()
langtarget = self._language_target
assert langtarget is not None
_add_to_attr_dict(
langtarget, lmodvalues if lmodvalues is not None else lenglishvalues
)
# Create an attrdict of our target language overlaid
# on our base (english).
# Create an attrdict of our target language overlaid on our base
# (english).
languages = [lenglishvalues]
if lmodvalues is not None:
languages.append(lmodvalues)
lfull = AttrDict()
for lmod in languages:
_add_to_attr_dict(lfull, lmod)
self.language_merged = lfull
self._language_merged = lfull
# Pass some keys/values in for low level code to use;
# start with everything in their 'internal' section.
# Pass some keys/values in for low level code to use; start with
# everything in their 'internal' section.
internal_vals = [
v for v in list(lfull['internal'].items()) if isinstance(v[1], str)
]
@ -265,7 +196,7 @@ class LanguageSubsystem:
('axisText', lfull['configGamepadWindow']['axisText'])
)
internal_vals.append(('buttonText', lfull['buttonText']))
lmerged = self.language_merged
lmerged = self._language_merged
assert lmerged is not None
random_names = [
n.strip() for n in lmerged['randomPlayerNamesText'].split(',')
@ -283,6 +214,13 @@ class LanguageSubsystem:
color=(0, 1, 0),
)
def do_apply_app_config(self) -> None:
assert _babase.in_logic_thread()
assert isinstance(_babase.app.config, dict)
lang = _babase.app.config.get('Lang', self.default_language)
if lang != self._language:
self.setlanguage(lang, print_change=False, store_to_config=False)
def get_resource(
self,
resource: str,
@ -294,38 +232,30 @@ class LanguageSubsystem:
DEPRECATED; use babase.Lstr functionality for these purposes.
"""
try:
# If we have no language set, go ahead and set it.
if self.language_merged is None:
language = self.language
# If we have no language set, try and set it to english.
# Also make a fuss because we should try to avoid this.
if self._language_merged is None:
try:
if _babase.do_once():
logging.warning(
'get_resource() called before language'
' set; falling back to english.'
)
self.setlanguage(
language, print_change=False, store_to_config=False
'English', print_change=False, store_to_config=False
)
except Exception:
from babase import _error
logging.exception('Error setting language to %s.', language)
# Try english as a fallback.
if language != 'English':
print('Resorting to fallback language (English)')
try:
self.setlanguage(
'English',
print_change=False,
store_to_config=False,
)
except Exception:
_error.print_exception(
'error setting language to english fallback'
)
logging.exception(
'Error setting fallback english language.'
)
raise
# If they provided a fallback_resource value, try the
# target-language-only dict first and then fall back to trying the
# fallback_resource value in the merged dict.
# target-language-only dict first and then fall back to
# trying the fallback_resource value in the merged dict.
if fallback_resource is not None:
try:
values = self.language_target
values = self._language_target
splits = resource.split('.')
dicts = splits[:-1]
key = splits[-1]
@ -336,11 +266,11 @@ class LanguageSubsystem:
val = values[key]
return val
except Exception:
# FIXME: Shouldn't we try the fallback resource in the
# merged dict AFTER we try the main resource in the
# merged dict?
# FIXME: Shouldn't we try the fallback resource in
# the merged dict AFTER we try the main resource in
# the merged dict?
try:
values = self.language_merged
values = self._language_merged
splits = fallback_resource.split('.')
dicts = splits[:-1]
key = splits[-1]
@ -352,14 +282,15 @@ class LanguageSubsystem:
return val
except Exception:
# If we got nothing for fallback_resource, default
# to the normal code which checks or primary
# value in the merge dict; there's a chance we can
# get an english value for it (which we weren't
# looking for the first time through).
# If we got nothing for fallback_resource,
# default to the normal code which checks or
# primary value in the merge dict; there's a
# chance we can get an english value for it
# (which we weren't looking for the first time
# through).
pass
values = self.language_merged
values = self._language_merged
splits = resource.split('.')
dicts = splits[:-1]
key = splits[-1]
@ -371,9 +302,9 @@ class LanguageSubsystem:
return val
except Exception:
# Ok, looks like we couldn't find our main or fallback resource
# anywhere. Now if we've been given a fallback value, return it;
# otherwise fail.
# Ok, looks like we couldn't find our main or fallback
# resource anywhere. Now if we've been given a fallback
# value, return it; otherwise fail.
from babase import _error
if fallback_value is not None:
@ -426,18 +357,93 @@ class LanguageSubsystem:
raise ValueError('Invalid Input; must be length 1')
return 0xE000 <= ord(char) <= 0xF8FF
def _can_display_language(self, language: str) -> bool:
"""Tell whether we can display a particular language.
On some platforms we don't have unicode rendering yet which
limits the languages we can draw.
"""
# We don't yet support full unicode display on windows or linux :-(.
if (
language
in {
'Chinese',
'ChineseTraditional',
'Persian',
'Korean',
'Arabic',
'Hindi',
'Vietnamese',
'Thai',
'Tamil',
}
and not _babase.can_display_full_unicode()
):
return False
return True
def _get_default_language(self) -> str:
languages = {
'ar': 'Arabic',
'be': 'Belarussian',
'zh': 'Chinese',
'hr': 'Croatian',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'eo': 'Esperanto',
'fil': 'Filipino',
'fr': 'French',
'de': 'German',
'el': 'Greek',
'hi': 'Hindi',
'hu': 'Hungarian',
'id': 'Indonesian',
'it': 'Italian',
'ko': 'Korean',
'ms': 'Malay',
'fa': 'Persian',
'pl': 'Polish',
'pt': 'Portuguese',
'ro': 'Romanian',
'ru': 'Russian',
'sr': 'Serbian',
'es': 'Spanish',
'sk': 'Slovak',
'sv': 'Swedish',
'ta': 'Tamil',
'th': 'Thai',
'tr': 'Turkish',
'uk': 'Ukrainian',
'vec': 'Venetian',
'vi': 'Vietnamese',
}
# Special case for Chinese: map specific variations to
# traditional. (otherwise will map to 'Chinese' which is
# simplified)
if self.locale in ('zh_HANT', 'zh_TW'):
language = 'ChineseTraditional'
else:
language = languages.get(self.locale[:2], 'English')
if not self._can_display_language(language):
language = 'English'
return language
class Lstr:
"""Used to define strings in a language-independent way.
Category: **General Utility Classes**
These should be used whenever possible in place of hard-coded strings
so that in-game or UI elements show up correctly on all clients in their
currently-active language.
These should be used whenever possible in place of hard-coded
strings so that in-game or UI elements show up correctly on all
clients in their currently-active language.
To see available resource keys, look at any of the bs_language_*.py files
in the game or the translations pages at legacy.ballistica.net/translate.
To see available resource keys, look at any of the bs_language_*.py
files in the game or the translations pages at
legacy.ballistica.net/translate.
##### Examples
EXAMPLE 1: specify a string from a resource path
@ -573,10 +579,10 @@ class Lstr:
def is_flat_value(self) -> bool:
"""Return whether the Lstr is a 'flat' value.
This is defined as a simple string value incorporating no translations,
resources, or substitutions. In this case it may be reasonable to
replace it with a raw string value, perform string manipulation on it,
etc.
This is defined as a simple string value incorporating no
translations, resources, or substitutions. In this case it may
be reasonable to replace it with a raw string value, perform
string manipulation on it, etc.
"""
return bool('v' in self.args and not self.args.get('s', []))

View File

@ -28,7 +28,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21143
TARGET_BALLISTICA_BUILD = 21147
TARGET_BALLISTICA_VERSION = '1.7.21'
_g_env_config: EnvConfig | None = None

View File

@ -176,10 +176,9 @@ void BaseFeatureSet::StartApp() {
LogVersionInfo();
g_core->LifecycleLog("will read config");
// Read the app config.
g_base->python->ReadConfig();
// Read in ba.app.config for anyone who wants to start looking at it
// (though we don't explicitly ask anyone to apply it until later).
python->ReadConfig();
// Allow our subsystems to start doing work in their own threads and
// communicating with other subsystems. Note that we may still want to run
@ -188,12 +187,8 @@ void BaseFeatureSet::StartApp() {
// devices with the logic thread before the logic thread applies the
// current config to them).
g_core->LifecycleLog("will call python on-main-thread");
python->OnMainThreadStartApp();
g_core->LifecycleLog("will call logic on-main-thread");
logic->OnMainThreadStartApp();
g_core->LifecycleLog("will call graphics-server on-main-thread");
graphics_server->OnMainThreadStartApp();
if (bg_dynamics_server) {
bg_dynamics_server->OnMainThreadStartApp();
@ -209,10 +204,14 @@ void BaseFeatureSet::StartApp() {
// if called early.
app_running_ = true;
// As the last step of this phase, tell the logic thread to apply
// the app config which will kick off screen creation and otherwise
// get the ball rolling.
logic->event_loop()->PushCall([this] { logic->ApplyAppConfig(); });
// As the last step of this phase, tell the logic thread to apply the app
// config which will kick off screen creation and otherwise get the ball
// rolling.
{
Python::ScopedInterpreterLock gil;
python->objs().Get(BasePython::ObjID::kPushApplyAppConfigCall).Call();
}
g_core->LifecycleLog("start-app end (main thread)");
}
@ -252,11 +251,6 @@ void BaseFeatureSet::set_app_mode(AppMode* mode) {
app_mode_->OnActivate();
// Since app-modes will mostly become active after the initial global
// apply-app-config happens, we need to tell them to do so explicitly when
// they spin up.
app_mode_->DoApplyAppConfig();
// Let some stuff know.
logic->OnAppModeChanged();
} catch (const Exception& exc) {

View File

@ -1111,6 +1111,11 @@ void Graphics::BuildAndPushFrameDef() {
assert(g_base->InLogicThread());
assert(camera_.Exists());
// Keep track of when we're in here; can be useful for making sure stuff
// doesn't muck with our lists/etc. while we're using them.
assert(!building_frame_def_);
building_frame_def_ = true;
// We should not be building/pushing any frames until after
// app-launch-commands have been run.
BA_PRECONDITION_FATAL(g_base->logic->app_bootstrapping_complete());
@ -1234,6 +1239,9 @@ void Graphics::BuildAndPushFrameDef() {
blotch_soft_verts_.clear();
blotch_soft_obj_indices_.clear();
blotch_soft_obj_verts_.clear();
assert(building_frame_def_);
building_frame_def_ = false;
}
void Graphics::DrawBoxingGlovesTest(FrameDef* frame_def) {
@ -1541,7 +1549,6 @@ void Graphics::SetSupportsHighQualityGraphics(bool s) {
void Graphics::ClearScreenMessageTranslations() {
assert(g_base && g_base->InLogicThread());
for (auto&& i : screen_messages_) {
i.translation_dirty = true;
}
@ -2017,6 +2024,10 @@ auto Graphics::ReflectionTypeFromString(const std::string& s)
void Graphics::LanguageChanged() {
assert(g_base && g_base->InLogicThread());
if (building_frame_def_) {
Log(LogLevel::kWarning,
"Graphics::LanguageChanged() called during draw; should not happen.");
}
// Also clear translations on all screen-messages.
ClearScreenMessageTranslations();
}

View File

@ -432,6 +432,7 @@ class Graphics {
int64_t frame_def_count_{1};
bool gyro_enabled_{true};
millisecs_t last_suppress_gyro_time_{};
int building_frame_def_{};
};
} // namespace ballistica::base

View File

@ -25,12 +25,9 @@ Logic::Logic() : display_timers_(new TimerList()) {
}
void Logic::OnMainThreadStartApp() {
g_core->LifecycleLog("will create logic loop");
event_loop_ = new EventLoop(EventLoopID::kLogic);
g_core->pausable_event_loops.push_back(event_loop_);
g_core->LifecycleLog("will push logic on-app-start");
// Sit and wait for our logic thread to run its startup stuff.
event_loop_->PushCallSynchronous([this] { OnAppStart(); });
}
@ -144,9 +141,8 @@ void Logic::OnAppShutdown() {
[] { g_base->app->LogicThreadShutdownComplete(); });
}
void Logic::ApplyAppConfig() {
void Logic::DoApplyAppConfig() {
assert(g_base->InLogicThread());
g_core->LifecycleLog("apply-app-config");
// Give all our other subsystems a chance.
// Note: keep these in the same order as OnAppStart.

View File

@ -33,7 +33,7 @@ class Logic {
void OnAppModeChanged();
void ApplyAppConfig();
void DoApplyAppConfig();
void OnScreenSizeChange(float virtual_width, float virtual_height,
float pixel_width, float pixel_height);

View File

@ -103,6 +103,7 @@ class BasePython {
kOpenURLWithWebBrowserModuleCall,
kOnNativeModuleImportCall,
kSetupEnvForAppRunCall,
kPushApplyAppConfigCall,
kLast // Sentinel; must be at end.
};

View File

@ -552,24 +552,22 @@ static PyMethodDef PyQuitDef = {
// ----------------------------- apply_config ----------------------------------
static auto PyApplyConfig(PyObject* self, PyObject* args) -> PyObject* {
static auto PyDoApplyAppConfig(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_TRY;
// Hmm; Python runs in the logic thread; technically we could just run
// ApplyAppConfig() immediately (though pushing is probably safer).
g_base->logic->event_loop()->PushCall(
[] { g_base->logic->ApplyAppConfig(); });
BA_PRECONDITION(g_base->InLogicThread());
g_base->logic->DoApplyAppConfig();
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyApplyConfigDef = {
"apply_config", // name
PyApplyConfig, // method
METH_VARARGS, // flags
static PyMethodDef PyDoApplyAppConfigDef = {
"do_apply_app_config", // name
PyDoApplyAppConfig, // method
METH_VARARGS, // flags
"apply_config() -> None\n"
"do_apply_app_config() -> None\n"
"\n"
"(internal)",
};
@ -1468,7 +1466,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
PyEnvDef,
PyPreEnvDef,
PyCommitConfigDef,
PyApplyConfigDef,
PyDoApplyAppConfigDef,
PyQuitDef,
PyAppTimerDef,
PyAppTimeDef,

View File

@ -1170,6 +1170,7 @@ static auto PySetInternalLanguageKeys(PyObject* self, PyObject* args)
BA_PRECONDITION(PyList_Check(random_names_list_obj));
std::unordered_map<std::string, std::string> language;
int size = static_cast<int>(PyList_GET_SIZE(list_obj));
for (int i = 0; i < size; i++) {
PyObject* entry = PyList_GET_ITEM(list_obj, i);
if (!PyTuple_Check(entry) || PyTuple_GET_SIZE(entry) != 2
@ -1180,6 +1181,7 @@ static auto PySetInternalLanguageKeys(PyObject* self, PyObject* args)
language[PyUnicode_AsUTF8(PyTuple_GET_ITEM(entry, 0))] =
PyUnicode_AsUTF8(PyTuple_GET_ITEM(entry, 1));
}
size = static_cast<int>(PyList_GET_SIZE(random_names_list_obj));
std::list<std::string> random_names;
for (int i = 0; i < size; i++) {
@ -1189,6 +1191,7 @@ static auto PySetInternalLanguageKeys(PyObject* self, PyObject* args)
}
random_names.emplace_back(PyUnicode_AsUTF8(entry));
}
Utils::SetRandomNameList(random_names);
assert(g_base->logic);
g_base->assets->SetLanguageKeys(language);

View File

@ -27,7 +27,7 @@ void CorePython::InitPython() {
// Pre-config as isolated if we include our own Python and as standard
// otherwise.
PyPreConfig preconfig;
PyPreConfig preconfig{};
if (g_buildconfig.contains_python_dist()) {
PyPreConfig_InitIsolatedConfig(&preconfig);
} else {
@ -44,7 +44,7 @@ void CorePython::InitPython() {
// Configure as isolated if we include our own Python and as standard
// otherwise.
PyConfig config;
PyConfig config{};
if (g_buildconfig.contains_python_dist()) {
PyConfig_InitIsolatedConfig(&config);
// We manage paths 100% ourself in this case and don't want any site
@ -113,6 +113,7 @@ void CorePython::InitPython() {
// Init Python.
status = Py_InitializeFromConfig(&config);
BA_PRECONDITION_FATAL(!PyStatus_Exception(status));
PyConfig_Clear(&config);
}
void CorePython::EnablePythonLoggingCalls() {

View File

@ -77,7 +77,14 @@ bool SceneV1AppMode::InMainMenu() const {
static SceneV1AppMode* g_scene_v1_app_mode{};
void SceneV1AppMode::OnActivate() { Reset(); }
void SceneV1AppMode::OnActivate() {
Reset();
// To set initial states, explicitly fire some of our 'On-Foo-Changed'
// callbacks.
DoApplyAppConfig();
LanguageChanged();
}
void SceneV1AppMode::OnAppStart() { assert(g_base->InLogicThread()); }
@ -1197,6 +1204,7 @@ void SceneV1AppMode::PruneSessions() {
}
void SceneV1AppMode::LanguageChanged() {
assert(g_base && g_base->InLogicThread());
if (Session* session = GetForegroundSession()) {
session->LanguageChanged();
}

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 = 21143;
const int kEngineBuildNumber = 21147;
const char* kEngineVersion = "1.7.21";
auto MonolithicMain(const core::CoreConfig& core_config) -> int {

View File

@ -76,16 +76,9 @@ EventLoop::EventLoop(EventLoopID identifier_in, ThreadSource source)
// Block until the thread is bootstrapped.
// (maybe not necessary, but let's be cautious in case we'd
// try to use things like thread_id before they're known).
if (identifier_ == EventLoopID::kLogic) {
g_core->LifecycleLog("logic thread bootstrap wait begin");
}
std::unique_lock lock(client_listener_mutex_);
client_listener_cv_.wait(lock, [this] { return bootstrapped_; });
if (identifier_ == EventLoopID::kLogic) {
g_core->LifecycleLog("logic thread bootstrap wait end");
}
break;
}
case ThreadSource::kWrapMain: {
@ -512,7 +505,7 @@ void EventLoop::PushThreadMessage(const ThreadMessage& t) {
// So tally up any logs and send them after.
std::vector<std::pair<LogLevel, std::string>> log_entries;
{
std::unique_lock<std::mutex> lock(thread_message_mutex_);
std::unique_lock lock(thread_message_mutex_);
// Plop the data on to the list; we're assuming the mutex is locked.
thread_messages_.push_back(t);
@ -742,11 +735,11 @@ auto EventLoop::CheckPushSafety() -> bool {
}
}
auto EventLoop::CheckPushRunnableSafety() -> bool {
std::scoped_lock lock(client_listener_mutex_);
std::unique_lock lock(thread_message_mutex_);
// We first complain when we get to 1000 queued messages so
// let's consider things unsafe when we're halfway there.
return (thread_messages_.size() < kThreadMessageSafetyThreshold);
return thread_messages_.size() < kThreadMessageSafetyThreshold;
}
} // namespace ballistica

View File

@ -12,4 +12,5 @@ values = [
babase.app.handle_deep_link, # kDeepLinkCall
babase.app.lang.get_resource, # kGetResourceCall
babase.app.lang.translate, # kTranslateCall
babase.app.push_apply_app_config, # kPushApplyAppConfigCall
]

View File

@ -18,7 +18,7 @@ if TYPE_CHECKING:
# Python version we build here (not necessarily same as we use in repo).
PY_VER_ANDROID = '3.11'
PY_VER_EXACT_ANDROID = '3.11.3'
PY_VER_EXACT_ANDROID = '3.11.4'
PY_VER_APPLE = '3.11'
PY_VER_EXACT_APPLE = '3.11.3'