mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-31 11:46:58 +08:00
lang updates and cache functionality for LogHandler
This commit is contained in:
parent
3816f1dcb9
commit
d3f3679473
@ -420,8 +420,8 @@
|
||||
"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/e8/42/a43c158be7fa45f2c0c3d4b84a1f",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/5b/cf/4501b151257c3d8d6ee8d0497d14",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/d4/64/6fff42a428e5c775795c081474e6",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/e2/24/5e7ea9ca5c9de4d3b7a28e53564d",
|
||||
"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/f8/15/e1a2fa38697417bcf2cf19cd34ef",
|
||||
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/44/aa/c12568afb4558dc7f9f2fa155467",
|
||||
@ -431,17 +431,17 @@
|
||||
"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/72/80/d6395c8a168558750c0d79ce769b",
|
||||
"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/8f/73/093120ae2241d8f4b899ccda2d75",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/25/65/1cb03566e73811fc6e1b841d9072",
|
||||
"assets/build/ba_data/data/languages/filipino.json": "https://files.ballistica.net/cache/ba1/e9/07/b2dc862601bcd70701b083d43279",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/2e/48/b0a8fafc5e5436e99d9a3d697d23",
|
||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/ef/e6/d4909f571d7473fd04055728490e",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/8a/2a/b2bc00eed0608b2199b2bc379b2e",
|
||||
"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/50/e8/837be1324c8128507b3df89b689f",
|
||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/91/98/42701cd595c2f70b7484614a8f49",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/d8/f2/aa16bc336bd7660cc86c3264bfc4",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/e3/85/14e57e3f49505e5a190daf7fe276",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/23/3b/26e9be528460af952a11e98c3b68",
|
||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/1a/10/9563348e729d1e5c8ae8c9cbc1f2",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/a8/e9/171a904f1331fdb7b1918a0f2598",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/83/4a/ec10142ac479bf8d80455b47a62b",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/df/b1/b2c9ebaad5e873ebedd365726d3d",
|
||||
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/19/e9/59c891b1fb85f3ba9f19283c233d",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/da/95/36797ec53a697a04e55b225a701d",
|
||||
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/d7/06/9d70642d0a4d1e3b1c2149d7a17c",
|
||||
@ -452,7 +452,7 @@
|
||||
"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/94/1a/533bc718e676191bafc25e2dc98f",
|
||||
"assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/f7/df/7ba5f99c5c2c4c86fc0503fcf0b7",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/14/a0/783cc6da2d122e9a7482c6a5ef8c",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/9a/90/8e2ed626def09f88c3b9ab5215a3",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/ab/35/644e4239cfa62a597a905412b90c",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/53/9e/068074156b38bab7f732977a4031",
|
||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/25/13/b64b849fc9fedcc18d81f6e08c4d",
|
||||
@ -3995,26 +3995,26 @@
|
||||
"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/15/b2/0744afc264f1e55a5944bf8ae964",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8e/98/ea10bd892f89c7ba5aec76721667",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/aa/e4/7c73515c9044e051a5d07cb1e964",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ba/37/245e7c3dc79588d73a57f9f08b55",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/28/034d014eea6aeba4b67d51cfc262",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/77/df/c85dfe5cb062b6925da7df8e740c",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/58/6b/058b05227950f5d83f23b01617d1",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bd/31/02ecb4d8c3bea8eb68d92befdd9d",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/aa/9d/96555101ebf8b14223b7639cea5b",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/1d/9a/16feda78b815cbed47b89983c48e",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b0/31/f60dc64681a35406595ed4836f0a",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b5/44/eb4645945794253446c55dc682bc",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/43/56/592cd419bfad9cbbb6e3f57c1007",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/c6/55/0dfcc3d90a9cee9212e2e10a91b1",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/19/c6/994729e095b54e6963ac2d4bbd10",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ce/21/77cd76cd1b0307ae8cc7038152e7",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a9/e6/23835561d55b6c1d1862217fc115",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/21/3d/e0a1e20ae12dd7b5ba1d61aed074",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/be/b5/fc827900f411576b992fc15a25fc",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/6f/51/d6a0951b6ab9122dd99ef33d4427",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f3/e1/0ee9ade5e9943dc4749aa4cc2182",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/32/4e/a7c1b096c62864641a59e65e7778",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6a/f4/8b86611cbaa7237c8a52e8fe6428",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/13/f5/fa3c97269613316994f0c2134860",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f8/7a/87877003ee3a13ff7cbbf1ec76a2",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/81/0c/708a16fff55ee37338b2d87f7620",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4a/91/89523b8f155261e0045a6bb6e277",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a9/04/da76c8e848852fef1e58577f59e3",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/dd/ac/33aed9cc1396ccba2111dfed02f6",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/1a/5a/0f1e671137a2ec60c2df8e95e078",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/92/50/ec5fbb3f8b9f4a60934f2dacf180",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7c/77/a430bf182d5210792716b6dbd8ee",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ef/6b/de6c811fa70bf4d5d1cdfe49eaae",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/92/e0/b9b1053231d7323d185298f8caaa",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/08/ef/c70efcd89a666758437f0736d956",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9d/94/1f0d32c943b64ff558f28ad89653",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a6/fb/a6e6a78d7b04d547c9c716ff0a8e",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/5a/b0/d0e087fcdf1756a0b9b5bf805f10",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/34/fb/e6c9fb0e20af0ba3376ca2abba29",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/b1/8b/5ba626c39ef586f3ba4bfd508181",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d5/f6/d62e6e6d5e7fe1945f08ccbb9a8f",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/02/c5/44d0082442b06153a7d7dce4c8ce",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d0/00/61378fb26ddcbf023fd3c40e4ffb",
|
||||
@ -4031,14 +4031,14 @@
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ff/26/da4a58abecf5d9275477eaec0c17",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/62/5d/8658a206b8c9b741be2422162784",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fc/57/d59920e098d23a2d150c899cde29",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/fb/8e/3bb1c858451a447f1a102d77c281",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/ae/ad/13ae735e45d31d2944c89e8bdcec",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/e8/3e/6c2546278ad0428965a05c9bd536",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/d4/e5/0fe217cac5837cf663c7c7f1aa92",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/ea/38/a5082d73202113900166a1ebd15f",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/ba/1c/16df69d156e23ab29e2c84465bd7",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/9e/b0/91b2e0b1dbd4541543f3f147bc06",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/c1/04/ad892d77317be76bc8fa035f9e86",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/39/a1/bce547622da143fcf9ea970cd3ab",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/d6/f3/8ca052a667342e316fa09655bc51",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/e0/b4/99c403ccbfd0c4b9b071e656d480",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/11/a0/e06103dae63a4648850bd089aacb",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/77/17/99eba0c7d42a9452306f7927ae4e",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/92/da/2faf9031e7c5ba5a99dd9e0c609d",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/64/2a/1b30ee7b4e8238ec2ea16bcacdeb",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/41/92/35b689da32ee45a4e7483feae8f8",
|
||||
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/c0/32/b7907e3859a5c5013a3d97b6b523",
|
||||
"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"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
### 1.7.7 (build 20856, api 7, 2022-09-15)
|
||||
### 1.7.7 (build 20857, api 7, 2022-09-15)
|
||||
- Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread.
|
||||
- Improved logging of missing playlist game types.
|
||||
- Some ba.Lstr functionality can now be used in background threads.
|
||||
|
||||
@ -1 +1 @@
|
||||
76251027805752156826413428926087661089
|
||||
41453813326605937968225345803585801012
|
||||
@ -2518,11 +2518,12 @@ def screenmessage(message: str | ba.Lstr,
|
||||
Category: **General Utility Functions**
|
||||
|
||||
If 'top' is True, the message will go to the top message area.
|
||||
For 'top' messages, 'image' can be a texture to display alongside the
|
||||
message.
|
||||
If 'log' is True, the message will also be printed to the output log
|
||||
'clients' can be a list of client-ids the message should be sent to,
|
||||
or None to specify that everyone should receive it.
|
||||
For 'top' messages, 'image' must be a dict containing 'texture'
|
||||
and 'tint_texture' textures and 'tint_color' and 'tint2_color'
|
||||
colors. This defines an icon to display alongside the message.
|
||||
If 'log' is True, the message will also be submitted to the log.
|
||||
'clients' can be a list of client-ids the message should be sent
|
||||
to, or None to specify that everyone should receive it.
|
||||
If 'transient' is True, the message will not be included in the
|
||||
game-stream and thus will not show up when viewing replays.
|
||||
Currently the 'clients' option only works for transient messages.
|
||||
|
||||
@ -35,7 +35,8 @@ def bootstrap() -> None:
|
||||
log_handler = setup_logging(log_path=None,
|
||||
level=LogLevel.DEBUG,
|
||||
suppress_non_root_debug=True,
|
||||
log_stdout_stderr=True)
|
||||
log_stdout_stderr=True,
|
||||
cache_size_limit=1024 * 1024)
|
||||
|
||||
log_handler.add_callback(_on_log)
|
||||
|
||||
@ -43,7 +44,7 @@ def bootstrap() -> None:
|
||||
|
||||
# Give a soft warning if we're being used with a different binary
|
||||
# version than we expect.
|
||||
expected_build = 20856
|
||||
expected_build = 20857
|
||||
running_build: int = env['build_number']
|
||||
if running_build != expected_build:
|
||||
print(
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kAppBuildNumber = 20856;
|
||||
const int kAppBuildNumber = 20857;
|
||||
const char* kAppVersion = "1.7.7";
|
||||
|
||||
// Our standalone globals.
|
||||
|
||||
@ -19,9 +19,9 @@ namespace ballistica {
|
||||
|
||||
const int kMaxPartyNameCombinedSize = 25;
|
||||
|
||||
/// The Game Module generally runs on a dedicated thread; it manages
|
||||
/// all game logic, builds frame_defs to send to the graphics-server for
|
||||
/// rendering, etc.
|
||||
/// The logic subsystem of the app. This runs on a dedicated thread
|
||||
/// and is where high level app logic happens. Much app functionality
|
||||
/// including UI calls must be run on the logic thread.
|
||||
class Logic {
|
||||
public:
|
||||
Logic();
|
||||
|
||||
@ -988,14 +988,12 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
|
||||
"Category: **General Utility Functions**\n"
|
||||
"\n"
|
||||
"If 'top' is True, the message will go to the top message area.\n"
|
||||
"For 'top' messages, 'image' can be a texture to display alongside "
|
||||
"the\n"
|
||||
"message.\n"
|
||||
"If 'log' is True, the message will also be printed to the output "
|
||||
"log\n"
|
||||
"'clients' can be a list of client-ids the message should be sent "
|
||||
"to,\n"
|
||||
"or None to specify that everyone should receive it.\n"
|
||||
"For 'top' messages, 'image' must be a dict containing 'texture'\n"
|
||||
"and 'tint_texture' textures and 'tint_color' and 'tint2_color'\n"
|
||||
"colors. This defines an icon to display alongside the message.\n"
|
||||
"If 'log' is True, the message will also be submitted to the log.\n"
|
||||
"'clients' can be a list of client-ids the message should be sent\n"
|
||||
"to, or None to specify that everyone should receive it.\n"
|
||||
"If 'transient' is True, the message will not be included in the\n"
|
||||
"game-stream and thus will not show up when viewing replays.\n"
|
||||
"Currently the 'clients' option only works for transient messages."},
|
||||
|
||||
@ -70,7 +70,7 @@ namespace ballistica {
|
||||
|
||||
auto Python::LoggingCall(LogLevel loglevel, const std::string& msg) -> void {
|
||||
// If we've not yet captured our Python logging calls, stash this call away.
|
||||
// We'll submit all accumulated entries after we bootstrap python.
|
||||
// We'll submit all accumulated entries after we bootstrap Python.
|
||||
if (!objexists(ObjID::kLoggingCriticalCall)) {
|
||||
std::scoped_lock lock(early_log_lock_);
|
||||
early_logs_.emplace_back(std::make_pair(loglevel, msg));
|
||||
|
||||
@ -67,6 +67,21 @@ class LogEntry:
|
||||
time: Annotated[datetime.datetime, IOAttrs('t')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class LogArchive:
|
||||
"""Info and data for a log."""
|
||||
|
||||
# Total number of entries submitted to the log.
|
||||
log_size: Annotated[int, IOAttrs('t')]
|
||||
|
||||
# Offset for the entries contained here.
|
||||
# (10 means our first entry is the 10th in the log, etc.)
|
||||
start_index: Annotated[int, IOAttrs('c')]
|
||||
|
||||
entries: Annotated[list[LogEntry], IOAttrs('e')]
|
||||
|
||||
|
||||
class LogHandler(logging.Handler):
|
||||
"""Fancy-pants handler for logging output.
|
||||
|
||||
@ -83,7 +98,8 @@ class LogHandler(logging.Handler):
|
||||
def __init__(self,
|
||||
path: str | Path | None,
|
||||
echofile: TextIO | None,
|
||||
suppress_non_root_debug: bool = False):
|
||||
suppress_non_root_debug: bool = False,
|
||||
cache_size_limit: int = 0):
|
||||
super().__init__()
|
||||
# pylint: disable=consider-using-with
|
||||
self._file = (None
|
||||
@ -97,14 +113,20 @@ class LogHandler(logging.Handler):
|
||||
'stdout': None,
|
||||
'stderr': None
|
||||
}
|
||||
self._cache_size = 0
|
||||
assert cache_size_limit >= 0
|
||||
self._cache_size_limit = cache_size_limit
|
||||
self._cache: list[tuple[int, LogEntry]] = []
|
||||
self._cache_index_offset = 0
|
||||
self._cache_lock = Lock()
|
||||
self._printed_callback_error = False
|
||||
self._thread_bootstrapped = False
|
||||
self._thread = Thread(target=self._thread_main, daemon=True)
|
||||
self._thread.start()
|
||||
|
||||
# Spin until our thread has set up its basic stuff;
|
||||
# otherwise we could wind up trying to push stuff to our
|
||||
# event loop before the loop exists.
|
||||
# Spin until our thread is up and running; otherwise we could
|
||||
# wind up trying to push stuff to our event loop before the
|
||||
# loop exists.
|
||||
while not self._thread_bootstrapped:
|
||||
time.sleep(0.001)
|
||||
|
||||
@ -124,6 +146,37 @@ class LogHandler(logging.Handler):
|
||||
self._thread_bootstrapped = True
|
||||
self._event_loop.run_forever()
|
||||
|
||||
def get_archive(self,
|
||||
start_index: int = 0,
|
||||
max_entries: int | None = None) -> LogArchive:
|
||||
"""Build and return an archive of log entries.
|
||||
|
||||
This will only return entries that have been processed by the
|
||||
background thread so may not include just-submitted logs.
|
||||
Entries in the range [start_index:start_index+max_entries] that
|
||||
are still in the cache will be returned. Be aware that this may
|
||||
not be the full requested range.
|
||||
"""
|
||||
|
||||
assert start_index >= 0
|
||||
if max_entries is not None:
|
||||
assert max_entries >= 0
|
||||
with self._cache_lock:
|
||||
# Transform start_index to our present cache space.
|
||||
start_index -= self._cache_index_offset
|
||||
# Calc end-index in our present cache space.
|
||||
end_index = (len(self._cache)
|
||||
if max_entries is None else start_index + max_entries)
|
||||
|
||||
# Clamp both indexes to both ends of our present space.
|
||||
start_index = max(0, min(start_index, len(self._cache)))
|
||||
end_index = max(0, min(end_index, len(self._cache)))
|
||||
|
||||
return LogArchive(
|
||||
log_size=self._cache_index_offset + len(self._cache),
|
||||
start_index=start_index + self._cache_index_offset,
|
||||
entries=[e[1] for e in self._cache[start_index:end_index]])
|
||||
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
# Called by logging to send us records.
|
||||
# We simply package them up and ship them to our thread.
|
||||
@ -143,22 +196,23 @@ class LogHandler(logging.Handler):
|
||||
# didn't expect to be stringified.
|
||||
msg = self.format(record)
|
||||
|
||||
# Also print pretty colored output to our echo file (generally
|
||||
# stderr). We do this part here instead of in our bg thread
|
||||
# because the delay can throw off command line prompts or make
|
||||
# tight debugging harder.
|
||||
# Also immediately print pretty colored output to our echo file
|
||||
# (generally stderr). We do this part here instead of in our bg
|
||||
# thread because the delay can throw off command line prompts or
|
||||
# make tight debugging harder.
|
||||
if self._echofile is not None:
|
||||
cbegin: str
|
||||
cend: str
|
||||
cbegin, cend = LEVELNO_COLOR_CODES.get(record.levelno, ('', ''))
|
||||
self._echofile.write(f'{cbegin}{msg}{cend}\n')
|
||||
ends = LEVELNO_COLOR_CODES.get(record.levelno)
|
||||
if ends is not None:
|
||||
self._echofile.write(f'{ends[0]}{msg}{ends[1]}\n')
|
||||
else:
|
||||
self._echofile.write(f'{msg}\n')
|
||||
|
||||
self._event_loop.call_soon_threadsafe(
|
||||
tpartial(self._emit_in_loop, record.name, record.levelno,
|
||||
tpartial(self._emit_in_thread, record.name, record.levelno,
|
||||
record.created, msg))
|
||||
|
||||
def _emit_in_loop(self, name: str, levelno: int, created: float,
|
||||
message: str) -> None:
|
||||
def _emit_in_thread(self, name: str, levelno: int, created: float,
|
||||
message: str) -> None:
|
||||
try:
|
||||
self._emit_entry(
|
||||
LogEntry(name=name,
|
||||
@ -174,9 +228,9 @@ class LogHandler(logging.Handler):
|
||||
"""Send raw stdout/stderr output to the logger to be collated."""
|
||||
|
||||
self._event_loop.call_soon_threadsafe(
|
||||
tpartial(self._file_write_in_loop, name, output))
|
||||
tpartial(self._file_write_in_thread, name, output))
|
||||
|
||||
def _file_write_in_loop(self, name: str, output: str) -> None:
|
||||
def _file_write_in_thread(self, name: str, output: str) -> None:
|
||||
try:
|
||||
assert name in ('stdout', 'stderr')
|
||||
|
||||
@ -222,9 +276,26 @@ class LogHandler(logging.Handler):
|
||||
self._file_chunk_ship_task[name] = None
|
||||
|
||||
def _emit_entry(self, entry: LogEntry) -> None:
|
||||
# This runs in our bg event loop thread and does most of the work.
|
||||
assert current_thread() is self._thread
|
||||
|
||||
# Store to our cache.
|
||||
if self._cache_size_limit > 0:
|
||||
with self._cache_lock:
|
||||
# Do a rough calc of how many bytes this entry consumes.
|
||||
entry_size = sum(
|
||||
sys.getsizeof(x)
|
||||
for x in (entry, entry.name, entry.message, entry.level,
|
||||
entry.time))
|
||||
self._cache.append((entry_size, entry))
|
||||
self._cache_size += entry_size
|
||||
|
||||
# Prune old until we are back at or under our limit.
|
||||
while self._cache_size > self._cache_size_limit:
|
||||
popped = self._cache.pop(0)
|
||||
self._cache_size -= popped[0]
|
||||
self._cache_index_offset += 1
|
||||
|
||||
# Pass to callbacks.
|
||||
with self._callbacks_lock:
|
||||
for call in self._callbacks:
|
||||
try:
|
||||
@ -271,11 +342,12 @@ class FileLogEcho:
|
||||
def setup_logging(log_path: str | Path | None,
|
||||
level: LogLevel,
|
||||
suppress_non_root_debug: bool = False,
|
||||
log_stdout_stderr: bool = False) -> LogHandler:
|
||||
log_stdout_stderr: bool = False,
|
||||
cache_size_limit: int = 0) -> LogHandler:
|
||||
"""Set up our logging environment.
|
||||
|
||||
Returns the custom handler which can be used to fetch information
|
||||
about logs that have passed through it. (worst log-levels, etc.).
|
||||
about logs that have passed through it. (worst log-levels, caches, etc.).
|
||||
"""
|
||||
|
||||
lmap = {
|
||||
@ -295,7 +367,8 @@ def setup_logging(log_path: str | Path | None,
|
||||
loghandler = LogHandler(
|
||||
log_path,
|
||||
echofile=sys.stderr if sys.stderr.isatty() else None,
|
||||
suppress_non_root_debug=suppress_non_root_debug)
|
||||
suppress_non_root_debug=suppress_non_root_debug,
|
||||
cache_size_limit=cache_size_limit)
|
||||
|
||||
# Note: going ahead with force=True here so that we replace any
|
||||
# existing logger. Though we warn if it looks like we are doing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user