mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 08:53:32 +08:00
logging and bug hunting
This commit is contained in:
parent
006156aef7
commit
c296d965a2
120
.efrocachemap
120
.efrocachemap
@ -420,41 +420,41 @@
|
||||
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/60/ad/38269b7f1c7dc20cb9a506cd0681",
|
||||
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/72/85/d6fc4d16b7081d91fba2850b5b10",
|
||||
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/e9/ae/1d674d0c086eaa0bd1c3b1db0505",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/3c/3f/dc185a4ea8f2512770558ce0ff90",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/c5/81/e386a592e4fdf702b9089f106610",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/a8/a2/8c6816daac85d0b899a324509cf6",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/92/43/36b34307575f6d6219bdf4898e18",
|
||||
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/61/03/89070ca765e06da3a419a579f503",
|
||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/8e/4f/992f2a50dbe9514d774c1bb4fd28",
|
||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/aa/ed/4bd02af3cffbd4c9c4be532fb1fe",
|
||||
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/c2/a4/993d5f0f30d0670d7053466929b6",
|
||||
"assets/build/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/c9/73/01a1343af814131b1ee96af0b687",
|
||||
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/cb/df/f2d54d3146a159c678a47d3ff01b",
|
||||
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/4e/8c/72ddb584856a15dfb11df95f9283",
|
||||
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/6a/fa/fcf4a804beaff927b0f12c179eaa",
|
||||
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/68/93/da8e9874f41a786edf52ba4ccaad",
|
||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/7e/e7/836562182c2056902a326f5c7b9d",
|
||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/ad/85/3caf0c981389e46835862248386a",
|
||||
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/ac/f5/c0922a99e40dfc9f5e026d43b533",
|
||||
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/65/3f/6f1b739feac015dc39e97675b49d",
|
||||
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/8e/90/3ba17e62e21919bc2fa7e46884be",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/5d/2a/a5363cbe713fd67ea0baaa44403a",
|
||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/27/48/4cf2f4a3dd35260ef9b3b188ccde",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/63/64/8073ab02f55940292099513d341b",
|
||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/cb/7b/b881356f22e5f8293a5e4b8976ae",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/ee/fa/6eb38e7d4cfd13702c66d37b9723",
|
||||
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/8a/82/392f2a4e0e6e5a5e367f19e49538",
|
||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/2e/d1/b506ddf3d27af7be1ae6159531a3",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/b2/81/53c8cd7617d649403e539c3a6171",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/b4/51/0f993429723480691d5289c7bc5d",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/30/91/9dc870d35ddca657bf07d0f88a82",
|
||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/72/35/c40aee4c2f7f64fa030f83eb08d5",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/7c/38/d4a44c481757d355836f292ede48",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/32/97/4c61425d7c200a5c4c9ae3a94a0e",
|
||||
"assets/build/ba_data/data/languages/malay.json": "https://files.ballistica.net/cache/ba1/66/32/92ae734c4358397d2e90c1c85325",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/db/14/2f441ccb65023775dc8139a63f3f",
|
||||
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/67/93/372c2a2428a830056e9ba22bbf95",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/e6/fb/dfef0975c9c58cbcc621c022ec4b",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/cb/96/86bb139f20e126593f7fdba9e9e1",
|
||||
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/d7/06/9d70642d0a4d1e3b1c2149d7a17c",
|
||||
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/a4/08/5e70701b63899cddf21733b0eea6",
|
||||
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/b7/98/2523d11d09614bcfad8fa50be100",
|
||||
"assets/build/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/4e/91/6f2a9a3ce733908e91377a6ddb9a",
|
||||
"assets/build/ba_data/data/languages/slovak.json": "https://files.ballistica.net/cache/ba1/20/a9/163d189884edf802636bf291e432",
|
||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/e9/6d/62090311ae9aabaaae3918ea2d5b",
|
||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/d8/19/21882f76375ade330ef5a6e791a4",
|
||||
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/91/0a/35c4baf539d5951fc03a794c0e0b",
|
||||
"assets/build/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/48/2c/78cb542498a59e3023b4838df515",
|
||||
"assets/build/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/3d/83/e1bb0a664d1c14c41b1a083acf0d",
|
||||
"assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/d6/16/523c643358880b03b233ed88e557",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/c3/d2/d075ad07ec8d8aec3616f8760534",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/73/7b/b8822b5632a8d3c7cf134e2859cc",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/2a/0e/b164149e76efd0e6d591a9bf04bb",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/3e/b6/052f1faed0264bf7135feb5c4cc3",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/a6/ed/416638d46950c9ab4f6155b9c334",
|
||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/1f/ae/abe3f105b3c4b51f6b7942773305",
|
||||
"assets/build/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/47/0a/a617cc85d927b576c4e6fc1091ed",
|
||||
@ -4008,50 +4008,50 @@
|
||||
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
|
||||
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/1c/77/ac670a5118abdf8a7687af0e159b",
|
||||
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/6f/3c/b6d4e92dcbac32aa3093d9139b9d",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a1/b8/31ad72ffe5df6bbedbd59eb3f02b",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d2/d9/084996631fa94337e0a92c93b753",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/0a/4483e91a808e4724dfbc382d6f60",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ec/4d/6c58d9a9c5b13837d87d3d871868",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/dd/12/2e3164bd4770a6c648e2e7dbc4f0",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/fa/41/63a57ecf884cecf7ee1c8b9b2dcf",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/64/2b/0ebcdfd2f61027dcfff899d8894f",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8f/e7/3ca7ed13d4a03013ecbb80ecb78c",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ec/e2/ebe20cc007e87d0ede6e0ec169af",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3a/77/32299795fdb8b0c0fbc3130b7193",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/1a/bfaeccd961429479947ea1cb2c47",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/43/74/b5749a746e72007f2f464b2941c6",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/eb/e2/f97727387a3f9707b079b7b2acd0",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5f/da/6a048012e6b94a303e59b8dae61b",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f5/11/e75118e0a8f821e030f82e79c1bc",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d2/ad/4ee541d9d19b2d6fc1dab4947a26",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/10/2b/133d1cf611800e518d5353a10a94",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/85/53/fde7e925ac80da650a02ee078ad0",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/96/8e/c8292f6fc6967003affeb6ca32b7",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/28/f6/26327365481296a963bb37d58d82",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6d/b6/4e4a46d553d1949c956e72a3617d",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/81/57/d0a2b72a86d6f7f542d07e4fba29",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ac/f5/a6350f397911c2833c35fb86aa6c",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/91/87/78eab8de6f5bc52ff10f75e9d0b5",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a9/29/9cf3b260aae600ccafb535309b62",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/56/c2/75943b307817b0f23807b4f36632",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/93/51/6cf630d6ab82f8946569b96f01b5",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e4/ba/31a54b98463bc261835ac9cc7c51",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/64/25/bba77bfd767e14a9df46795c93bb",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f2/17/02a1053141eac72b24c323b10003",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/ca/dcbb87a7c32120a42ab6ca1e7194",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ca/dc/4a0fcdee7fc3c57960d5381a0299",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6c/a3/b70ad508a305efc2a10b5ba4508e",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/a9/1426b7eadc8be33f98f103fb12f0",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/38/8f/50753e457af4c626e2285c3171ac",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/fe/4d/77331e69f4fc0ef288df17377b42",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/9b/07/37e3a24a6ee588d0e5d4ba7b5335",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/0a/60/0109e5badaf8d6610cc9a4a61aa2",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/6d/e7/4e5bf2f3c16ca59770d5789c2481",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b5/de/6914b0c6ab3142ad99547e930d88",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/3e/a4/e22b4cc12099dc6863a418d186f9",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/bd/c7/c97d29a73c75b3e699f14bcd6e37",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/44/36/de0a2f89ccd4e4728301cecd1033",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b2/8a/31e68e8aeb4a440a98cdb37e688e",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7e/c2/ed0e710cd33e9a96c7f54fdf400a",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/62/35/37d0f605248971a7d270914c0e61",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/91/a1/5da5cec236aa862f7f92f89783cd",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/37/bb/b6bfe02bbd14a9c2d02fb782e4a9",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/05/38/a9adca329b4a147d58dd81a714ac",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2c/03/e562ae1a5cc7be268e1bf0ccc4c0",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c9/d5/066f05c777e200dd73084f0a1c25",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f7/6f/239efdb4e9e06cc0256f74da3aa8",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d7/77/48d470740edb84a271bfb18c2a16",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e1/2f/d8e39443dd972ea41fb0c241e8fd",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/32/9b/9d76eef13898e654b088698512d7",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/34/94/4abfe29e9b0443b292c53659a133",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/43/b1/2a8098e867f5d2a2cc086a4fb3f5",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/19/b6/0700636b968985ecc9ff1d3bd28e",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/db/ee/569470160da9dff657538c06ce7b",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/91/f9/6ec6bf4f8496ec4f71b3716db983",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/66/8a/7f50eede3fb6b6d7a655e4613f2e",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/d4/40/1121fb6089b698565347acec66f6",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/06/3b/0d289dd9a1170f750859e1c35b99",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f5/70/38d78023e0b99fdbe6ee29edd809",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/35/92/f2e39484904878e7eb9f5b3aff60",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6e/c5/6a81e0fc6027de9eca1c4a63143d",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/88/b5/e58450cec94d586f3d824f53c580",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/af/cf144d78359363ba027f2bd98a55",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9d/96/78f5d0d1e9249c71f018d84d9b24",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/58/d1/0f90ecfd6631b5476da915a76c55",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7c/bc/ec9ef218fb8065b58182493c981d",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/6b/b2a4eb26f043bb474e7e7e958470",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/64/e1/93f3afbc17ba6405cc970b559bb2",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/79/d2/f3b45d1aca8056c6cb951adc99ba",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4b/40/2ad8e00744d0b821e86fc42fc1f6",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8d/55/9876fecbe5d5076879b08d441665",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b4/f1/6c795ec50a26c24c734c5e0168b4",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7d/44/03c734fb003671a15182e8446a44",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7b/65/cadda8309ad9a4360a6930f05df8",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/41/a5/13590a172a2bf749bf419f67ce9f",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/76/26/0f89328b9e4554a5e656b1ead2d1",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/4b/da/b914c9e05be25d475155727046f4",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/c3/fb/78fe613f999fc6a9291c7141aeb8",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/f8/b2/cf697fd62a3f0bdbd248173551f0",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/d3/56/62b48ba16afb6023e730c9a42e75",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/4c/6e/009f37e5b619ce32e398b8039f62",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/26/03/2ee19e3130a7455efe5c9f78cd93",
|
||||
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/25/77/8093dfffddaa80cd513ddaa61867",
|
||||
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
|
||||
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"
|
||||
|
||||
6
.idea/dictionaries/ericf.xml
generated
6
.idea/dictionaries/ericf.xml
generated
@ -721,6 +721,7 @@
|
||||
<w>dummyret</w>
|
||||
<w>dummytoken</w>
|
||||
<w>dummyval</w>
|
||||
<w>dumpminlog</w>
|
||||
<w>dups</w>
|
||||
<w>dval</w>
|
||||
<w>dxml</w>
|
||||
@ -1376,6 +1377,7 @@
|
||||
<w>levelmodule</w>
|
||||
<w>levelname</w>
|
||||
<w>levelno</w>
|
||||
<w>levelnos</w>
|
||||
<w>levelstr</w>
|
||||
<w>lfull</w>
|
||||
<w>lfval</w>
|
||||
@ -1542,6 +1544,7 @@
|
||||
<w>mdiv</w>
|
||||
<w>mdocs</w>
|
||||
<w>mdocslines</w>
|
||||
<w>mdpath</w>
|
||||
<w>mdpi</w>
|
||||
<w>megalint</w>
|
||||
<w>memfunctions</w>
|
||||
@ -1569,6 +1572,7 @@
|
||||
<w>minigame</w>
|
||||
<w>minigames</w>
|
||||
<w>miniplayer</w>
|
||||
<w>minlog</w>
|
||||
<w>minping</w>
|
||||
<w>minusbutton</w>
|
||||
<w>minval</w>
|
||||
@ -2342,6 +2346,7 @@
|
||||
<w>shobs</w>
|
||||
<w>shortname</w>
|
||||
<w>shouldn</w>
|
||||
<w>showbuffer</w>
|
||||
<w>showpoints</w>
|
||||
<w>showstats</w>
|
||||
<w>showsubseconds</w>
|
||||
@ -2869,6 +2874,7 @@
|
||||
<w>webpage</w>
|
||||
<w>webpages</w>
|
||||
<w>weeeird</w>
|
||||
<w>whatarev</w>
|
||||
<w>whatevs</w>
|
||||
<w>whatisv</w>
|
||||
<w>wheee</w>
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
### 1.7.16 (build 20967, api 7, 2022-12-16)
|
||||
### 1.7.17 (build 20973, api 7, 2022-12-20)
|
||||
- V2 accounts now show a 'Unlink Legacy (V1) Accounts' button in account settings if they have any old v1 links present. This can be used to clear out old links to replace them with V2 links which work correctly with V2 accounts.
|
||||
- `ba.internal.dump_tracebacks()` is now `ba.internal.dump_app_state()` and `ba.internal.log_dumped_tracebacks()` is now `ba.internal.log_dumped_app_state()`. This reflects the fact that these calls may be expanded to include other app state in the future (C++ layer thread states, etc.).
|
||||
- Added `ba.app.health_monitor` which will dump app state if the logic thread ever stops responding for 5+ seconds while the app is running (to help diagnose deadlock situations).
|
||||
- Various extra logging and bug fixes related to V2 accounts and master server communication (trying to get this stuff working as smoothly as possible now that it is feature-complete).
|
||||
|
||||
### 1.7.16 (build 20969, api 7, 2022-12-18)
|
||||
- Fixed a bug where profile names encased in curly brackets could cause harmless error messages.
|
||||
- Android will no longer log errors on ba.open_url() calls if a browser is not available (it still just falls back to the in-app dialog in that case).
|
||||
- The 'Upgrade' button for device accounts now signs you out and closes the upgrade window to hopefully make it more clear that you need to sign in with your newly created/upgraded BombSquad account.
|
||||
|
||||
@ -32,6 +32,7 @@ if TYPE_CHECKING:
|
||||
from bastd.actor import spazappearance
|
||||
from ba._accountv2 import AccountV2Subsystem
|
||||
from ba._level import Level
|
||||
from ba._apputils import AppHealthMonitor
|
||||
|
||||
|
||||
class App:
|
||||
@ -50,7 +51,9 @@ class App:
|
||||
# Implementations for these will be filled in by internal libs.
|
||||
accounts_v2: AccountV2Subsystem
|
||||
cloud: CloudSubsystem
|
||||
|
||||
log_handler: efro.log.LogHandler
|
||||
health_monitor: AppHealthMonitor
|
||||
|
||||
class State(Enum):
|
||||
"""High level state the app can be in."""
|
||||
@ -346,7 +349,6 @@ class App:
|
||||
# pylint: disable=cyclic-import
|
||||
# pylint: disable=too-many-locals
|
||||
from ba import _asyncio
|
||||
from ba import _apputils
|
||||
from ba import _appconfig
|
||||
from ba import _map
|
||||
from ba import _campaign
|
||||
@ -354,11 +356,16 @@ class App:
|
||||
from bastd import maps as stdmaps
|
||||
from bastd.actor import spazappearance
|
||||
from ba._generated.enums import TimeType
|
||||
from ba._apputils import log_dumped_tracebacks
|
||||
from ba._apputils import (
|
||||
log_dumped_app_state,
|
||||
handle_leftover_v1_cloud_log_file,
|
||||
AppHealthMonitor,
|
||||
)
|
||||
|
||||
assert _ba.in_logic_thread()
|
||||
|
||||
self._aioloop = _asyncio.setup_asyncio()
|
||||
self.health_monitor = AppHealthMonitor()
|
||||
|
||||
cfg = self.config
|
||||
|
||||
@ -402,7 +409,7 @@ class App:
|
||||
|
||||
# If there's a leftover log file, attempt to upload it to the
|
||||
# master-server and/or get rid of it.
|
||||
_apputils.handle_leftover_v1_cloud_log_file()
|
||||
handle_leftover_v1_cloud_log_file()
|
||||
|
||||
# Only do this stuff if our config file is healthy so we don't
|
||||
# overwrite a broken one or whatnot and wipe out data.
|
||||
@ -461,7 +468,7 @@ class App:
|
||||
)
|
||||
|
||||
# If any traceback dumps happened last run, log and clear them.
|
||||
log_dumped_tracebacks()
|
||||
log_dumped_app_state()
|
||||
|
||||
self._launch_completed = True
|
||||
self._update_state()
|
||||
@ -493,6 +500,7 @@ class App:
|
||||
self.cloud.on_app_pause()
|
||||
self.accounts_v1.on_app_pause()
|
||||
self.plugins.on_app_pause()
|
||||
self.health_monitor.on_app_pause()
|
||||
else:
|
||||
# Leaving paused state:
|
||||
if self.state is self.State.PAUSED:
|
||||
@ -501,6 +509,7 @@ class App:
|
||||
self.accounts_v1.on_app_resume()
|
||||
self.music.on_app_resume()
|
||||
self.plugins.on_app_resume()
|
||||
self.health_monitor.on_app_resume()
|
||||
|
||||
if self._initial_login_completed and self._meta_scan_completed:
|
||||
self.state = self.State.RUNNING
|
||||
|
||||
@ -6,8 +6,12 @@ from __future__ import annotations
|
||||
import gc
|
||||
import os
|
||||
import logging
|
||||
from threading import Thread
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from efro.log import LogLevel
|
||||
from efro.dataclassio import ioprepped, dataclass_to_json, dataclass_from_json
|
||||
import _ba
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -266,22 +270,67 @@ def print_corrupt_file_error() -> None:
|
||||
_tbfiles: list[TextIO] = []
|
||||
|
||||
|
||||
def dump_tracebacks(delay: float) -> None:
|
||||
"""Dump a traceback of all Python threads after a delay in seconds.
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class DumpedAppStateMetadata:
|
||||
"""High level info about a dumped app state."""
|
||||
|
||||
Can be used for debugging deadlock situations. Will dump to a preset
|
||||
file location in the app config dir. Will attempt to log and clear
|
||||
the results after dumping. It will be done at next launch otherwise,
|
||||
or can be done explicitly via log_dumped_tracebacks().
|
||||
reason: str
|
||||
app_time: float
|
||||
log_level: LogLevel
|
||||
|
||||
Do not use this call during regular operation of the app; it is only
|
||||
intended for debugging as it can leak file descriptors/etc.
|
||||
|
||||
def dump_app_state(
|
||||
delay: float = 0.0,
|
||||
reason: str = 'Unspecified',
|
||||
log_level: LogLevel = LogLevel.WARNING,
|
||||
) -> None:
|
||||
"""Dump various app state for debugging purposes.
|
||||
|
||||
This includes stack traces for all Python threads (and potentially
|
||||
other info in the future).
|
||||
|
||||
This is intended for use debugging deadlock situations. It will dump
|
||||
to preset file location(s) in the app config dir, and will attempt to
|
||||
log and clear the results after dumping. If that should fail (due to
|
||||
a hung app, etc.), then the results will be logged and cleared on the
|
||||
next app run.
|
||||
|
||||
Do not use this call during regular smooth operation of the app; it
|
||||
is should only be used for debugging or in response to confirmed
|
||||
problems as it can leak file descriptors, cause hitches, etc.
|
||||
"""
|
||||
# pylint: disable=consider-using-with
|
||||
import faulthandler
|
||||
from ba._generated.enums import TimeType
|
||||
|
||||
tbpath = os.path.join(os.path.dirname(_ba.app.config_file_path), '_tbdump')
|
||||
# Dump our metadata immediately. If a delay is passed, it generally
|
||||
# means we expect things to hang momentarily, so we should not delay
|
||||
# writing our metadata or it will likely not happen. Though we
|
||||
# should remember that metadata doesn't line up perfectly in time with
|
||||
# the dump in that case.
|
||||
try:
|
||||
mdpath = os.path.join(
|
||||
os.path.dirname(_ba.app.config_file_path), '_appstate_dump_md'
|
||||
)
|
||||
with open(mdpath, 'w', encoding='utf-8') as outfile:
|
||||
outfile.write(
|
||||
dataclass_to_json(
|
||||
DumpedAppStateMetadata(
|
||||
reason=reason,
|
||||
app_time=_ba.time(TimeType.REAL),
|
||||
log_level=log_level,
|
||||
)
|
||||
)
|
||||
)
|
||||
except Exception:
|
||||
# Abandon whole dump if we can't write metadata.
|
||||
logging.exception('Error writing app state dump metadata.')
|
||||
return
|
||||
|
||||
tbpath = os.path.join(
|
||||
os.path.dirname(_ba.app.config_file_path), '_appstate_dump_tb'
|
||||
)
|
||||
|
||||
# faulthandler needs the raw file descriptor to still be valid when
|
||||
# it fires, so stuff this into a global var to make sure it doesn't get
|
||||
@ -289,23 +338,132 @@ def dump_tracebacks(delay: float) -> None:
|
||||
tbfile = open(tbpath, 'w', encoding='utf-8')
|
||||
_tbfiles.append(tbfile)
|
||||
|
||||
faulthandler.dump_traceback_later(delay, file=tbfile)
|
||||
if delay > 0.0:
|
||||
faulthandler.dump_traceback_later(delay, file=tbfile)
|
||||
else:
|
||||
faulthandler.dump_traceback(file=tbfile)
|
||||
|
||||
# Attempt to log shortly after dumping.
|
||||
with _ba.Context('ui'):
|
||||
_ba.timer(delay + 1.0, log_dumped_tracebacks, timetype=TimeType.REAL)
|
||||
# Allow sufficient time since we don't know how long the dump takes.
|
||||
# We want this to work from any thread, so need to kick this part
|
||||
# over to the logic thread so timer works.
|
||||
_ba.pushcall(
|
||||
lambda: _ba.timer(
|
||||
delay + 1.0, log_dumped_app_state, timetype=TimeType.REAL
|
||||
),
|
||||
from_other_thread=True,
|
||||
suppress_other_thread_warning=True,
|
||||
)
|
||||
|
||||
|
||||
def log_dumped_tracebacks() -> None:
|
||||
"""If a traceback dump exists, log it and clear it. No-op otherwise."""
|
||||
def log_dumped_app_state() -> None:
|
||||
"""If an app-state dump exists, log it and clear it. No-op otherwise."""
|
||||
|
||||
try:
|
||||
tbpath = os.path.join(
|
||||
os.path.dirname(_ba.app.config_file_path), '_tbdump'
|
||||
out = ''
|
||||
mdpath = os.path.join(
|
||||
os.path.dirname(_ba.app.config_file_path), '_appstate_dump_md'
|
||||
)
|
||||
if os.path.exists(tbpath):
|
||||
with open(tbpath, 'r', encoding='utf-8') as infile:
|
||||
logging.info('Dumped tracebacks:\n%s', infile.read())
|
||||
os.unlink(tbpath)
|
||||
if os.path.exists(mdpath):
|
||||
with open(mdpath, 'r', encoding='utf-8') as infile:
|
||||
metadata = dataclass_from_json(
|
||||
DumpedAppStateMetadata, infile.read()
|
||||
)
|
||||
os.unlink(mdpath)
|
||||
out += (
|
||||
f'App state dump:\nReason: {metadata.reason}\n'
|
||||
f'Time: {metadata.app_time:.2f}'
|
||||
)
|
||||
tbpath = os.path.join(
|
||||
os.path.dirname(_ba.app.config_file_path), '_appstate_dump_tb'
|
||||
)
|
||||
if os.path.exists(tbpath):
|
||||
with open(tbpath, 'r', encoding='utf-8') as infile:
|
||||
out += '\nPython tracebacks:\n' + infile.read()
|
||||
os.unlink(tbpath)
|
||||
logging.log(metadata.log_level.python_logging_level, out)
|
||||
except Exception:
|
||||
logging.exception('Error logging dumped tracebacks.')
|
||||
logging.exception('Error logging dumped app state.')
|
||||
|
||||
|
||||
class AppHealthMonitor:
|
||||
"""Logs things like app-not-responding issues."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
assert _ba.in_logic_thread()
|
||||
self._running = True
|
||||
self._thread = Thread(target=self._bg_thread_main, daemon=True)
|
||||
self._thread.start()
|
||||
self._response = False
|
||||
self._first_check = True
|
||||
|
||||
def _bg_thread_main(self) -> None:
|
||||
|
||||
try:
|
||||
self._monitor_app()
|
||||
except Exception:
|
||||
logging.exception('Error in AppHealthMonitor thread.')
|
||||
|
||||
def _set_response(self) -> None:
|
||||
assert _ba.in_logic_thread()
|
||||
self._response = True
|
||||
|
||||
def _check_running(self) -> bool:
|
||||
# Workaround for the fact that mypy assumes _running
|
||||
# doesn't change during the course of a function.
|
||||
return self._running
|
||||
|
||||
def _monitor_app(self) -> None:
|
||||
import time
|
||||
|
||||
while bool(True):
|
||||
|
||||
# Always sleep a bit between checks.
|
||||
time.sleep(1.234)
|
||||
|
||||
# Do nothing while backgrounded.
|
||||
while not self._running:
|
||||
time.sleep(2.3456)
|
||||
|
||||
# Wait for the logic thread to run something we send it.
|
||||
starttime = time.monotonic()
|
||||
self._response = False
|
||||
_ba.pushcall(self._set_response, raw=True)
|
||||
while not self._response:
|
||||
|
||||
# Abort this check if we went into the background.
|
||||
if not self._check_running():
|
||||
break
|
||||
|
||||
# Wait a bit longer the first time through since the app
|
||||
# could still be starting up; we generally don't want to
|
||||
# report that.
|
||||
threshold = 10 if self._first_check else 5
|
||||
|
||||
# If we've been waiting too long (and the app is running)
|
||||
# dump the app state and bail. Make an exception for the
|
||||
# first check though since the app could just be taking
|
||||
# a while to get going; we don't want to report that.
|
||||
duration = time.monotonic() - starttime
|
||||
if duration > threshold:
|
||||
dump_app_state(
|
||||
reason=f'Logic thread unresponsive'
|
||||
f' for {threshold} seconds.'
|
||||
)
|
||||
|
||||
# We just do one alert for now.
|
||||
return
|
||||
|
||||
time.sleep(1.042)
|
||||
|
||||
self._first_check = False
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Should be called when the app pauses."""
|
||||
assert _ba.in_logic_thread()
|
||||
self._running = False
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Should be called when the app resumes."""
|
||||
assert _ba.in_logic_thread()
|
||||
self._running = True
|
||||
|
||||
@ -47,7 +47,7 @@ def bootstrap() -> None:
|
||||
|
||||
# Give a soft warning if we're being used with a different binary
|
||||
# version than we expect.
|
||||
expected_build = 20967
|
||||
expected_build = 20973
|
||||
running_build: int = env['build_number']
|
||||
if running_build != expected_build:
|
||||
print(
|
||||
|
||||
@ -53,7 +53,9 @@ def get_store_item_display_size(item_name: str) -> tuple[float, float]:
|
||||
if item_name.startswith('characters.'):
|
||||
return 340 * 0.6, 430 * 0.6
|
||||
if item_name in ['pro', 'upgrades.pro', 'merch']:
|
||||
return 650 * 0.9, 500 * 0.85
|
||||
return 650 * 0.9, 500 * (
|
||||
0.72 if _ba.app.config.get('Merch Link') else 0.85
|
||||
)
|
||||
if item_name.startswith('maps.'):
|
||||
return 510 * 0.6, 450 * 0.6
|
||||
if item_name.startswith('icons.'):
|
||||
|
||||
@ -101,8 +101,8 @@ from ba._apputils import (
|
||||
is_browser_likely_available,
|
||||
get_remote_app_name,
|
||||
should_submit_debug_info,
|
||||
dump_tracebacks,
|
||||
log_dumped_tracebacks,
|
||||
dump_app_state,
|
||||
log_dumped_app_state,
|
||||
)
|
||||
from ba._benchmark import (
|
||||
run_gpu_benchmark,
|
||||
@ -334,6 +334,6 @@ __all__ = [
|
||||
'sign_out_v1',
|
||||
'sign_in_v1',
|
||||
'mark_config_dirty',
|
||||
'dump_tracebacks',
|
||||
'log_dumped_tracebacks',
|
||||
'dump_app_state',
|
||||
'log_dumped_app_state',
|
||||
]
|
||||
|
||||
@ -38,6 +38,8 @@ class AccountSettingsWindow(ba.Window):
|
||||
self._sign_in_v2_proxy_button: ba.Widget | None = None
|
||||
self._sign_in_device_button: ba.Widget | None = None
|
||||
|
||||
self._show_legacy_unlink_button = False
|
||||
|
||||
self._signing_in_adapter: LoginAdapter | None = None
|
||||
self._close_once_signed_in = close_once_signed_in
|
||||
ba.set_analytics_screen('Account Window')
|
||||
@ -57,14 +59,8 @@ class AccountSettingsWindow(ba.Window):
|
||||
self._r = 'accountSettingsWindow'
|
||||
self._modal = modal
|
||||
self._needs_refresh = False
|
||||
self._signed_in = ba.internal.get_v1_account_state() == 'signed_in'
|
||||
self._account_state_num = ba.internal.get_v1_account_state_num()
|
||||
self._show_linked = (
|
||||
self._signed_in
|
||||
and ba.internal.get_v1_account_misc_read_val(
|
||||
'allowAccountLinking2', False
|
||||
)
|
||||
)
|
||||
self._v1_signed_in = ba.internal.get_v1_account_state() == 'signed_in'
|
||||
self._v1_account_state_num = ba.internal.get_v1_account_state_num()
|
||||
self._check_sign_in_timer = ba.Timer(
|
||||
1.0,
|
||||
ba.WeakCall(self._update),
|
||||
@ -73,12 +69,12 @@ class AccountSettingsWindow(ba.Window):
|
||||
)
|
||||
|
||||
# Currently we can only reset achievements on game-center.
|
||||
account_type: str | None
|
||||
if self._signed_in:
|
||||
account_type = ba.internal.get_v1_account_type()
|
||||
v1_account_type: str | None
|
||||
if self._v1_signed_in:
|
||||
v1_account_type = ba.internal.get_v1_account_type()
|
||||
else:
|
||||
account_type = None
|
||||
self._can_reset_achievements = account_type == 'Game Center'
|
||||
v1_account_type = None
|
||||
self._can_reset_achievements = v1_account_type == 'Game Center'
|
||||
|
||||
app = ba.app
|
||||
uiscale = app.ui.uiscale
|
||||
@ -190,31 +186,25 @@ class AccountSettingsWindow(ba.Window):
|
||||
def _update(self) -> None:
|
||||
|
||||
# If they want us to close once we're signed in, do so.
|
||||
if self._close_once_signed_in and self._signed_in:
|
||||
if self._close_once_signed_in and self._v1_signed_in:
|
||||
self._back()
|
||||
return
|
||||
|
||||
# Hmm should update this to use get_account_state_num.
|
||||
# Theoretically if we switch from one signed-in account to another
|
||||
# in the background this would break.
|
||||
account_state_num = ba.internal.get_v1_account_state_num()
|
||||
account_state = ba.internal.get_v1_account_state()
|
||||
|
||||
show_linked = (
|
||||
self._signed_in
|
||||
and ba.internal.get_v1_account_misc_read_val(
|
||||
'allowAccountLinking2', False
|
||||
)
|
||||
)
|
||||
v1_account_state_num = ba.internal.get_v1_account_state_num()
|
||||
v1_account_state = ba.internal.get_v1_account_state()
|
||||
show_legacy_unlink_button = self._should_show_legacy_unlink_button()
|
||||
|
||||
if (
|
||||
account_state_num != self._account_state_num
|
||||
or self._show_linked != show_linked
|
||||
v1_account_state_num != self._v1_account_state_num
|
||||
or show_legacy_unlink_button != self._show_legacy_unlink_button
|
||||
or self._needs_refresh
|
||||
):
|
||||
self._show_linked = show_linked
|
||||
self._account_state_num = account_state_num
|
||||
self._signed_in = account_state == 'signed_in'
|
||||
self._v1_account_state_num = v1_account_state_num
|
||||
self._v1_signed_in = v1_account_state == 'signed_in'
|
||||
self._show_legacy_unlink_button = show_legacy_unlink_button
|
||||
self._refresh()
|
||||
|
||||
# Go ahead and refresh some individual things
|
||||
@ -253,10 +243,10 @@ class AccountSettingsWindow(ba.Window):
|
||||
False if gpgs_adapter is None else gpgs_adapter.is_back_end_active()
|
||||
)
|
||||
|
||||
show_signed_in_as = self._signed_in
|
||||
show_signed_in_as = self._v1_signed_in
|
||||
signed_in_as_space = 95.0
|
||||
|
||||
show_sign_in_benefits = not self._signed_in
|
||||
show_sign_in_benefits = not self._v1_signed_in
|
||||
sign_in_benefits_space = 80.0
|
||||
|
||||
show_signing_in_text = (
|
||||
@ -282,17 +272,17 @@ class AccountSettingsWindow(ba.Window):
|
||||
sign_in_button_space = 70.0
|
||||
deprecated_space = 60
|
||||
|
||||
show_game_service_button = self._signed_in and v1_account_type in [
|
||||
show_game_service_button = self._v1_signed_in and v1_account_type in [
|
||||
'Game Center'
|
||||
]
|
||||
game_service_button_space = 60.0
|
||||
|
||||
show_what_is_v2 = self._signed_in and v1_account_type == 'V2'
|
||||
show_what_is_v2 = self._v1_signed_in and v1_account_type == 'V2'
|
||||
|
||||
show_linked_accounts_text = self._signed_in
|
||||
show_linked_accounts_text = self._v1_signed_in
|
||||
linked_accounts_text_space = 60.0
|
||||
|
||||
show_achievements_button = self._signed_in and v1_account_type in (
|
||||
show_achievements_button = self._v1_signed_in and v1_account_type in (
|
||||
'Google Play',
|
||||
'Local',
|
||||
'V2',
|
||||
@ -300,33 +290,33 @@ class AccountSettingsWindow(ba.Window):
|
||||
achievements_button_space = 60.0
|
||||
|
||||
show_achievements_text = (
|
||||
self._signed_in and not show_achievements_button
|
||||
self._v1_signed_in and not show_achievements_button
|
||||
)
|
||||
achievements_text_space = 27.0
|
||||
|
||||
show_leaderboards_button = self._signed_in and is_gpgs
|
||||
show_leaderboards_button = self._v1_signed_in and is_gpgs
|
||||
leaderboards_button_space = 60.0
|
||||
|
||||
show_campaign_progress = self._signed_in
|
||||
show_campaign_progress = self._v1_signed_in
|
||||
campaign_progress_space = 27.0
|
||||
|
||||
show_tickets = self._signed_in
|
||||
show_tickets = self._v1_signed_in
|
||||
tickets_space = 27.0
|
||||
|
||||
show_reset_progress_button = False
|
||||
reset_progress_button_space = 70.0
|
||||
|
||||
show_manage_v2_account_button = (
|
||||
self._signed_in and v1_account_type == 'V2'
|
||||
self._v1_signed_in and v1_account_type == 'V2'
|
||||
)
|
||||
manage_v2_account_button_space = 100.0
|
||||
|
||||
show_player_profiles_button = self._signed_in
|
||||
show_player_profiles_button = self._v1_signed_in
|
||||
player_profiles_button_space = (
|
||||
70.0 if show_manage_v2_account_button else 100.0
|
||||
)
|
||||
|
||||
show_link_accounts_button = self._signed_in and (
|
||||
show_link_accounts_button = self._v1_signed_in and (
|
||||
primary_v2_account is None or FORCE_ENABLE_V1_LINKING
|
||||
)
|
||||
link_accounts_button_space = 70.0
|
||||
@ -334,10 +324,12 @@ class AccountSettingsWindow(ba.Window):
|
||||
show_unlink_accounts_button = show_link_accounts_button
|
||||
unlink_accounts_button_space = 90.0
|
||||
|
||||
show_v2_link_info = self._signed_in and not show_link_accounts_button
|
||||
show_v2_link_info = self._v1_signed_in and not show_link_accounts_button
|
||||
v2_link_info_space = 70.0
|
||||
|
||||
show_sign_out_button = self._signed_in and v1_account_type in [
|
||||
legacy_unlink_button_space = 120.0
|
||||
|
||||
show_sign_out_button = self._v1_signed_in and v1_account_type in [
|
||||
'Local',
|
||||
'Google Play',
|
||||
'V2',
|
||||
@ -394,6 +386,8 @@ class AccountSettingsWindow(ba.Window):
|
||||
self._sub_height += unlink_accounts_button_space
|
||||
if show_v2_link_info:
|
||||
self._sub_height += v2_link_info_space
|
||||
if self._show_legacy_unlink_button:
|
||||
self._sub_height += legacy_unlink_button_space
|
||||
if show_sign_out_button:
|
||||
self._sub_height += sign_out_button_space
|
||||
if show_cancel_sign_in_button:
|
||||
@ -460,7 +454,7 @@ class AccountSettingsWindow(ba.Window):
|
||||
v_align='center',
|
||||
autoselect=True,
|
||||
selectable=True,
|
||||
on_activate_call=ba.WeakCall(self._on_what_is_v2_press),
|
||||
on_activate_call=show_what_is_v2_page,
|
||||
click_activate=True,
|
||||
)
|
||||
if first_selectable is None:
|
||||
@ -1046,6 +1040,35 @@ class AccountSettingsWindow(ba.Window):
|
||||
color=(0.5, 0.45, 0.55),
|
||||
)
|
||||
|
||||
if self._show_legacy_unlink_button:
|
||||
v -= legacy_unlink_button_space
|
||||
button_width_w = button_width * 1.5
|
||||
ba.textwidget(
|
||||
parent=self._subcontainer,
|
||||
position=(self._sub_width * 0.5 - 150.0, v + 75),
|
||||
size=(300.0, 60),
|
||||
text=ba.Lstr(resource='whatIsThisText'),
|
||||
scale=0.8,
|
||||
color=(0.3, 0.7, 0.05),
|
||||
maxwidth=200.0,
|
||||
h_align='center',
|
||||
v_align='center',
|
||||
autoselect=True,
|
||||
selectable=True,
|
||||
on_activate_call=show_what_is_legacy_unlinking_page,
|
||||
click_activate=True,
|
||||
)
|
||||
btn = ba.buttonwidget(
|
||||
parent=self._subcontainer,
|
||||
position=((self._sub_width - button_width_w) * 0.5, v + 25),
|
||||
autoselect=True,
|
||||
size=(button_width_w, 60),
|
||||
label=ba.Lstr(resource=self._r + '.unlinkLegacyV1AccountsText'),
|
||||
textcolor=(0.8, 0.4, 0),
|
||||
color=(0.55, 0.5, 0.6),
|
||||
on_activate_call=self._unlink_accounts_press,
|
||||
)
|
||||
|
||||
if show_sign_out_button:
|
||||
v -= sign_out_button_space
|
||||
self._sign_out_button = btn = ba.buttonwidget(
|
||||
@ -1153,7 +1176,7 @@ class AccountSettingsWindow(ba.Window):
|
||||
timetype=ba.TimeType.REAL,
|
||||
)
|
||||
|
||||
def _have_unlinkable_accounts(self) -> bool:
|
||||
def _have_unlinkable_v1_accounts(self) -> bool:
|
||||
# if this is not present, we haven't had contact from the server so
|
||||
# let's not proceed..
|
||||
if ba.internal.get_public_login_id() is None:
|
||||
@ -1166,12 +1189,21 @@ class AccountSettingsWindow(ba.Window):
|
||||
def _update_unlink_accounts_button(self) -> None:
|
||||
if self._unlink_accounts_button is None:
|
||||
return
|
||||
if self._have_unlinkable_accounts():
|
||||
if self._have_unlinkable_v1_accounts():
|
||||
clr = (0.75, 0.7, 0.8, 1.0)
|
||||
else:
|
||||
clr = (1.0, 1.0, 1.0, 0.25)
|
||||
ba.textwidget(edit=self._unlink_accounts_button_label, color=clr)
|
||||
|
||||
def _should_show_legacy_unlink_button(self) -> bool:
|
||||
|
||||
# Only show this when fully signed in to a v2 account.
|
||||
if not self._v1_signed_in or ba.app.accounts_v2.primary is None:
|
||||
return False
|
||||
|
||||
out = self._have_unlinkable_v1_accounts()
|
||||
return out
|
||||
|
||||
def _update_linked_accounts_text(self) -> None:
|
||||
if self._linked_accounts_text is None:
|
||||
return
|
||||
@ -1297,7 +1329,7 @@ class AccountSettingsWindow(ba.Window):
|
||||
# pylint: disable=cyclic-import
|
||||
from bastd.ui.account import unlink
|
||||
|
||||
if not self._have_unlinkable_accounts():
|
||||
if not self._have_unlinkable_v1_accounts():
|
||||
ba.playsound(ba.getsound('error'))
|
||||
return
|
||||
unlink.AccountUnlinkWindow(origin_widget=self._unlink_accounts_button)
|
||||
@ -1499,3 +1531,9 @@ def show_what_is_v2_page() -> None:
|
||||
"""Show the webpage describing V2 accounts."""
|
||||
bamasteraddr = ba.internal.get_master_server_address(version=2)
|
||||
ba.open_url(f'{bamasteraddr}/whatisv2')
|
||||
|
||||
|
||||
def show_what_is_legacy_unlinking_page() -> None:
|
||||
"""Show the webpage describing legacy unlinking."""
|
||||
bamasteraddr = ba.internal.get_master_server_address(version=2)
|
||||
ba.open_url(f'{bamasteraddr}/whatarev1links')
|
||||
|
||||
@ -515,7 +515,20 @@ class MainMenuWindow(ba.Window):
|
||||
self._tdelay = 2.0
|
||||
self._t_delay_inc = 0.02
|
||||
self._t_delay_play = 1.7
|
||||
self._next_refresh_allow_time = ba.time(ba.TimeType.REAL) + 2.01
|
||||
|
||||
def _set_allow_time() -> None:
|
||||
self._next_refresh_allow_time = ba.time(ba.TimeType.REAL) + 2.5
|
||||
|
||||
# Slight hack: widget transitions currently only progress when
|
||||
# frames are being drawn, but this tends to get called before
|
||||
# frame drawing even starts, meaning we don't know exactly how
|
||||
# long we should wait before refreshing to avoid interrupting
|
||||
# the transition. To make things a bit better, let's do a
|
||||
# redundant set of the time in a deferred call which hopefully
|
||||
# happens closer to actual frame draw times.
|
||||
_set_allow_time()
|
||||
ba.pushcall(_set_allow_time)
|
||||
|
||||
ba.app.did_menu_intro = True
|
||||
self._width = 400.0
|
||||
self._height = 200.0
|
||||
|
||||
@ -907,7 +907,11 @@ class StoreBrowserWindow(ba.Window):
|
||||
dummy_name
|
||||
)
|
||||
section['v_spacing'] = (
|
||||
-17 if self._tab == 'characters' else 0
|
||||
-25
|
||||
if self._tab == 'extras'
|
||||
else -17
|
||||
if self._tab == 'characters'
|
||||
else 0
|
||||
)
|
||||
if 'title' not in section:
|
||||
section['title'] = ''
|
||||
@ -919,7 +923,13 @@ class StoreBrowserWindow(ba.Window):
|
||||
else 0
|
||||
)
|
||||
section['y_offs'] = (
|
||||
55
|
||||
20
|
||||
if (
|
||||
self._tab == 'extras'
|
||||
and uiscale is ba.UIScale.SMALL
|
||||
and ba.app.config.get('Merch Link')
|
||||
)
|
||||
else 55
|
||||
if (
|
||||
self._tab == 'extras'
|
||||
and uiscale is ba.UIScale.SMALL
|
||||
|
||||
@ -45,19 +45,23 @@ def instantiate_store_item_display(
|
||||
item['name'] = title = get_store_item_name_translated(item_name)
|
||||
|
||||
btn: ba.Widget | None
|
||||
|
||||
# Hack; showbuffer stuff isn't working well when we're showing merch.
|
||||
showbuffer = 10 if item_name in {'merch', 'pro', 'pro_sale'} else 76.0
|
||||
|
||||
if button:
|
||||
item['button'] = btn = ba.buttonwidget(
|
||||
parent=parent_widget,
|
||||
position=b_pos,
|
||||
transition_delay=delay,
|
||||
show_buffer_top=76.0,
|
||||
show_buffer_top=showbuffer,
|
||||
enable_sound=False,
|
||||
button_type='square',
|
||||
size=(b_width, b_height),
|
||||
autoselect=True,
|
||||
label='',
|
||||
)
|
||||
ba.widget(edit=btn, show_buffer_bottom=76.0)
|
||||
ba.widget(edit=btn, show_buffer_bottom=showbuffer)
|
||||
else:
|
||||
btn = None
|
||||
|
||||
@ -170,11 +174,11 @@ def instantiate_store_item_display(
|
||||
)
|
||||
|
||||
if item_name == 'merch':
|
||||
frame_size = b_width * 0.7
|
||||
frame_size = b_width * 0.65
|
||||
im_dim = frame_size * (100.0 / 113.0)
|
||||
im_pos = (
|
||||
b_pos[0] + b_width * 0.5 - im_dim * 0.5 + b_offs_x,
|
||||
b_pos[1] + b_height * 0.5 - im_dim * 0.5,
|
||||
b_pos[1] + b_height * 0.47 - im_dim * 0.5,
|
||||
)
|
||||
ba.imagewidget(
|
||||
parent=parent_widget,
|
||||
|
||||
@ -388,6 +388,7 @@
|
||||
<w>dummyret</w>
|
||||
<w>dummyval</w>
|
||||
<w>dummyvalid</w>
|
||||
<w>dumpminlog</w>
|
||||
<w>dval</w>
|
||||
<w>dxgi</w>
|
||||
<w>dynamicdata</w>
|
||||
@ -732,6 +733,7 @@
|
||||
<w>leaderboards</w>
|
||||
<w>lenval</w>
|
||||
<w>levelno</w>
|
||||
<w>levelnos</w>
|
||||
<w>levelstr</w>
|
||||
<w>lgui</w>
|
||||
<w>lhalf</w>
|
||||
@ -807,6 +809,7 @@
|
||||
<w>maxtries</w>
|
||||
<w>maxwait</w>
|
||||
<w>maxwidth</w>
|
||||
<w>mdpath</w>
|
||||
<w>mediump</w>
|
||||
<w>memalign</w>
|
||||
<w>memchr</w>
|
||||
@ -824,6 +827,7 @@
|
||||
<w>millisecs</w>
|
||||
<w>minelem</w>
|
||||
<w>miniplayer</w>
|
||||
<w>minlog</w>
|
||||
<w>minping</w>
|
||||
<w>minsdl</w>
|
||||
<w>mipmapcount</w>
|
||||
@ -1245,6 +1249,7 @@
|
||||
<w>shhh</w>
|
||||
<w>shifthigh</w>
|
||||
<w>shouldnt</w>
|
||||
<w>showbuffer</w>
|
||||
<w>shufflable</w>
|
||||
<w>signsubscale</w>
|
||||
<w>sigsetjmp</w>
|
||||
@ -1518,6 +1523,7 @@
|
||||
<w>weeeird</w>
|
||||
<w>welp</w>
|
||||
<w>whaaaaaaa</w>
|
||||
<w>whatarev</w>
|
||||
<w>whatisv</w>
|
||||
<w>wheee</w>
|
||||
<w>wheeee</w>
|
||||
|
||||
@ -32,8 +32,8 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kAppBuildNumber = 20967;
|
||||
const char* kAppVersion = "1.7.16";
|
||||
const int kAppBuildNumber = 20973;
|
||||
const char* kAppVersion = "1.7.17";
|
||||
|
||||
// Our standalone globals.
|
||||
// These are separated out for easy access.
|
||||
|
||||
@ -446,7 +446,9 @@ auto ContainerWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
||||
CheckLayout();
|
||||
|
||||
// Ignore mouse stuff while transitioning out.
|
||||
if (transitioning_ && transitioning_out_) break;
|
||||
if (transitioning_ && transitioning_out_) {
|
||||
break;
|
||||
}
|
||||
|
||||
float x = m.fval1;
|
||||
float y = m.fval2;
|
||||
@ -505,7 +507,9 @@ auto ContainerWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
||||
CheckLayout();
|
||||
|
||||
// Ignore mouse stuff while transitioning.
|
||||
if (transitioning_ && transitioning_out_) break;
|
||||
if (transitioning_ && transitioning_out_) {
|
||||
break;
|
||||
}
|
||||
|
||||
float x = m.fval1;
|
||||
float y = m.fval2;
|
||||
@ -546,7 +550,9 @@ auto ContainerWidget::HandleMessage(const WidgetMessage& m) -> bool {
|
||||
CheckLayout();
|
||||
|
||||
// Ignore mouse stuff while transitioning.
|
||||
if (transitioning_ && transitioning_out_) break;
|
||||
if (transitioning_ && transitioning_out_) {
|
||||
break;
|
||||
}
|
||||
|
||||
float x = m.fval1;
|
||||
float y = m.fval2;
|
||||
@ -909,7 +915,9 @@ void ContainerWidget::Draw(RenderPass* pass, bool draw_transparent) {
|
||||
}
|
||||
|
||||
// Don't draw if we've fully transitioned out.
|
||||
if (transitioning_out_ && !transitioning_) return;
|
||||
if (transitioning_out_ && !transitioning_) {
|
||||
return;
|
||||
}
|
||||
|
||||
float l = transition_offset_x_smoothed_ + transition_scale_offset_x_;
|
||||
float r = l + width_;
|
||||
|
||||
@ -37,7 +37,27 @@ class LogLevel(Enum):
|
||||
ERROR = 3
|
||||
CRITICAL = 4
|
||||
|
||||
@property
|
||||
def python_logging_level(self) -> int:
|
||||
"""Give the corresponding logging level."""
|
||||
return LOG_LEVEL_LEVELNOS[self]
|
||||
|
||||
@classmethod
|
||||
def from_python_logging_level(cls, levelno: int) -> LogLevel:
|
||||
"""Given a Python logging level, return a LogLevel."""
|
||||
return LEVELNO_LOG_LEVELS[levelno]
|
||||
|
||||
|
||||
# Python logging levels from LogLevels
|
||||
LOG_LEVEL_LEVELNOS = {
|
||||
LogLevel.DEBUG: logging.DEBUG,
|
||||
LogLevel.INFO: logging.INFO,
|
||||
LogLevel.WARNING: logging.WARNING,
|
||||
LogLevel.ERROR: logging.ERROR,
|
||||
LogLevel.CRITICAL: logging.CRITICAL,
|
||||
}
|
||||
|
||||
# LogLevels from Python logging levels
|
||||
LEVELNO_LOG_LEVELS = {
|
||||
logging.DEBUG: LogLevel.DEBUG,
|
||||
logging.INFO: LogLevel.INFO,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user