lots of work on logging, langs, and cloud subscriptions

This commit is contained in:
Eric 2024-11-01 18:37:17 -07:00
parent 4a5976d3ce
commit 402dfc66c5
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
31 changed files with 556 additions and 158 deletions

137
.efrocachemap generated
View File

@ -421,43 +421,44 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "84353324570add5ea6698d8a7ddd99be",
"build/assets/ba_data/data/langdata.json": "1f4ee8b8b810e7b644291f775cb06bf0",
"build/assets/ba_data/data/languages/arabic.json": "609f5d698a488e40e61787b62ee8ea5e",
"build/assets/ba_data/data/languages/belarussian.json": "3d5523d0004293aa2df02f3f6f3b84f8",
"build/assets/ba_data/data/languages/chinese.json": "57d199cfd2a5cf493e777dd96cc12f7c",
"build/assets/ba_data/data/languages/chinesetraditional.json": "d85c58cc1e0e4bd0b09b2bc768cb1971",
"build/assets/ba_data/data/languages/croatian.json": "b23619cb396ac16640c47458f884b16a",
"build/assets/ba_data/data/languages/czech.json": "be5d536a1160607dfa158e59ecc1c324",
"build/assets/ba_data/data/languages/czech.json": "7f123919752ed1e9de5bd06b46fa811e",
"build/assets/ba_data/data/languages/danish.json": "8e57db30c5250df2abff14a822f83ea7",
"build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343",
"build/assets/ba_data/data/languages/english.json": "5a73dea22df1117d58a79459def62ff5",
"build/assets/ba_data/data/languages/dutch.json": "734357560f53b4820221f6d60a0b79e8",
"build/assets/ba_data/data/languages/english.json": "a13015c5fea152cf84f5988e5cab9298",
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
"build/assets/ba_data/data/languages/filipino.json": "30f9622136067fe866bebf7e81ee8546",
"build/assets/ba_data/data/languages/french.json": "69578cc38349367912659a62ace5a42d",
"build/assets/ba_data/data/languages/french.json": "e0bf81cff0497dd84044442606cc878e",
"build/assets/ba_data/data/languages/german.json": "c4b8c4d3c078b7902155af3221cf9cf4",
"build/assets/ba_data/data/languages/gibberish.json": "d6810f99fc9055b5203c382a83bc5128",
"build/assets/ba_data/data/languages/gibberish.json": "48bd2b7f70bdb76ac217c27c06f7a294",
"build/assets/ba_data/data/languages/greek.json": "d28d1092fbb00ed857cbd53124c0dc78",
"build/assets/ba_data/data/languages/hindi.json": "54cd56bade6922b40989a8ac5e0c17f6",
"build/assets/ba_data/data/languages/hindi.json": "5f60453c7dd3853c95c6f822e92d5300",
"build/assets/ba_data/data/languages/hungarian.json": "9d88004a98f0fbe2ea72edd5e0b3002e",
"build/assets/ba_data/data/languages/indonesian.json": "2ccb3fe081ead7706dbebb1008a8bc4e",
"build/assets/ba_data/data/languages/italian.json": "d9eb41f6eafb19040f8d5c0608790b62",
"build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597",
"build/assets/ba_data/data/languages/malay.json": "f6ce0426d03a62612e3e436ed5d1be1f",
"build/assets/ba_data/data/languages/persian.json": "fc25780341e0dfebc393e4c1c846b7a9",
"build/assets/ba_data/data/languages/piratespeak.json": "da60ddd83706b0e9e61c7ef9b6e7c975",
"build/assets/ba_data/data/languages/polish.json": "89333fb207f9eb2f22fff5a95b022c35",
"build/assets/ba_data/data/languages/portuguese.json": "eb2563e245e1ea00b870264dced3ebd7",
"build/assets/ba_data/data/languages/romanian.json": "55a8744e466801013ea131266a856924",
"build/assets/ba_data/data/languages/portuguese.json": "ac198f63b4af6e1f25044e92b953b96e",
"build/assets/ba_data/data/languages/romanian.json": "5ae206fe0b71c4015b02b86da8931c8f",
"build/assets/ba_data/data/languages/russian.json": "0fcc60bf1e8e19a74f02b0798728ec68",
"build/assets/ba_data/data/languages/serbian.json": "623fa4129a1154c2f32ed7867e56ff6a",
"build/assets/ba_data/data/languages/slovak.json": "3c08c748c96c71bd9e1d7291fb8817b6",
"build/assets/ba_data/data/languages/spanish.json": "0a37387183a6634fc8e9ac225fcf20b1",
"build/assets/ba_data/data/languages/spanish.json": "e7f59cd89c0ebe2b7cd4c116f4d0e639",
"build/assets/ba_data/data/languages/swedish.json": "3b179e7333183c70adb0811246b09959",
"build/assets/ba_data/data/languages/tamil.json": "ead39b864228696a9b0d19344bc4b5ec",
"build/assets/ba_data/data/languages/thai.json": "1d665629361f302693dead39de8fa945",
"build/assets/ba_data/data/languages/turkish.json": "6153ca5248b8e4743e9501ac72378493",
"build/assets/ba_data/data/languages/ukrainian.json": "3a5b8132690fcd583d280879876c85b7",
"build/assets/ba_data/data/languages/venetian.json": "a1315f5233ebbee1464683ac55d5d9d5",
"build/assets/ba_data/data/languages/vietnamese.json": "5ae84265600b6cfda45c9bed18724e1d",
"build/assets/ba_data/data/languages/vietnamese.json": "34a8b75acba2c0234e0b00fb4ef7d011",
"build/assets/ba_data/data/maps/big_g.json": "1dd301d490643088a435ce75df971054",
"build/assets/ba_data/data/maps/bridgit.json": "6aea74805f4880cc11237c5734a24422",
"build/assets/ba_data/data/maps/courtyard.json": "4b836554c8949bcd2ae382f5e3c1a9cc",
@ -945,17 +946,17 @@
"build/assets/ba_data/meshes/zoeTorso.bob": "26a1007e98902178d8c62fd7069d5da5",
"build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a",
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "8133ab2f7828219b186d4cecb2d5443b",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "611f53e8096b704efa4e0caa4c5dcd7c",
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "072b2f0da8254144432a91d068fa6fb1",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "131628a15d2001d10cac7c73d001c3c2",
"build/assets/ba_data/python-site-packages/certifi/core.py": "c1b8c102093ea26587619677c7ec6016",
"build/assets/ba_data/python-site-packages/typing_extensions.py": "1f6b4db70adb7ca05dff2b74f6cde8aa",
"build/assets/ba_data/python-site-packages/urllib3/__init__.py": "06cffcf88c8024218069f628c9938c50",
"build/assets/ba_data/python-site-packages/urllib3/_base_connection.py": "4404e529dbd3db128d9a2e60c6ed9243",
"build/assets/ba_data/python-site-packages/urllib3/_collections.py": "14963d7d43c0e51e777851c0e2868928",
"build/assets/ba_data/python-site-packages/urllib3/_request_methods.py": "87d6a7a77db1324e81d02f919c134f1a",
"build/assets/ba_data/python-site-packages/urllib3/_version.py": "46e3fbaaf7d02c2e55fcecc98deb5af8",
"build/assets/ba_data/python-site-packages/urllib3/connection.py": "3b49efceb61dfab0587286686e0e5ada",
"build/assets/ba_data/python-site-packages/urllib3/_request_methods.py": "ee22bc685aec965a9cbc8fd51097758b",
"build/assets/ba_data/python-site-packages/urllib3/_version.py": "eb50943fd218eb58da9cc08cdc3d97d9",
"build/assets/ba_data/python-site-packages/urllib3/connection.py": "4afbb583ae2aff33f1da0d0a27a5eb21",
"build/assets/ba_data/python-site-packages/urllib3/connectionpool.py": "e891fe6cdff0c03a3b670e225c0c4d88",
"build/assets/ba_data/python-site-packages/urllib3/contrib/__init__.py": "340c83beff7dcff8f5c7b87cd43cedaf",
"build/assets/ba_data/python-site-packages/urllib3/contrib/emscripten/__init__.py": "33531b60d1ff8b9073567240f2a1745f",
@ -963,23 +964,25 @@
"build/assets/ba_data/python-site-packages/urllib3/contrib/emscripten/fetch.py": "be8618e1c9a004108bf9f82f706503d7",
"build/assets/ba_data/python-site-packages/urllib3/contrib/emscripten/request.py": "da01c66ef924f2a2875d46adb87d7507",
"build/assets/ba_data/python-site-packages/urllib3/contrib/emscripten/response.py": "11208e765d5e9a1d481ded597e58c7d3",
"build/assets/ba_data/python-site-packages/urllib3/contrib/pyopenssl.py": "7a14ef1c58c55511581043ed25aebba3",
"build/assets/ba_data/python-site-packages/urllib3/contrib/pyopenssl.py": "fc0e3d0b92a7866fdd3dd242eee78713",
"build/assets/ba_data/python-site-packages/urllib3/contrib/socks.py": "bd5fed33c678f750ad9d1c754a26faf0",
"build/assets/ba_data/python-site-packages/urllib3/exceptions.py": "c346a13d762dcdff2f9cccc1d06c92d6",
"build/assets/ba_data/python-site-packages/urllib3/fields.py": "e24ef9e64962ca25322c0216cc4bc923",
"build/assets/ba_data/python-site-packages/urllib3/filepost.py": "d0a96fd7614fcaa368b26d8a769ff848",
"build/assets/ba_data/python-site-packages/urllib3/http2.py": "c307bd4c486d10070770c320145eb33c",
"build/assets/ba_data/python-site-packages/urllib3/http2/__init__.py": "e2b631c71eba41cadcbd71097df87d0b",
"build/assets/ba_data/python-site-packages/urllib3/http2/connection.py": "98ec5901ae0a7ab8d54cb298f3797ea7",
"build/assets/ba_data/python-site-packages/urllib3/http2/probe.py": "24a017e7e59ca2060a4b7af53c15723a",
"build/assets/ba_data/python-site-packages/urllib3/poolmanager.py": "6dd72a45419efb9a2ab4e58c527d84d5",
"build/assets/ba_data/python-site-packages/urllib3/response.py": "f9f74417b5c2b4e5812b473435e3f455",
"build/assets/ba_data/python-site-packages/urllib3/util/__init__.py": "3ef2c56aa3ccfc25f466dc767f191b2c",
"build/assets/ba_data/python-site-packages/urllib3/util/connection.py": "888aa8c2f0a4a76749e6c3fd0df597e2",
"build/assets/ba_data/python-site-packages/urllib3/util/connection.py": "373bae67383b8abf80d88c0d4e26d2fe",
"build/assets/ba_data/python-site-packages/urllib3/util/proxy.py": "2de685261596886eb8e2655e1af9ce7b",
"build/assets/ba_data/python-site-packages/urllib3/util/request.py": "a1fb665c16fa443eef15db73c5e29917",
"build/assets/ba_data/python-site-packages/urllib3/util/request.py": "72389227066178a97711ead0d25a0868",
"build/assets/ba_data/python-site-packages/urllib3/util/response.py": "e6a942417aa97215e358ae97b53bafe6",
"build/assets/ba_data/python-site-packages/urllib3/util/retry.py": "4eeffe54c7d400c4af731f02ef3fb074",
"build/assets/ba_data/python-site-packages/urllib3/util/ssl_.py": "c1b929bdfba831479f4b2d1538954536",
"build/assets/ba_data/python-site-packages/urllib3/util/ssl_.py": "6105f661daa3e837e9ff8fdf06b2037a",
"build/assets/ba_data/python-site-packages/urllib3/util/ssl_match_hostname.py": "cbb28520c901282629d47375af2dd717",
"build/assets/ba_data/python-site-packages/urllib3/util/ssltransport.py": "0a51cd95ce75673b6c1117cb22da18b1",
"build/assets/ba_data/python-site-packages/urllib3/util/ssltransport.py": "77fa0b9225a7d6033f1413687f575a96",
"build/assets/ba_data/python-site-packages/urllib3/util/timeout.py": "e3bc037067fd6aaed823955be6f1792d",
"build/assets/ba_data/python-site-packages/urllib3/util/url.py": "6a37bafe6598aecba9e034be2085f583",
"build/assets/ba_data/python-site-packages/urllib3/util/util.py": "95e6d2fa1b0f310a991612421f1a29a1",
@ -4096,53 +4099,53 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "16c5eddc745dc4a601cb2ee364b71e31",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "51a65b326094cf210be9d7d085e57c2b",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "96e368ec6da34e00222328f3e2821320",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "b7a33145dfe3f18adf42133a0843be2d",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e7642737ca3a0ff3f034a073e657ef42",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "376c2361f94219726a082b745f500db7",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "339b5cc93d9db484800f488cf1b2f4b9",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "cf9527c43d75f7a51f483e17a59eab82",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "758b91a1374bfbd8489b2cc68ec18bd2",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "33d824f0b6f30446167636ad68e9a4ae",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "7203b89f81d3315822156e0041429aef",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "0d4048eccd45dbf7a6269722def6accd",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "06481d98907f976a3f9ee0273ceaff38",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "db76906a502c58fedb79ebe9237cd8ec",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "91ce9cf92332763823df13fec765da78",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "a8e9aadab42b687abd5c3c299f3373e4",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "a354c943a42e737044029f746df3e74b",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "7936c43cf14fa0912c9261d03d478a91",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "0d82db33672ec85d7e720e9233b22e84",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d041406d19983269b8ba5e576186521d",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "47cd40a453b5e7c8031c36afe51cfc74",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "61b8d712130f831f049179bf25c96b86",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "47cd40a453b5e7c8031c36afe51cfc74",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "61b8d712130f831f049179bf25c96b86",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "a26331b58f4511138f90106ce28a595e",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "3292f6eaed1c1715754b15cf9dac3108",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "a26331b58f4511138f90106ce28a595e",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "3292f6eaed1c1715754b15cf9dac3108",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "b89d6a533de222a7cd988d575ffb0b65",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "d4a9e505da7243d9418d99805ccd0550",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "b89d6a533de222a7cd988d575ffb0b65",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "d4a9e505da7243d9418d99805ccd0550",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "c551a02dc318a7f665a727f88cf2b1c1",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "8911877eeeabd36033f4552c84d18f96",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "7cc7fd84cf143a1e4e1429ef7cb8bf18",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "8911877eeeabd36033f4552c84d18f96",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "c48af47c5fbbb085a65d00598050d30d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "03fd14ef8f7baf3d25612a9d31792f4b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "5aea1501b99692a6675f7566944f4523",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "a3198455822b3576a17e0e57bf79e9ee",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "d18789c1c44f7bc9d9c808385df18555",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "8de2be3f0402065db2a75708d1ba08af",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "591e71334f4da572cfdae7c603e25f55",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "87461e54837ca42f9e45dc0926746133",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "ab2a763986c41b05e108609e2245bc88",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "22354f5977eecb7898e8fed6a15a3471",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "5f42e62b736e12db3418740a66eaaaa6",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "3985a5b97d65f3069e78e2b864270973",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "31c224d17503059828870a65e8bc6983",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "ff368944b4df967e9ae9adca0ba2ecb6",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "2eb53cf0c1469f2de823fc37ed66e947",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "b1e608f6a95595309fcb3db40763fdc3",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "be64c41aecd2f18efc6b34c98e3c340f",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "701213f2480fcc86aabdf954d6499f42",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "c909d72602b5296d1d10d292547cf4f2",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6ee608e0c722de648614a6d9453fa8ef",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4564cff8a6abc34c046726c4a2f83fa1",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "0bc4cd868fd813d6a9f442f2dd38242a",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "b4ef832c06699a5b505d005057c15a18",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "d1be84a36ac1de882eeaf704e5dd4490",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9daa986905e50270f19135279d040d90",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "a51416a1fc183a310012472a717fbb96",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a23c0971f8b9549c7a709d72447fd47c",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "e2891d1c10f73a875e1c5efcf3006121",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "8c667cd77a82124b48c50630b2dd4aed",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "7e6824b45b74266c09823109b5a7069f",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "8c667cd77a82124b48c50630b2dd4aed",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "7e6824b45b74266c09823109b5a7069f",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "ee9800f3b72862f087ced2ef382d39f1",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "1e121312835e14cfecc7ee3d26f57439",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "ee9800f3b72862f087ced2ef382d39f1",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "1e121312835e14cfecc7ee3d26f57439",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "7b8ba069d9ca2edc257f6868fc9e9df9",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "a237f9e945d1a416be9aa913b5d60705",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "7b8ba069d9ca2edc257f6868fc9e9df9",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "a237f9e945d1a416be9aa913b5d60705",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "920f39fc5155d9c41b96ff01a88a5020",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "c39bcd7db4fd85f1b59855aeaf966070",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "a0abd47869e753575f06a4336659ca79",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "c39bcd7db4fd85f1b59855aeaf966070",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "e77911c9d4e0dd92bfff36a506abb54a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "558708ed8550ff325e3c40445e92fbf0",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "01222e9a53456ba1765779e2d43df195",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0e9441acd45a6e923963477c6efcc3bd",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "37e5cf12b015c65126ebe16ff55ac70f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "570acb3ca5c9e199e61ddaef41737aec",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1c6f9950c4426c881ddc80d9be42a3c3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "3fb42beee8520d8bab03535989dafa5c",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "794d258d59fd17a61752843a9a0551ad",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "efa61468cf098f77cc6a234461d8b86d",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "3a583e7e03bd4907b21adc3bf5729d15",
"src/ballistica/base/mgen/pyembed/binding_base_app.inc": "f0f9dc33ecd4ef7a384f131d62c96c97",
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "3ceb412513963f0818ab39c58bf292e3",
"src/ballistica/core/mgen/pyembed/binding_core.inc": "02bf828e423d0fced4d87aa74f25cbdc",

View File

@ -1,4 +1,7 @@
### 1.7.37 (build 22062, api 9, 2024-10-22)
### 1.7.37 (build 22068, api 9, 2024-11-01)
- I am pleased to announce that after years of hard work from many members of
the community, PirateSpeak is now complete and available as a language choice.
This changes everything.
- Bumping api version to 9. As you'll see below, there's some UI changes that
will require a bit of work for any UI mods to adapt to. If your mods don't
touch UI stuff at all you can simply bump your api version and call it a day.
@ -134,6 +137,10 @@
bg-dynamics message overflows.
- Added a close button to the dev-console as an alternate to using key presses
to close it.
- (build 22063) Added a 'Copy History' button in the Python tab in the
dev-console. Note that this will copy all cached log history; not just what is
displayed in the dev-console. This should be handy for diagnosing problems in
the future.
### 1.7.36 (build 21944, api 8, 2024-07-26)
- Wired up Tokens, BombSquad's new purchasable currency. The first thing these

View File

@ -2,14 +2,14 @@ cpplint==2.0.0
dmgbuild==1.6.2
filelock==3.16.1
furo==2024.8.6
mypy==1.12.1
mypy==1.13.0
pbxproj==4.2.1
pdoc==15.0.0
pur==7.3.2
pylint==3.3.1
pylsp-mypy==0.6.9
pytest==8.3.3
python-daemon==3.0.1
python-daemon==3.1.0
python-lsp-black==2.0.0
python-lsp-server==1.12.0
requests==2.32.3

View File

@ -443,6 +443,7 @@
"ba_data/data/languages/korean.json",
"ba_data/data/languages/malay.json",
"ba_data/data/languages/persian.json",
"ba_data/data/languages/piratespeak.json",
"ba_data/data/languages/polish.json",
"ba_data/data/languages/portuguese.json",
"ba_data/data/languages/romanian.json",
@ -964,7 +965,6 @@
"ba_data/python-site-packages/urllib3/__pycache__/exceptions.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/__pycache__/fields.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/__pycache__/filepost.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/__pycache__/http2.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/__pycache__/poolmanager.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/__pycache__/response.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/_base_connection.py",
@ -992,7 +992,12 @@
"ba_data/python-site-packages/urllib3/exceptions.py",
"ba_data/python-site-packages/urllib3/fields.py",
"ba_data/python-site-packages/urllib3/filepost.py",
"ba_data/python-site-packages/urllib3/http2.py",
"ba_data/python-site-packages/urllib3/http2/__init__.py",
"ba_data/python-site-packages/urllib3/http2/__pycache__/__init__.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/http2/__pycache__/connection.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/http2/__pycache__/probe.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/urllib3/http2/connection.py",
"ba_data/python-site-packages/urllib3/http2/probe.py",
"ba_data/python-site-packages/urllib3/poolmanager.py",
"ba_data/python-site-packages/urllib3/response.py",
"ba_data/python-site-packages/urllib3/util/__init__.py",

View File

@ -13,6 +13,7 @@
"ba_data/python/babase/__pycache__/_apputils.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_cloud.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_devconsoletabs.cpython-312.opt-1.pyc",
"ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc",
@ -42,6 +43,7 @@
"ba_data/python/babase/_apputils.py",
"ba_data/python/babase/_assetmanager.py",
"ba_data/python/babase/_asyncio.py",
"ba_data/python/babase/_cloud.py",
"ba_data/python/babase/_devconsole.py",
"ba_data/python/babase/_devconsoletabs.py",
"ba_data/python/babase/_emptyappmode.py",

View File

@ -174,6 +174,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/_apputils.py \
$(BUILD_DIR)/ba_data/python/babase/_assetmanager.py \
$(BUILD_DIR)/ba_data/python/babase/_asyncio.py \
$(BUILD_DIR)/ba_data/python/babase/_cloud.py \
$(BUILD_DIR)/ba_data/python/babase/_devconsole.py \
$(BUILD_DIR)/ba_data/python/babase/_devconsoletabs.py \
$(BUILD_DIR)/ba_data/python/babase/_emptyappmode.py \
@ -452,6 +453,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_apputils.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_assetmanager.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_asyncio.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_cloud.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_devconsole.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_devconsoletabs.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_emptyappmode.cpython-312.opt-1.pyc \
@ -2728,7 +2730,9 @@ SCRIPT_TARGETS_PY_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/exceptions.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/fields.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/filepost.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/connection.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/probe.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/poolmanager.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/response.py \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/util/__init__.py \
@ -2769,7 +2773,9 @@ SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/exceptions.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/fields.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/filepost.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/http2.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/__pycache__/connection.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/http2/__pycache__/probe.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/poolmanager.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/__pycache__/response.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/urllib3/util/__pycache__/__init__.cpython-312.opt-1.pyc \
@ -5160,6 +5166,7 @@ DATA_TARGETS = \
$(BUILD_DIR)/ba_data/data/languages/korean.json \
$(BUILD_DIR)/ba_data/data/languages/malay.json \
$(BUILD_DIR)/ba_data/data/languages/persian.json \
$(BUILD_DIR)/ba_data/data/languages/piratespeak.json \
$(BUILD_DIR)/ba_data/data/languages/polish.json \
$(BUILD_DIR)/ba_data/data/languages/portuguese.json \
$(BUILD_DIR)/ba_data/data/languages/romanian.json \

View File

@ -131,6 +131,7 @@ from babase._apputils import (
get_remote_app_name,
AppHealthMonitor,
)
from babase._cloud import CloudSubscription
from babase._devconsole import (
DevConsoleTab,
DevConsoleTabEntry,
@ -230,6 +231,7 @@ __all__ = [
'clipboard_get_text',
'clipboard_has_text',
'clipboard_is_supported',
'CloudSubscription',
'clipboard_set_text',
'commit_app_config',
'ContextCall',

View File

@ -0,0 +1,26 @@
# Released under the MIT License. See LICENSE for details.
#
"""Cloud related functionality."""
from __future__ import annotations
from typing import TYPE_CHECKING
import _babase
if TYPE_CHECKING:
pass
class CloudSubscription:
"""User handle to a subscription to some cloud data.
Do not instantiate these directly; use the subscribe methods
in *.app.plus.cloud to create them.
"""
def __init__(self, subscription_id: int) -> None:
self._subscription_id = subscription_id
def __del__(self) -> None:
if _babase.app.plus is not None:
_babase.app.plus.cloud.unsubscribe(self._subscription_id)

View File

@ -34,7 +34,22 @@ class DevConsoleTab:
h_anchor: Literal['left', 'center', 'right'] = 'center',
label_scale: float = 1.0,
corner_radius: float = 8.0,
style: Literal['normal', 'light'] = 'normal',
style: Literal[
'normal',
'bright',
'red',
'red_bright',
'purple',
'purple_bright',
'yellow',
'yellow_bright',
'blue',
'blue_bright',
'white',
'white_bright',
'black',
'black_bright',
] = 'normal',
disabled: bool = False,
) -> None:
"""Add a button to the tab being refreshed."""

View File

@ -57,7 +57,9 @@ class DevConsoleTabAppModes(DevConsoleTab):
label_scale=0.6,
call=partial(self._set_app_mode, mode),
style=(
'light' if isinstance(_babase.app._mode, mode) else 'normal'
'bright'
if isinstance(_babase.app._mode, mode)
else 'normal'
),
)
@ -110,7 +112,7 @@ class DevConsoleTabUI(DevConsoleTab):
# h_anchor='left',
label_scale=0.6,
call=self.toggle_ui_overlay,
style='light' if ui_overlay else 'normal',
style='bright' if ui_overlay else 'normal',
)
x = 300
self.text(
@ -132,7 +134,7 @@ class DevConsoleTabUI(DevConsoleTab):
label_scale=0.6,
call=partial(_babase.app.set_ui_scale, scale),
style=(
'light'
'bright'
if scale.name.lower() == _babase.get_ui_scale()
else 'normal'
),
@ -232,14 +234,20 @@ class Table(Generic[T]):
)
# Align everything to the bottom of the dev-console.
yoffs = -1.0 * (
tab.height
- (
rows_on_this_page * self._entry_height
+ margin_top
+ margin_bottom
#
# UPDATE: Nevermind; top feels better. Keeping this code around
# in case we ever want to make it an option though.
if bool(False):
yoffs = -1.0 * (
tab.height
- (
rows_on_this_page * self._entry_height
+ margin_top
+ margin_bottom
)
)
)
else:
yoffs = 0
# Keep our corners up to date for user use.
self.top_left = (center_to_left + xoffs, tab.height + yoffs)
@ -253,12 +261,14 @@ class Table(Generic[T]):
# Page left/right buttons.
tab.button(
'<',
pos=(center_to_left + xoffs, margin_bottom),
pos=(
center_to_left + xoffs,
yoffs + tab.height - margin_top - rows * self._entry_height,
),
size=(
self._margin_left_right,
rows_on_this_page * self._entry_height,
rows * self._entry_height,
),
# h_anchor='left',
call=partial(self._page_left, tab),
disabled=entry_offset == 0,
)
@ -269,13 +279,12 @@ class Table(Generic[T]):
+ xoffs
+ self._margin_left_right
+ columns_on_this_page * self._entry_width,
margin_bottom,
yoffs + tab.height - margin_top - rows * self._entry_height,
),
size=(
self._margin_left_right,
rows_on_this_page * self._entry_height,
rows * self._entry_height,
),
# h_anchor='left',
call=partial(self._page_right, tab),
disabled=(
entry_offset + entries_on_this_page >= len(self._entries)
@ -353,6 +362,7 @@ class DevConsoleTabLogging(DevConsoleTab):
self._table = Table(
title='Logging Levels',
entry_width=800,
entry_height=42,
debug_bounds=False,
entries=list[str](),
draw_entry_call=self._draw_entry,
@ -469,21 +479,22 @@ class DevConsoleTabLogging(DevConsoleTab):
logger = logging.getLogger(entry)
level = logger.level
index = 0
if entry != 'root' and level == logging.NOTSET:
# Show the level being inherited in NOTSET cases.
notsetlevelname = logging.getLevelName(logger.getEffectiveLevel())
if notsetlevelname == 'NOTSET':
notsetname = 'Not Set'
else:
notsetname = f'Not Set ({notsetlevelname.capitalize()})'
else:
notsetname = 'Not Set'
effectivelevel = logger.getEffectiveLevel()
# if entry != 'root' and level == logging.NOTSET:
# # Show the level being inherited in NOTSET cases.
# notsetlevelname = logging.getLevelName(logger.getEffectiveLevel())
# if notsetlevelname == 'NOTSET':
# notsetname = 'Not Set'
# else:
# notsetname = f'Not Set ({notsetlevelname.capitalize()})'
# else:
notsetname = 'Not Set'
tab.button(
notsetname,
pos=(x + width - bwidth * 6.5 + xoffs + 1.0, y + 5.0),
size=(bwidth * 1.5 - 2.0, height - 10),
size=(bwidth * 1.0 - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.NOTSET else 'normal',
style='white_bright' if level == logging.NOTSET else 'black',
call=partial(
self._set_entry_val, entry_index, entry, logging.NOTSET
),
@ -494,7 +505,12 @@ class DevConsoleTabLogging(DevConsoleTab):
pos=(x + width - bwidth * 5 + xoffs + 1.0, y + 5.0),
size=(bwidth - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.DEBUG else 'normal',
style=(
'blue_bright'
if level == logging.DEBUG
else 'blue' if effectivelevel <= logging.DEBUG else 'black'
),
# style='bright' if level == logging.DEBUG else 'normal',
call=partial(
self._set_entry_val, entry_index, entry, logging.DEBUG
),
@ -505,7 +521,12 @@ class DevConsoleTabLogging(DevConsoleTab):
pos=(x + width - bwidth * 4 + xoffs + 1.0, y + 5.0),
size=(bwidth - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.INFO else 'normal',
style=(
'white_bright'
if level == logging.INFO
else 'white' if effectivelevel <= logging.INFO else 'black'
),
# style='bright' if level == logging.INFO else 'normal',
call=partial(self._set_entry_val, entry_index, entry, logging.INFO),
)
index += 1
@ -514,7 +535,11 @@ class DevConsoleTabLogging(DevConsoleTab):
pos=(x + width - bwidth * 3 + xoffs + 1.0, y + 5.0),
size=(bwidth - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.WARNING else 'normal',
style=(
'yellow_bright'
if level == logging.WARNING
else 'yellow' if effectivelevel <= logging.WARNING else 'black'
),
call=partial(
self._set_entry_val, entry_index, entry, logging.WARNING
),
@ -525,7 +550,11 @@ class DevConsoleTabLogging(DevConsoleTab):
pos=(x + width - bwidth * 2 + xoffs + 1.0, y + 5.0),
size=(bwidth - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.ERROR else 'normal',
style=(
'red_bright'
if level == logging.ERROR
else 'red' if effectivelevel <= logging.ERROR else 'black'
),
call=partial(
self._set_entry_val, entry_index, entry, logging.ERROR
),
@ -536,7 +565,13 @@ class DevConsoleTabLogging(DevConsoleTab):
pos=(x + width - bwidth * 1 + xoffs + 1.0, y + 5.0),
size=(bwidth - 2.0, height - 10),
label_scale=btextscale,
style='light' if level == logging.CRITICAL else 'normal',
style=(
'purple_bright'
if level == logging.CRITICAL
else (
'purple' if effectivelevel <= logging.CRITICAL else 'black'
)
),
call=partial(
self._set_entry_val, entry_index, entry, logging.CRITICAL
),
@ -563,7 +598,7 @@ class DevConsoleTabTest(DevConsoleTab):
size=(100, 30),
h_anchor='left',
label_scale=0.6,
style='light',
style='bright',
)
self.text(
'TestText',

View File

@ -430,3 +430,40 @@ def unsupported_controller_message(name: str) -> None:
Lstr(resource='unsupportedControllerText', subs=[('${NAME}', name)]),
color=(1, 0, 0),
)
def copy_dev_console_history() -> None:
"""Copy log history from the dev console."""
import baenv
from babase._language import Lstr
if not _babase.clipboard_is_supported():
_babase.getsimplesound('error').play()
_babase.screenmessage(
'Clipboard not supported on this build.',
color=(1, 0, 0),
)
return
# This requires us to be running with a log-handler set up.
envconfig = baenv.get_config()
if envconfig.log_handler is None:
_babase.getsimplesound('error').play()
_babase.screenmessage(
'Not available; standard engine logging is not enabled.',
color=(1, 0, 0),
)
return
# Just dump everything in the log-handler's cache.
archive = envconfig.log_handler.get_cached()
lines: list[str] = []
stdnames = ('stdout', 'stderr')
for entry in archive.entries:
reltime = entry.time.timestamp() - envconfig.launch_time
level_ex = '' if entry.name in stdnames else f' {entry.level.name}'
lines.append(f'{reltime:.3f} {entry.name}{level_ex}: {entry.message}')
_babase.clipboard_set_text('\n'.join(lines))
_babase.screenmessage(Lstr(resource='copyConfirmText'), color=(0, 1, 0))
_babase.getsimplesound('gunCocking').play()

View File

@ -83,6 +83,8 @@ class LanguageSubsystem(AppSubsystem):
for i, name in enumerate(names):
if name == 'Chinesetraditional':
names[i] = 'ChineseTraditional'
elif name == 'Piratespeak':
names[i] = 'PirateSpeak'
except Exception:
from babase import _error

View File

@ -21,10 +21,10 @@ from babase import (
import _baclassic
if TYPE_CHECKING:
from typing import Callable
from typing import Callable, Any
from efro.call import CallbackRegistration
from babase import AppIntent, AccountV2Handle
from babase import AppIntent, AccountV2Handle, CloudSubscription
from bauiv1 import UIV1AppSubsystem, MainWindow, MainWindowState
@ -35,6 +35,7 @@ class ClassicAppMode(AppMode):
self._on_primary_account_changed_callback: (
CallbackRegistration | None
) = None
self._test_sub: CloudSubscription | None = None
@override
@classmethod
@ -154,8 +155,21 @@ class ClassicAppMode(AppMode):
) -> None:
"""Update subscriptions/etc. for a new primary account state."""
assert in_logic_thread()
del account # Unused.
# print('WOULD WIRE UP LISTENERS FOR ACCOUNT', account)
if bool(False):
assert app.plus is not None
if account is None:
self._test_sub = None
else:
with account:
self._test_sub = app.plus.cloud.subscribe(
self._on_sub_update
)
else:
self._test_sub = None
def _on_sub_update(self, val: Any) -> None:
print(f'GOT SUB UPDATE: {val}')
def _root_ui_menu_press(self) -> None:
from babase import push_back_press

View File

@ -53,7 +53,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 22062
TARGET_BALLISTICA_BUILD = 22068
TARGET_BALLISTICA_VERSION = '1.7.37'

View File

@ -174,10 +174,32 @@ class CloudSubsystem(babase.AppSubsystem):
'Cloud functionality is not present in this build.'
)
# def subscribe(
# self,
# on_response: Callable[[Any], None],
# ) -> CallbackRegistration:
def subscribe(
self, updatecall: Callable[[Any], None]
) -> babase.CloudSubscription:
"""Subscribe to some data."""
from bacommon.cloud import TestCloudSubscriptionRequest
return self._subscribe(TestCloudSubscriptionRequest(), updatecall)
def _subscribe(
self,
request: bacommon.cloud.CloudSubscriptionRequest,
updatecall: Callable[[Any], None],
) -> babase.CloudSubscription:
"""Subscribe to some cloud data."""
raise NotImplementedError(
'Cloud functionality is not present in this build.'
)
def unsubscribe(self, subscription_id: int) -> None:
"""Unsubscribe from some subscription.
Do not call this manually; it is called by CloudSubscription.
"""
raise NotImplementedError(
'Cloud functionality is not present in this build.'
)
def cloud_console_exec(code: str) -> None:

View File

@ -32,6 +32,7 @@ class CTFFlag(Flag):
activity: CaptureTheFlagGame
def __init__(self, team: Team):
assert team.flagmaterial is not None
super().__init__(
materials=[team.flagmaterial],

View File

@ -184,7 +184,7 @@ void AssetsServer::WriteReplayMessages() {
fclose(replay_out_file_);
replay_out_file_ = nullptr;
g_core->Log(LogName::kBaAudio, LogLevel::kError,
"error writing replay file: "
"Error writing replay file: "
+ g_core->platform->GetErrnoString());
return;
}
@ -197,7 +197,7 @@ void AssetsServer::WriteReplayMessages() {
fclose(replay_out_file_);
replay_out_file_ = nullptr;
g_core->Log(LogName::kBaAudio, LogLevel::kError,
"error writing replay file: "
"Error writing replay file: "
+ g_core->platform->GetErrnoString());
return;
}
@ -206,7 +206,7 @@ void AssetsServer::WriteReplayMessages() {
fclose(replay_out_file_);
replay_out_file_ = nullptr;
g_core->Log(LogName::kBaAudio, LogLevel::kError,
"error writing replay file: "
"Error writing replay file: "
+ g_core->platform->GetErrnoString());
return;
}
@ -220,7 +220,7 @@ void AssetsServer::WriteReplayMessages() {
replay_out_file_ = nullptr;
g_core->Log(
LogName::kBaAudio, LogLevel::kError,
"error writing replay file: " + g_core->platform->GetErrnoString());
"Error writing replay file: " + g_core->platform->GetErrnoString());
return;
}
replay_bytes_written_ += data_compressed.size() + 2;
@ -240,11 +240,6 @@ void AssetsServer::Process() {
if (!g_base->graphics->has_client_context()) {
return;
}
// if (!g_base->assets ||
// || !g_base->graphics->texture_compression_types_are_set() // NOLINT
// || !g_base->graphics_server->texture_quality_set()) {
// return;
// }
// Process exactly 1 preload item. Empty out our non-audio list first
// (audio is less likely to cause noticeable hitches if it needs to be loaded

View File

@ -7,7 +7,7 @@
#include <vector>
#include "ballistica/base/assets/asset.h"
#include "ballistica/base/audio/al_sys.h"
#include "ballistica/base/audio/al_sys.h" // IWYU pragma: keep.
namespace ballistica::base {

View File

@ -3,10 +3,6 @@
#ifndef BALLISTICA_BASE_AUDIO_AL_SYS_H_
#define BALLISTICA_BASE_AUDIO_AL_SYS_H_
#include <string>
#include "ballistica/shared/ballistica.h"
#if BA_ENABLE_AUDIO
#if BA_HAVE_FRAMEWORK_OPENAL

View File

@ -394,7 +394,7 @@ void Logic::UpdateDisplayTimeForHeadlessMode_() {
// don't care about keeping the increments smooth or consistent.
// The one thing we *do* try to do, however, is keep our timer length
// updated so that we fire exactly when the next app-mode event is
// updated so that we'll fire exactly when the next app-mode event is
// scheduled (or at least close enough so we can fudge it and tell them
// its that exact time).
@ -554,6 +554,18 @@ void Logic::UpdateDisplayTimeForFrameDraw_() {
display_time_increment_ = display_time_increment_ + offs;
}
// If our final increment is bigger than some sane threshold, clamp it
// and try to report the conditions that caused it. We should finesse
// our math so that this never happens naturally.
const float max_increment{0.25f};
if (display_time_increment_ > max_increment) {
BA_LOG_ONCE(LogName::kBaDisplayTime, LogLevel::kWarning,
"Calced excessively large display_time_increment_ ("
+ std::to_string(display_time_increment_)
+ "); should not happen.");
display_time_increment_ = max_increment;
}
g_core->Log(LogName::kBaDisplayTime, LogLevel::kDebug,
[this, use_avg, this_increment, chaos, used] {
char buffer[256];

View File

@ -241,7 +241,11 @@ auto NetworkReader::RunThread_() -> int {
recvfrom(sd, buffer, sizeof(buffer), 0,
reinterpret_cast<sockaddr*>(&from), &from_size);
if (rresult == 0) {
g_core->Log(LogName::kBaNetworking, LogLevel::kError,
// Note: have gotten reports of server attacks with this log
// message repeating. So now only logging this once to eliminate
// repeated log overhead and hopefully make the attack less
// effective.
BA_LOG_ONCE(LogName::kBaNetworking, LogLevel::kError,
"NetworkReader Recv got length 0; this shouldn't "
"happen");
} else if (rresult == -1) {

View File

@ -117,6 +117,7 @@ class BasePython {
kUnsupportedControllerMessageCall,
kGetV2AccountIdCall,
kAppOnNativeActiveChangedCall,
kCopyDevConsoleHistoryCall,
kLast // Sentinel; must be at end.
};

View File

@ -39,13 +39,69 @@ const float kDevConsoleTabButtonCornerRadius{16.0f};
const double kTransitionSeconds{0.15};
enum class DevConsoleHAnchor_ { kLeft, kCenter, kRight };
enum class DevButtonStyle_ { kNormal, kLight };
enum class DevButtonStyle_ {
kNormal,
kBright,
kRed,
kRedBright,
kPurple,
kPurpleBright,
kYellow,
kYellowBright,
kBlue,
kBlueBright,
kWhite,
kWhiteBright,
kBlack,
kBlackBright
};
static auto DevButtonStyleFromStr_(const char* strval) {
if (!strcmp(strval, "light")) {
return DevButtonStyle_::kLight;
if (!strcmp(strval, "normal")) {
return DevButtonStyle_::kNormal;
}
assert(!strcmp(strval, "normal"));
if (!strcmp(strval, "bright")) {
return DevButtonStyle_::kBright;
}
if (!strcmp(strval, "red")) {
return DevButtonStyle_::kRed;
}
if (!strcmp(strval, "red_bright")) {
return DevButtonStyle_::kRedBright;
}
if (!strcmp(strval, "blue")) {
return DevButtonStyle_::kBlue;
}
if (!strcmp(strval, "blue_bright")) {
return DevButtonStyle_::kBlueBright;
}
if (!strcmp(strval, "purple")) {
return DevButtonStyle_::kPurple;
}
if (!strcmp(strval, "purple_bright")) {
return DevButtonStyle_::kPurpleBright;
}
if (!strcmp(strval, "yellow")) {
return DevButtonStyle_::kYellow;
}
if (!strcmp(strval, "yellow_bright")) {
return DevButtonStyle_::kYellowBright;
}
if (!strcmp(strval, "white")) {
return DevButtonStyle_::kWhite;
}
if (!strcmp(strval, "white_bright")) {
return DevButtonStyle_::kWhiteBright;
}
if (!strcmp(strval, "black")) {
return DevButtonStyle_::kBlack;
}
if (!strcmp(strval, "black_bright")) {
return DevButtonStyle_::kBlackBright;
}
g_core->Log(LogName::kBa, LogLevel::kError,
std::string("Invalid button-style: ") + strval);
return DevButtonStyle_::kNormal;
}
@ -260,7 +316,79 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
Vector3f fgcolor;
Vector3f bgcolor;
switch (style) {
case DevButtonStyle_::kLight:
case DevButtonStyle_::kYellow:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{0.8f, 0.5f, 0.0f} : Vector3f{0.45, 0.4f, 0.35f};
break;
case DevButtonStyle_::kYellowBright:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.0f, 0.0f, 0.0f};
bgcolor =
pressed ? Vector3f{1.0f, 0.5f, 0.0f} : Vector3f{0.9, 0.7f, 0.0f};
break;
case DevButtonStyle_::kRed:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{1.0f, 0.2f, 0.2f} : Vector3f{0.45, 0.3f, 0.35f};
break;
case DevButtonStyle_::kRedBright:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{1.0f, 0.0f, 0.0f} : Vector3f{0.8, 0.05f, 0.1f};
break;
case DevButtonStyle_::kPurple:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{0.8f, 0.0f, 1.0f} : Vector3f{0.35, 0.2f, 0.4f};
break;
case DevButtonStyle_::kPurpleBright:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{1.0f, 0.5f, 1.0f} : Vector3f{0.6, 0.2f, 0.8f};
break;
case DevButtonStyle_::kBlue:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{0.0f, 0.5f, 0.7f} : Vector3f{0.35, 0.4f, 0.55f};
break;
case DevButtonStyle_::kBlueBright:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.0f, 0.0f, 0.0f};
bgcolor =
pressed ? Vector3f{0.2f, 0.2f, 1.0f} : Vector3f{0.5, 0.7f, 1.0f};
break;
case DevButtonStyle_::kWhite:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
pressed ? Vector3f{0.3f, 0.3f, 0.3f} : Vector3f{0.38, 0.33f, 0.4f};
break;
case DevButtonStyle_::kWhiteBright:
fgcolor =
pressed ? Vector3f{1.0f, 1.0f, 1.0f} : Vector3f{0.0f, 0.0f, 0.0f};
bgcolor =
pressed ? Vector3f{0.4f, 0.4f, 0.4f} : Vector3f{0.8, 0.7f, 0.8f};
break;
case DevButtonStyle_::kBlack:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.8f, 0.7f, 0.8f};
bgcolor =
pressed ? Vector3f{1.0f, 1.0f, 1.0f} : Vector3f{0.0, 0.0f, 0.0f};
break;
case DevButtonStyle_::kBlackBright:
fgcolor =
pressed ? Vector3f{1.0f, 1.0f, 1.0f} : Vector3f{1.0f, 0.9f, 1.0f};
bgcolor =
pressed ? Vector3f{0.4f, 0.4f, 0.4f} : Vector3f{0.25f, 0.2f, 0.25f};
break;
case DevButtonStyle_::kBright:
fgcolor =
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.9f, 0.8f, 0.9f};
bgcolor =
@ -605,6 +733,10 @@ void DevConsole::AddPythonTerminal() {
"Exec", 0.5f * bs, DevConsoleHAnchor_::kRight, -33.0f * bs, 15.95f * bs,
32.0f * bs, 13.0f * bs, 2.0 * bs, DevButtonStyle_::kNormal, false,
[this] { Exec(); }));
widgets_.emplace_back(std::make_unique<Button_>(
"Copy History", 0.5f * bs, DevConsoleHAnchor_::kRight, -85.0f * bs,
Height() - 25.0f * bs, 80.0f * bs, 20.0f * bs, 4.0 * bs,
DevButtonStyle_::kNormal, false, [this] { CopyHistory(); }));
python_terminal_visible_ = true;
}
@ -1075,6 +1207,13 @@ auto DevConsole::HandleKeyRelease(const SDL_Keysym* keysym) -> bool {
return state_ != State_::kInactive;
}
void DevConsole::CopyHistory() {
BA_PRECONDITION(g_base->InLogicThread());
g_base->python->objs()
.Get(BasePython::ObjID::kCopyDevConsoleHistoryCall)
.Call();
}
void DevConsole::Exec() {
BA_PRECONDITION(g_base->InLogicThread());
if (!input_enabled_) {

View File

@ -57,6 +57,7 @@ class DevConsole {
auto HandleMouseDown(int button, float x, float y) -> bool;
void HandleMouseUp(int button, float x, float y);
void Exec();
void CopyHistory();
void AddButton(const char* label, float x, float y, float width, float height,
PyObject* call, const char* h_anchor_str, float label_scale,

View File

@ -520,9 +520,9 @@ void ClassicAppMode::StepDisplayTime() {
legacy_display_time_millisecs_prev_ = legacy_display_time_millisecs_;
// Special case: due to things like app-mode-switches our
// prev-display-time-millisecs may be way in the past which
// can give us huge step values. So if this value is much bigger
// than the direct conversion of display_time_increment, clamp it.
// prev-display-time-millisecs may be way far in the past which can give
// us huge step values. So if this value is much bigger than the direct
// conversion of display_time_increment, clamp it.
auto milliseconds_inc_max =
static_cast<int>(g_base->logic->display_time_increment() * 1000.0 * 1.5);
if (legacy_display_time_millisecs_inc > milliseconds_inc_max) {

View File

@ -509,12 +509,13 @@ void HostSession::Update(int time_advance_millisecs, double time_advance) {
}
}
// Shouldn't be getting huge steps through here; watch out for that.
// We shouldn't be getting *huge* steps coming through here. Warn if that
// ever happens so we can fix it at the source.
if (time_advance_millisecs > 500 || time_advance > 0.5) {
printf(
"WARNING: HostSession::Update() got excessive time_advance "
"(%d ms, %f s); should not happen.\n",
time_advance_millisecs, time_advance);
BA_LOG_ONCE(LogName::kBa, LogLevel::kError,
"HostSession::Update() got excessive time_advance ("
+ std::to_string(time_advance_millisecs) + " ms, "
+ std::to_string(time_advance) + " s); should not happen.");
}
// We can be killed at any time, so let's keep an eye out for that.

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

View File

@ -59,6 +59,7 @@ values = [
_hooks.get_dev_console_tab_names, # kGetDevConsoleTabNamesCall
_hooks.unsupported_controller_message, # kUnsupportedControllerMessageCall
_hooks.get_v2_account_id, # kGetV2AccountIdCall
_hooks.copy_dev_console_history, # kCopyDevConsoleHistoryCall
_language.Lstr, # kLStrClass
_general.Call, # kCallClass
_apputils.garbage_collect_session_end, # kGarbageCollectSessionEndCall

View File

@ -4,11 +4,11 @@
from __future__ import annotations
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Annotated, override
from typing import TYPE_CHECKING, Annotated, override, assert_never
from enum import Enum
from efro.message import Message, Response
from efro.dataclassio import ioprepped, IOAttrs
from efro.dataclassio import ioprepped, IOAttrs, IOMultiType
from bacommon.transfer import DirectoryManifest
from bacommon.login import LoginType
@ -323,3 +323,49 @@ class BSPrivatePartyResponse(Response):
tokens: Annotated[int, IOAttrs('t')]
gold_pass: Annotated[bool, IOAttrs('g')]
datacode: Annotated[str | None, IOAttrs('d')]
class CloudSubscriptionRequestTypeID(Enum):
"""Type ID for each of our subclasses."""
TEST = 'test'
class CloudSubscriptionRequest(IOMultiType[CloudSubscriptionRequestTypeID]):
"""Top level class for our multitype."""
@override
@classmethod
def get_type_id(cls) -> CloudSubscriptionRequestTypeID:
# Require child classes to supply this themselves. If we
# did a full type registry/lookup here it would require us
# to import everything and would prevent lazy loading.
raise NotImplementedError()
@override
@classmethod
def get_type(
cls, type_id: CloudSubscriptionRequestTypeID
) -> type[CloudSubscriptionRequest]:
"""Return the subclass for each of our type-ids."""
# pylint: disable=cyclic-import
out: type[CloudSubscriptionRequest]
t = CloudSubscriptionRequestTypeID
if type_id is t.TEST:
out = TestCloudSubscriptionRequest
else:
# Important to make sure we provide all types.
assert_never(type_id)
return out
@ioprepped
@dataclass
class TestCloudSubscriptionRequest(CloudSubscriptionRequest):
"""Just a test."""
@override
@classmethod
def get_type_id(cls) -> CloudSubscriptionRequestTypeID:
return CloudSubscriptionRequestTypeID.TEST

View File

@ -47,6 +47,7 @@ class MessageProtocol:
forward_clean_errors: bool = False,
remote_errors_include_stack_traces: bool = False,
log_errors_on_receiver: bool = True,
log_response_decode_errors: bool = True,
) -> None:
"""Create a protocol with a given configuration.
@ -78,14 +79,22 @@ class MessageProtocol:
goal is usually to avoid returning opaque RemoteErrors and to
instead return something meaningful as part of the expected
response type (even if that value itself represents a logical
error state). If 'log_errors_on_receiver' is False, however, such
exceptions will *not* be logged on the receiver. This can be
useful in combination with 'remote_errors_include_stack_traces'
and 'forward_clean_errors' in situations where all error
logging/management will be happening on the sender end. Be
aware, however, that in that case it may be possible for
communication errors to prevent such error messages from
ever being seen.
error state). If 'log_errors_on_receiver' is False, however,
such exceptions will *not* be logged on the receiver. This can
be useful in combination with
'remote_errors_include_stack_traces' and 'forward_clean_errors'
in situations where all error logging/management will be
happening on the sender end. Be aware, however, that in that
case it may be possible for communication errors to prevent some
errors from ever being acknowledged.
If an error occurs when decoding a message response, a
RuntimeError is generated locally. However, in practice it is
likely for such errors to be silently ignored by message
handling code alongside more common communication type errors,
meaning serious protocol breakage could go unnoticed. To avoid
this, a log message is also printed in such cases. Pass
'log_response_decode_errors' as False to disable this logging.
"""
# pylint: disable=too-many-locals
self.message_types_by_id: dict[int, type[Message]] = {}
@ -170,6 +179,7 @@ class MessageProtocol:
remote_errors_include_stack_traces
)
self.log_errors_on_receiver = log_errors_on_receiver
self.log_response_decode_errors = log_response_decode_errors
@staticmethod
def encode_dict(obj: dict) -> str:
@ -252,7 +262,7 @@ class MessageProtocol:
return out
def message_from_dict(self, data: dict) -> Message:
"""Decode a message from a json string."""
"""Decode a message from a dict."""
out = self._from_dict(data, self.message_types_by_id, 'message')
assert isinstance(out, Message)
return out

View File

@ -6,6 +6,7 @@ Supports static typing for message types and possible return types.
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from efro.error import CleanError, RemoteError, CommunicationError
@ -369,6 +370,19 @@ class MessageSender:
bound_obj, message, response_dict, response
)
except Exception as exc:
# We pragmatically log by default if decoding fails. This
# means a message type was likely changed in a way that
# breaks the protocol, but individual message handlers are
# likely to lump all errors together (communication and
# otherwise) which could cause such breakage to go
# unnoticed.
if self.protocol.log_response_decode_errors:
logging.exception(
'Error decoding message response;'
' protocol might be broken.',
)
response = ErrorSysResponse(
error_message='Error decoding raw response.',
error_type=ErrorSysResponse.ErrorType.LOCAL,