mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 21:37:57 +08:00
Language updates and minor bug fixes
This commit is contained in:
parent
3f427c7747
commit
738bad8852
118
.efrocachemap
118
.efrocachemap
@ -420,39 +420,39 @@
|
||||
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/d5/f8/de3b22ac60d0caee44369117c8db",
|
||||
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/c7/37/660e2ceca8b9b2db2cfce5a9f6f0",
|
||||
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/d9/82/92157cb4f21fdd8c911eec910ad4",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/4b/50/f349b757f92f6362a39f70ea7a80",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/45/70/91f386517fa3dc7322e1345ee1ab",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/25/20/31a26a4899e68dd9a0c6c272b998",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/a5/48/9e4424d04b273c8bdc25f9be4b6e",
|
||||
"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/55/93/1f358b653e9a347593d9b23f0061",
|
||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/fa/2e/fe2446e2dab7d8c7cf18a39b4b8e",
|
||||
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/60/48/bf681053e91e38d0f4c4b1f8f1a6",
|
||||
"assets/build/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/6c/2b/7a0669cc74fbcebbb76c440c6c04",
|
||||
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/61/77/ae85d46474923707f8a7190849a2",
|
||||
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/46/e4da3c1d2b0ebf916df55c608b28",
|
||||
"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/13/42/9585944a58dd340611373a48732f",
|
||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/11/26/c3dfae5a52f337529c4ea129237c",
|
||||
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/4c/c7/0184b8178869d1a3827a1bfcd5bb",
|
||||
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/a6/43/180ad35f294f7087661479687a12",
|
||||
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/ac/ec/2677e8fd26c395a5032d7d6e7aa1",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/b6/e0/37dd30b686f475733ccc4b3cab49",
|
||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/c0/26/04875251b9237f3133c84a910afd",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/f6/5c/591661f58ee2cf4a78fd8fa54bed",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/45/5c/abf0567aaea410b43783453eba5f",
|
||||
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/82/eb/37ff44af76812097f9c98f05c730",
|
||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/08/3b/68cea4d16f7020d932829af85323",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/b0/48/e1ebe08bfdfc94fcb61a16b851e5",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/75/70/e33e6ee95830052e8f36cd2135f7",
|
||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/f3/11/d81cc9f0c76b81b0b8dcf64fe292",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/07/37/ab65ccee3a555bd40e9661860c58",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/1b/45/b1e45fe07e0d632e979a9433dadd",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/37/90/0350db0bd1e98215fde8ee3f4059",
|
||||
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/76/be/84e567de0aabd9f9145b62179c2c",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/08/be/543b564010ad45e191d6ff5f130b",
|
||||
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/df/30/9ab2f22cdd54f0393a7d2aba2ae0",
|
||||
"assets/build/ba_data/data/languages/russian.json": "https://files.ballistica.net/cache/ba1/f2/41/d4f06aabfc3499534e04fedb10dd",
|
||||
"assets/build/ba_data/data/languages/serbian.json": "https://files.ballistica.net/cache/ba1/13/19/828be486951be254445263f36c6e",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/a6/ad/7ee52772db14f9008044bb877ed1",
|
||||
"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/6c/46/292406974d45fd9a92e40022b443",
|
||||
"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/f9/4b/d9f01814224066856695452ef57c",
|
||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/bc/93/b5d78fcd8cdffda7f3d9cc238cef",
|
||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/80/d7/bd62eacc2ec901e145e37168c737",
|
||||
"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/9f/2c/367db6734a89603ed45534fccb14",
|
||||
"assets/build/ba_data/data/languages/tamil.json": "https://files.ballistica.net/cache/ba1/55/46/61fa6c9a93f6c0d57529d7949190",
|
||||
"assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/9d/51/f699dbd4beb88bc3cff699a287a7",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/7e/d0/b21f8bcdc7f2727a6e68af3d0e68",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/c0/4e/c8a66ed415b8b0ce3ff30462b2a2",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/7f/bb/6239adeb551be5e09f3457d7b411",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/68/77/cc871b6ed611cb8d6f74cf1a9d00",
|
||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/f2/af/afd1503c7a10cacaa15bc02369b2",
|
||||
@ -3995,50 +3995,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/b2/e5/0ee0561e16257a32830645239f34",
|
||||
"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/e2/e0/7e12f13ce528c828ae8c482ac1c5",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a4/cd/a23c971748bee4c4726192d892e6",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/04/c6/240b3031c13ca7df990e5c867e82",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/58/c4/339c89e00d13ed26f2b83ace0053",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d6/fa/9d66b57832c3155899fda3b9ed2d",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3a/7f/df248f9fcab1f0a6b3188de679f1",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4a/a2/a9e03eabf8dce07d7d150dbe533f",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/12/c4/672108a20af3efd292f0f19cb6d1",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f9/70/991734c16666f041ec26fd3d24fc",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3f/1d/5867b2567b0b5092898c79ba13c6",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/46/b7/69773f4298626ff327680db9aa26",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/03/75/f2f6bb1c9eebf8c3eecb44fd76b5",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b7/40/3c89c40a3522c5533bf567b86005",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/6c/0f/982997d664d258a9f2dd7d100447",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d0/52/a06b3b9ec34d78c27ece18dfc04c",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/e7/5d1b3acd640935f2d262adf9f56e",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/57/d4/79d1653f278e083ff3d970b345e5",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/0b/ce/5aef8c58b6120549ac677c0aa83a",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/5b/57/68e576ff9ceed03102d2ef199a23",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/53/77/fb69f8b5475e0ab5fb5c028fda1c",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3c/08/bcb4ce1689de4f0a4ffe1d7c542f",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/67/44/8916488c91538d83248f0ec5a2e5",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/d7/6ff4bfa3bb6805fa812fb023876e",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c1/f0/a26ed674437c26c8af557c10fc25",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b9/b0/e3a2098f4324d361135d140c7d16",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/d2/25ea99e21ab82489758ad2f4eda1",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/18/d3/b3fa835ed6fce67f22513718fcf5",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/74/37/d65ed9c851e97a4c16f99ce4b996",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/85/4a/c04a061403b47b26c2fe477bce5b",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/04/37/dd511de9d333afd4f77c8a37d11c",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2d/40/33c32f48b5ec2ff940d8ed114e0f",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/55/f7/3f6a200eae7baf961a9ba3d1857d",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fd/e8/af76c5dccfe324c6081185f5e8f0",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/aa/c5/159b01f8dc8a4201dec430c77a5c",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c3/ec/f087eff8388ef3f0a16699bb44b3",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/64/98/01a2649fa88ad6513e8c36d3ac04",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/ee/67/86f37883c1d82436296c107cb0af",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/b6/0a/288ab61d465b4901cf7112a241c9",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/73/88/561fac00c0eb27f6b451322cf777",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/e6/11/73127ddbd3a779076770a7448ce1",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/2a/3c/ef57604bb8e94075d74eafe258e3",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/5d/ca/0e6d9a2ac4d0f750b8295b6d775e",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/ff/e3/f03bc482b4e305288e7418acb38a",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/8a/33/713bfca4012f0d1b7b7b4e896d46",
|
||||
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/6e/6f/004b696e9a13b083069374e4bb6a",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/2f/ec/756d728d0a912a0a0ce1e46b3351",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/2e/d8/41fb2f73f9b915e809a3d8671c45",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/a9/931e229fed568facc7d77b407a9a",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9c/f3/aef423feb4f5e91ce72fb5a25fa0",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/cd/c2/f5f0a7ae3197fe5f05bfcee3a3e3",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/4f/dc/2a1a296dddd5d5fef6b2f0bef6e8",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c6/4c/e1274ac12ae7a0a60d02686abc0b",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6c/b1/f56d3edb7c6efa23518b78b74846",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/87/b2/0a85ffc1ed64724da5663086a2a9",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/bc/95/67636889721c129a697a55fc47c2",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/59/8f/0bfe1878a0941351294b2306b2ad",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/de/43/bfab4d3fda82d02e97207f5be4cd",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/39/d0/6bb26d2fce1d6f8644191217c00c",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/80/33/fc11bdaba571fc91429518881081",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/be/9d/9e39fc8085e1061d016e9ea242a6",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8a/aa/fef783198a65c064b1c8be235307",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/87/4b/06fca73ff1a1c22f92f462c8e539",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/97/32/95378dfe465d38aa3bbebb932669",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/e3/af/8e86cf496985267f69a98613eb15",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/3a/4a/2860a58d8b460ca6ff8243a0f185",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c3/a5/d77c0da95027f6c6b2158d554692",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/92/93/d343eb8e8783494d8d04949fcd34",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/26/c623cadc48e151bf438579730e33",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cc/32/eb7bd9b981c303d59ec32efc46b7",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7a/9a/43e14da4b3ec46f69fd710d4daba",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a4/c1/e4548f2abcba4c48e713dd24e2fd",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/69/79/8e676bba0b03ed522c2475bb07b4",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/69/97/6119b7a2dd5c1f3fbcb2d921652d",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/73/53/98ea7844b411cbc99a347213410f",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/74/78/9b5b9048e0fcb3f6283983046cd8",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7a/1a/503e5789b08c3a85bb34bebccdf8",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/04/cf/a70ffac469d5bbc2ba9d56ebffcb",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6f/e6/66090d68d391eba428a6b5d146e5",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2f/4c/d59f4dd0c41e1cb3f32f3864e8cc",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/16/9c/bda065fbb75646796383ff4c0490",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8c/56/b6f1a19cda20dada065f0f43cd83",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/f4/76/36e047c715c69980bf53f47cc03b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/83/03/e08562ec65eba9577c9fbe1a98b0",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/26/08/755cd4f6d908359e0a7d33a5f9dd",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/bd/d7/0de5664c35680f40a9c8efbc264b",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/e9/65/0693588e1b04bff51d197c77e6c6",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/bd/b1/866126ff56ab9c6148b750282295",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/ef/47/19efea33fdbd69c376f35b590e3b",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/5b/e6/174649077bcc202ead74e7e5bf4d",
|
||||
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/7d/3e/229a581cb2454ed856f1d8b564a7",
|
||||
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/d3/db/e73d4dcf1280d5f677c3cf8b47c3"
|
||||
}
|
||||
@ -1,4 +1,8 @@
|
||||
### 1.7.5 (20648, 2022-07-12)
|
||||
### 1.7.5 (20650, 2022-07-14)
|
||||
- Android build now uses the ReLinker library to load the native main.so, which will (hopefully) avoid some random load failures on older Android versions.
|
||||
- Android Google Play build now prints a message at launch if the billing library isn't available or needs to be updated (explaining why purchases won't work in that case).
|
||||
- Various minor bug fixes (mostly cleaning up unnecessary error logging)
|
||||
- Updated Android builds to use the new NDK 25 release
|
||||
|
||||
### 1.7.4 (20646, 2022-07-12)
|
||||
- Fixed the trophies list showing an incorrect total (Thanks itsre3!)
|
||||
|
||||
@ -204,6 +204,12 @@ def no_game_circle_message() -> None:
|
||||
_ba.screenmessage(Lstr(resource='noGameCircleText'), color=(1, 0, 0))
|
||||
|
||||
|
||||
def google_play_purchases_not_available_message() -> None:
|
||||
from ba._language import Lstr
|
||||
_ba.screenmessage(Lstr(resource='googlePlayPurchasesNotAvailableText'),
|
||||
color=(1, 0, 0))
|
||||
|
||||
|
||||
def empty_call() -> None:
|
||||
pass
|
||||
|
||||
|
||||
@ -127,29 +127,33 @@ class MasterServerCallThread(threading.Thread):
|
||||
self._callback(arg)
|
||||
|
||||
def run(self) -> None:
|
||||
# pylint: disable=too-many-branches, consider-using-with
|
||||
# pylint: disable=consider-using-with
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
import json
|
||||
|
||||
from efro.error import is_urllib_network_error
|
||||
from efro.error import is_urllib_communication_error
|
||||
from ba import _general
|
||||
|
||||
response_data: Any = None
|
||||
url: str | None = None
|
||||
try:
|
||||
self._data = _general.utf8_all(self._data)
|
||||
_ba.set_thread_name('BA_ServerCallThread')
|
||||
if self._request_type == 'get':
|
||||
url = (_ba.get_master_server_address() + '/' + self._request +
|
||||
'?' + urllib.parse.urlencode(self._data))
|
||||
response = urllib.request.urlopen(
|
||||
urllib.request.Request(
|
||||
(_ba.get_master_server_address() + '/' +
|
||||
self._request + '?' +
|
||||
urllib.parse.urlencode(self._data)), None,
|
||||
{'User-Agent': _ba.app.user_agent_string}),
|
||||
url, None, {'User-Agent': _ba.app.user_agent_string}),
|
||||
context=_ba.app.net.sslcontext,
|
||||
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
||||
elif self._request_type == 'post':
|
||||
url = _ba.get_master_server_address() + '/' + self._request
|
||||
response = urllib.request.urlopen(
|
||||
urllib.request.Request(
|
||||
_ba.get_master_server_address() + '/' + self._request,
|
||||
url,
|
||||
urllib.parse.urlencode(self._data).encode(),
|
||||
{'User-Agent': _ba.app.user_agent_string}),
|
||||
context=_ba.app.net.sslcontext,
|
||||
@ -172,29 +176,18 @@ class MasterServerCallThread(threading.Thread):
|
||||
raise TypeError(f'invalid responsetype: {self._response_type}')
|
||||
|
||||
except Exception as exc:
|
||||
do_print = False
|
||||
response_data = None
|
||||
|
||||
# Ignore common network errors; note unexpected ones.
|
||||
if is_urllib_network_error(exc):
|
||||
pass
|
||||
elif (self._response_type == MasterServerResponseType.JSON
|
||||
and isinstance(exc, json.decoder.JSONDecodeError)):
|
||||
# FIXME: should handle this better; could mean either the
|
||||
# server sent us bad data or it got corrupted along the way.
|
||||
pass
|
||||
else:
|
||||
do_print = True
|
||||
|
||||
if do_print:
|
||||
# Any other error here is unexpected,
|
||||
# so let's make a note of it,
|
||||
if not is_urllib_communication_error(exc, url=url):
|
||||
print(f'Error in MasterServerCallThread'
|
||||
f' (response-type={self._response_type},'
|
||||
f' (url={url},'
|
||||
f' response-type={self._response_type},'
|
||||
f' response-data={response_data}):')
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
response_data = None
|
||||
|
||||
if self._callback is not None:
|
||||
_ba.pushcall(_general.Call(self._run_callback, response_data),
|
||||
from_other_thread=True)
|
||||
|
||||
@ -705,8 +705,8 @@ class ManualGatherTab(GatherTab):
|
||||
from_other_thread=True,
|
||||
)
|
||||
except Exception as exc:
|
||||
from efro.error import is_udp_network_error
|
||||
if is_udp_network_error(exc):
|
||||
from efro.error import is_udp_communication_error
|
||||
if is_udp_communication_error(exc):
|
||||
ba.pushcall(ba.Call(
|
||||
_safe_set_text, self._checking_state_text,
|
||||
ba.Lstr(resource='gatherWindow.'
|
||||
|
||||
@ -219,9 +219,9 @@ class AddrFetchThread(threading.Thread):
|
||||
sock.close()
|
||||
ba.pushcall(ba.Call(self._call, val), from_other_thread=True)
|
||||
except Exception as exc:
|
||||
from efro.error import is_udp_network_error
|
||||
from efro.error import is_udp_communication_error
|
||||
# Ignore expected network errors; log others.
|
||||
if is_udp_network_error(exc):
|
||||
if is_udp_communication_error(exc):
|
||||
pass
|
||||
else:
|
||||
ba.print_exception()
|
||||
@ -271,8 +271,8 @@ class PingThread(threading.Thread):
|
||||
ping if accessible else None),
|
||||
from_other_thread=True)
|
||||
except Exception as exc:
|
||||
from efro.error import is_udp_network_error
|
||||
if is_udp_network_error(exc):
|
||||
from efro.error import is_udp_communication_error
|
||||
if is_udp_communication_error(exc):
|
||||
pass
|
||||
else:
|
||||
ba.print_exception('Error on gather ping', once=True)
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
;; Projectile indexing and search will ignore the following
|
||||
;; (in addition to git-ignored stuff which it ignores by default)
|
||||
;; NOTE TO SELF: this means searches in spinoff projects will mostly fail
|
||||
;; because everything is gitignored; should search in parent repo instead.
|
||||
(nil . ((projectile-globally-ignored-directories . ("docs"
|
||||
"submodules"
|
||||
"src/external"
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kAppBuildNumber = 20648;
|
||||
const int kAppBuildNumber = 20650;
|
||||
const char* kAppVersion = "1.7.5";
|
||||
|
||||
// Our standalone globals.
|
||||
|
||||
@ -25,10 +25,6 @@ auto FatalError::ReportFatalError(const std::string& message,
|
||||
// error to the user and exiting the app cleanly (so we don't pollute our
|
||||
// crash records with results of user tinkering).
|
||||
|
||||
// Try to avoid crash reports if we're not a clean blessed build.
|
||||
// bool exit_cleanly = !IsUnmodifiedBlessedBuild();
|
||||
// printf("BLESSED %d\n", static_cast<int>(IsUnmodifiedBlessedBuild()));
|
||||
|
||||
// Give the platform the opportunity to completely override our handling.
|
||||
if (g_platform) {
|
||||
auto handled =
|
||||
|
||||
@ -195,21 +195,14 @@ auto PyExtraHashValue(PyObject* self, PyObject* args, PyObject* keywds)
|
||||
const_cast<char**>(kwlist))) {
|
||||
return nullptr;
|
||||
}
|
||||
const char* h = (g_app_globals->user_ran_commands ? "cjief3l" : "wofocj8");
|
||||
const char* h =
|
||||
((g_app_globals->user_ran_commands || g_app_globals->have_mods)
|
||||
? "cjief3l"
|
||||
: "wofocj8");
|
||||
return PyUnicode_FromString(h);
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
auto PySetHaveMods(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
Platform::SetLastPyCall("set_have_mods");
|
||||
int have_mods;
|
||||
if (!PyArg_ParseTuple(args, "p", &have_mods)) return nullptr;
|
||||
g_app_globals->have_mods = static_cast<bool>(have_mods);
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
auto PyGetIdleTime(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
Platform::SetLastPyCall("get_idle_time");
|
||||
@ -1077,11 +1070,6 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
|
||||
"\n"
|
||||
"Returns the amount of time since any game input has been received."},
|
||||
|
||||
{"set_have_mods", PySetHaveMods, METH_VARARGS,
|
||||
"set_have_mods(have_mods: bool) -> None\n"
|
||||
"\n"
|
||||
"(internal)"},
|
||||
|
||||
{"ehv", (PyCFunction)PyExtraHashValue, METH_VARARGS | METH_KEYWORDS,
|
||||
"ehv() -> None\n"
|
||||
"\n"
|
||||
|
||||
@ -309,6 +309,7 @@ class Python {
|
||||
kSubmitAnalyticsCountsCall,
|
||||
kSetLastAdNetworkCall,
|
||||
kNoGameCircleMessageCall,
|
||||
kGooglePlayPurchasesNotAvailableMessageCall,
|
||||
kEmptyCall,
|
||||
kLevelIconPressCall,
|
||||
kTrophyIconPressCall,
|
||||
|
||||
@ -64,6 +64,7 @@ def get_binding_values() -> tuple[Any, ...]:
|
||||
_hooks.submit_analytics_counts, # kSubmitAnalyticsCountsCall
|
||||
_hooks.set_last_ad_network, # kSetLastAdNetworkCall
|
||||
_hooks.no_game_circle_message, # kNoGameCircleMessageCall
|
||||
_hooks.google_play_purchases_not_available_message, # kGooglePlayPurchasesNotAvailableMessageCall
|
||||
_hooks.empty_call, # kEmptyCall
|
||||
_hooks.level_icon_press, # kLevelIconPressCall
|
||||
_hooks.trophy_icon_press, # kTrophyIconPressCall
|
||||
|
||||
@ -12,7 +12,7 @@ from dataclasses import dataclass
|
||||
import pytest
|
||||
|
||||
from efrotools.statictest import static_type_equals
|
||||
from efro.error import CleanError, RemoteError
|
||||
from efro.error import CleanError, RemoteError, CommunicationError
|
||||
from efro.dataclassio import ioprepped
|
||||
from efro.message import (Message, Response, MessageProtocol, MessageSender,
|
||||
BoundMessageSender, MessageReceiver,
|
||||
@ -748,6 +748,8 @@ def test_full_pipeline() -> None:
|
||||
msg = _TestMessageSenderBBoth()
|
||||
|
||||
test_handling_unregistered = False
|
||||
test_send_method_exceptions = False
|
||||
test_send_method_exceptions_comm = False
|
||||
|
||||
def __init__(self, target: TestClassRSync | TestClassRAsync) -> None:
|
||||
self.test_sidecar = False
|
||||
@ -756,6 +758,13 @@ def test_full_pipeline() -> None:
|
||||
@msg.send_method
|
||||
def _send_raw_message(self, data: str) -> str:
|
||||
"""Handle synchronous sending of raw json message data."""
|
||||
|
||||
# Test throwing exceptions in send methods.
|
||||
if self.test_send_method_exceptions:
|
||||
raise (CommunicationError()
|
||||
if self.test_send_method_exceptions_comm else
|
||||
RuntimeError())
|
||||
|
||||
# Just talk directly to the receiver for this example.
|
||||
# (currently only support synchronous receivers)
|
||||
assert isinstance(self._target, TestClassRSync)
|
||||
@ -774,6 +783,13 @@ def test_full_pipeline() -> None:
|
||||
@msg.send_async_method
|
||||
async def _send_raw_message_async(self, data: str) -> str:
|
||||
"""Handle asynchronous sending of raw json message data."""
|
||||
|
||||
# Test throwing exceptions in async send methods.
|
||||
if self.test_send_method_exceptions:
|
||||
raise (CommunicationError()
|
||||
if self.test_send_method_exceptions_comm else
|
||||
RuntimeError())
|
||||
|
||||
# Just talk directly to the receiver for this example.
|
||||
# (we can do sync or async receivers)
|
||||
if isinstance(self._target, TestClassRSync):
|
||||
@ -932,3 +948,21 @@ def test_full_pipeline() -> None:
|
||||
assert getattr(response1, '_sidecar_data') == 198
|
||||
obj.test_sidecar = False
|
||||
obj_r_sync.test_sidecar = False
|
||||
|
||||
# Now test errors in the raw-send function. Errors there should
|
||||
# come across as either CommunicationErrors or RuntimeErrors
|
||||
obj.test_send_method_exceptions = True
|
||||
|
||||
obj.test_send_method_exceptions_comm = False
|
||||
with pytest.raises(RuntimeError):
|
||||
response1 = obj.msg.send(_TMsg1(ival=0))
|
||||
with pytest.raises(RuntimeError):
|
||||
response4 = asyncio.run(obj.msg.send_async(_TMsg1(ival=0)))
|
||||
|
||||
obj.test_send_method_exceptions_comm = True
|
||||
with pytest.raises(CommunicationError):
|
||||
response1 = obj.msg.send(_TMsg1(ival=0))
|
||||
with pytest.raises(CommunicationError):
|
||||
response4 = asyncio.run(obj.msg.send_async(_TMsg1(ival=0)))
|
||||
|
||||
obj.test_send_method_exceptions = False
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
import errno
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
@ -39,12 +40,13 @@ class CommunicationError(Exception):
|
||||
"""A communication related error has occurred.
|
||||
|
||||
This covers anything network-related going wrong in the sending
|
||||
of data or receiving of a response. This error does not imply
|
||||
of data or receiving of a response. Basically anything that is out
|
||||
of our control should get lumped in here. This error does not imply
|
||||
that data was not received on the other end; only that a full
|
||||
acknowledgement round trip was not completed.
|
||||
|
||||
These errors should be gracefully handled whenever possible, as
|
||||
occasional network outages are generally unavoidable.
|
||||
occasional network issues are unavoidable.
|
||||
"""
|
||||
|
||||
|
||||
@ -55,9 +57,9 @@ class RemoteError(Exception):
|
||||
occurs remotely. The error string can consist of a remote stack
|
||||
trace or a simple message depending on the context.
|
||||
|
||||
Communication systems should raise more specific error types when
|
||||
more introspection/control is needed; this is intended somewhat as
|
||||
a catch-all.
|
||||
Communication systems should raise more specific error types locally
|
||||
when more introspection/control is needed; this is intended somewhat
|
||||
as a catch-all.
|
||||
"""
|
||||
|
||||
def __str__(self) -> str:
|
||||
@ -69,31 +71,43 @@ class IntegrityError(ValueError):
|
||||
"""Data has been tampered with or corrupted in some form."""
|
||||
|
||||
|
||||
def is_urllib_network_error(exc: BaseException) -> bool:
|
||||
"""Is the provided exception from urllib a network-related error?
|
||||
def is_urllib_communication_error(exc: BaseException, url: str | None) -> bool:
|
||||
"""Is the provided exception from urllib a communication-related error?
|
||||
|
||||
Url, if provided can provide extra context for when to treat an error
|
||||
as such an error.
|
||||
|
||||
This should be passed an exception which resulted from opening or
|
||||
reading a urllib Request. It returns True for any errors that could
|
||||
conceivably arise due to unavailable/poor network connections,
|
||||
firewall/connectivity issues, etc. These issues can often be safely
|
||||
ignored or presented to the user as general 'network-unavailable'
|
||||
states.
|
||||
firewall/connectivity issues, or other issues out of our control.
|
||||
These errors can often be safely ignored or presented to the user
|
||||
as general 'network-unavailable' states.
|
||||
"""
|
||||
import urllib.error
|
||||
import http.client
|
||||
import errno
|
||||
import socket
|
||||
if isinstance(
|
||||
exc,
|
||||
(urllib.error.URLError, ConnectionError, http.client.IncompleteRead,
|
||||
http.client.BadStatusLine, socket.timeout)):
|
||||
if isinstance(exc, (urllib.error.URLError, ConnectionError,
|
||||
http.client.IncompleteRead, http.client.BadStatusLine,
|
||||
http.client.RemoteDisconnected, socket.timeout)):
|
||||
|
||||
# Special case: although an HTTPError is a subclass of URLError,
|
||||
# we don't return True for it. It means we have successfully
|
||||
# communicated with the server but what we are asking for is
|
||||
# not there/etc.
|
||||
# we don't consider it a communication error. It generally means we
|
||||
# have successfully communicated with the server but what we are asking
|
||||
# for is not there/etc.
|
||||
if isinstance(exc, urllib.error.HTTPError):
|
||||
|
||||
# Special sub-case: appspot.com hosting seems to give 403 errors
|
||||
# (forbidden) to some countries. I'm assuming for legal reasons?..
|
||||
# Let's consider that a communication error since its out of our
|
||||
# control so we don't fill up logs with it.
|
||||
if exc.code == 403 and url is not None and '.appspot.com' in url:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if isinstance(exc, OSError):
|
||||
if exc.errno == 10051: # Windows unreachable network error.
|
||||
return True
|
||||
@ -106,18 +120,17 @@ def is_urllib_network_error(exc: BaseException) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def is_udp_network_error(exc: BaseException) -> bool:
|
||||
"""Is the provided exception a network-related error?
|
||||
def is_udp_communication_error(exc: BaseException) -> bool:
|
||||
"""Should this udp-related exception be considered a communication error?
|
||||
|
||||
This should be passed an exception which resulted from creating and
|
||||
using a socket.SOCK_DGRAM type socket. It should return True for any
|
||||
errors that could conceivably arise due to unavailable/poor network
|
||||
connections, firewall/connectivity issues, etc. These issues can often
|
||||
conditions, firewall/connectivity issues, etc. These issues can often
|
||||
be safely ignored or presented to the user as general
|
||||
'network-unavailable' states.
|
||||
"""
|
||||
import errno
|
||||
if isinstance(exc, ConnectionRefusedError):
|
||||
if isinstance(exc, ConnectionRefusedError | TimeoutError):
|
||||
return True
|
||||
if isinstance(exc, OSError):
|
||||
if exc.errno == 10051: # Windows unreachable network error.
|
||||
@ -140,8 +153,8 @@ def is_udp_network_error(exc: BaseException) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def is_asyncio_streams_network_error(exc: BaseException) -> bool:
|
||||
"""Is the provided exception a network-related error?
|
||||
def is_asyncio_streams_communication_error(exc: BaseException) -> bool:
|
||||
"""Should this streams error be considered a communication error?
|
||||
|
||||
This should be passed an exception which resulted from creating and
|
||||
using asyncio streams. It should return True for any errors that could
|
||||
@ -149,7 +162,6 @@ def is_asyncio_streams_network_error(exc: BaseException) -> bool:
|
||||
firewall/connectivity issues, etc. These issues can often be safely
|
||||
ignored or presented to the user as general 'connection-lost' events.
|
||||
"""
|
||||
import errno
|
||||
import ssl
|
||||
|
||||
if isinstance(exc, (
|
||||
|
||||
@ -56,6 +56,7 @@ class ErrorResponse(Response):
|
||||
OTHER = 0
|
||||
CLEAN = 1
|
||||
LOCAL = 2
|
||||
COMMUNICATION = 3
|
||||
|
||||
error_message: Annotated[str, IOAttrs('m')]
|
||||
error_type: Annotated[ErrorType, IOAttrs('e')] = ErrorType.OTHER
|
||||
|
||||
@ -9,7 +9,7 @@ from __future__ import annotations
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, TypeVar
|
||||
|
||||
from efro.error import CleanError, RemoteError
|
||||
from efro.error import CleanError, RemoteError, CommunicationError
|
||||
from efro.message._message import EmptyResponse, ErrorResponse
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -35,7 +35,7 @@ class MessageSender:
|
||||
def send_raw_message(self, message: str) -> str:
|
||||
# Actually send the message here.
|
||||
|
||||
# MyMessageSender class should provide overloads for send(), send_bg(),
|
||||
# MyMessageSender class should provide overloads for send(), send_async(),
|
||||
# etc. to ensure all sending happens with valid types.
|
||||
obj = MyClass()
|
||||
obj.msg.send(SomeMessageType())
|
||||
@ -54,7 +54,12 @@ class MessageSender:
|
||||
def send_method(
|
||||
self, call: Callable[[Any, str],
|
||||
str]) -> Callable[[Any, str], str]:
|
||||
"""Function decorator for setting raw send method."""
|
||||
"""Function decorator for setting raw send method.
|
||||
|
||||
Send methods take strings and should return strings.
|
||||
Any Exception raised during the send_method manifests as
|
||||
a CommunicationError for the message sender.
|
||||
"""
|
||||
assert self._send_raw_message_call is None
|
||||
self._send_raw_message_call = call
|
||||
return call
|
||||
@ -62,7 +67,12 @@ class MessageSender:
|
||||
def send_async_method(
|
||||
self, call: Callable[[Any, str], Awaitable[str]]
|
||||
) -> Callable[[Any, str], Awaitable[str]]:
|
||||
"""Function decorator for setting raw send-async method."""
|
||||
"""Function decorator for setting raw send-async method.
|
||||
|
||||
Send methods take strings and should return strings.
|
||||
Any Exception raised during the send_method manifests as
|
||||
a CommunicationError for the message sender.
|
||||
"""
|
||||
assert self._send_async_raw_message_call is None
|
||||
self._send_async_raw_message_call = call
|
||||
return call
|
||||
@ -123,7 +133,17 @@ class MessageSender:
|
||||
raise RuntimeError('send() is unimplemented for this type.')
|
||||
|
||||
msg_encoded = self._encode_message(bound_obj, message)
|
||||
response_encoded = self._send_raw_message_call(bound_obj, msg_encoded)
|
||||
try:
|
||||
response_encoded = self._send_raw_message_call(
|
||||
bound_obj, msg_encoded)
|
||||
except Exception as exc:
|
||||
# Any error in the raw send call gets recorded as either
|
||||
# a local or communication error.
|
||||
return ErrorResponse(
|
||||
error_message=f'Error in send async method: {exc}',
|
||||
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
||||
if isinstance(exc, CommunicationError) else
|
||||
ErrorResponse.ErrorType.LOCAL))
|
||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||
|
||||
async def send_split_part_1_async(self, bound_obj: Any,
|
||||
@ -139,9 +159,17 @@ class MessageSender:
|
||||
raise RuntimeError('send_async() is unimplemented for this type.')
|
||||
|
||||
msg_encoded = self._encode_message(bound_obj, message)
|
||||
response_encoded = await self._send_async_raw_message_call(
|
||||
bound_obj, msg_encoded)
|
||||
|
||||
try:
|
||||
response_encoded = await self._send_async_raw_message_call(
|
||||
bound_obj, msg_encoded)
|
||||
except Exception as exc:
|
||||
# Any error in the raw send call gets recorded as either
|
||||
# a local or communication error.
|
||||
return ErrorResponse(
|
||||
error_message=f'Error in send async method: {exc}',
|
||||
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
||||
if isinstance(exc, CommunicationError) else
|
||||
ErrorResponse.ErrorType.LOCAL))
|
||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||
|
||||
def send_split_part_2(self, message: Message,
|
||||
@ -183,8 +211,8 @@ class MessageSender:
|
||||
# If we got to this point, we successfully communicated
|
||||
# with the other end so errors represent protocol mismatches
|
||||
# or other invalid data. For now let's just log it but perhaps
|
||||
# we'd want to somehow embed it in the ErrorResponse to be raised
|
||||
# directly to the user later.
|
||||
# we'd want to somehow embed it in the ErrorResponse to be
|
||||
# available directly to the user later.
|
||||
logging.exception('Error decoding raw response')
|
||||
response = ErrorResponse(
|
||||
error_message=
|
||||
@ -208,6 +236,10 @@ class MessageSender:
|
||||
# Some error occurred. Raise a local Exception for it.
|
||||
if isinstance(raw_response, ErrorResponse):
|
||||
|
||||
if (raw_response.error_type is
|
||||
ErrorResponse.ErrorType.COMMUNICATION):
|
||||
raise CommunicationError(raw_response.error_message)
|
||||
|
||||
# If something went wrong on our end of the connection,
|
||||
# don't say it was a remote error.
|
||||
if raw_response.error_type is ErrorResponse.ErrorType.LOCAL:
|
||||
|
||||
@ -14,7 +14,8 @@ from threading import current_thread
|
||||
from typing import TYPE_CHECKING, Annotated
|
||||
|
||||
from efro.util import assert_never
|
||||
from efro.error import CommunicationError, is_asyncio_streams_network_error
|
||||
from efro.error import (CommunicationError,
|
||||
is_asyncio_streams_communication_error)
|
||||
from efro.dataclassio import (dataclass_to_json, dataclass_from_json,
|
||||
ioprepped, IOAttrs)
|
||||
|
||||
@ -596,7 +597,7 @@ class RPCEndpoint:
|
||||
if isinstance(exc, _KeepaliveTimeoutError):
|
||||
return True
|
||||
|
||||
return is_asyncio_streams_network_error(exc)
|
||||
return is_asyncio_streams_communication_error(exc)
|
||||
|
||||
def _check_env(self) -> None:
|
||||
# I was seeing that asyncio stuff wasn't working as expected if
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user