From 4d3f47c0faafa10d9428ef89749eb2a2d94fae00 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 24 Jan 2024 16:43:28 -0800 Subject: [PATCH] adopted override decorator for python layer --- .efrocachemap | 106 +++++++++--------- CHANGELOG.md | 11 +- src/assets/ba_data/python/babase/_app.py | 2 + src/assets/ba_data/python/babase/_apputils.py | 5 + .../ba_data/python/babase/_devconsole.py | 4 + .../ba_data/python/babase/_emptyappmode.py | 6 + src/assets/ba_data/python/babase/_env.py | 2 + src/assets/ba_data/python/babase/_general.py | 4 + src/assets/ba_data/python/babase/_language.py | 6 + src/assets/ba_data/python/babase/_login.py | 3 + src/assets/ba_data/python/babase/_plugin.py | 7 ++ src/assets/ba_data/python/babase/_ui.py | 4 + .../ba_data/python/baclassic/_benchmark.py | 2 + src/assets/ba_data/python/baclassic/_net.py | 2 + .../ba_data/python/baclassic/_subsystem.py | 5 + .../ba_data/python/baclassic/macmusicapp.py | 7 ++ .../ba_data/python/baclassic/osmusic.py | 7 ++ src/assets/ba_data/python/baenv.py | 2 +- .../ba_data/python/baplus/_subsystem.py | 8 +- .../python/bascenev1/_activitytypes.py | 9 ++ .../ba_data/python/bascenev1/_appmode.py | 7 ++ .../ba_data/python/bascenev1/_coopgame.py | 4 + .../ba_data/python/bascenev1/_coopsession.py | 5 + .../ba_data/python/bascenev1/_dependency.py | 2 + .../python/bascenev1/_dualteamsession.py | 2 + .../python/bascenev1/_freeforallsession.py | 2 + .../ba_data/python/bascenev1/_gameactivity.py | 6 + src/assets/ba_data/python/bascenev1/_level.py | 2 + src/assets/ba_data/python/bascenev1/_map.py | 3 + .../python/bascenev1/_multiteamsession.py | 4 + .../ba_data/python/bascenev1/_nodeactor.py | 4 + .../ba_data/python/bascenev1/_teamgame.py | 5 + .../python/bascenev1lib/activity/coopjoin.py | 2 + .../python/bascenev1lib/activity/coopscore.py | 5 + .../python/bascenev1lib/activity/drawscore.py | 3 + .../bascenev1lib/activity/dualteamscore.py | 3 + .../activity/freeforallvictory.py | 5 +- .../bascenev1lib/activity/multiteamjoin.py | 3 + .../bascenev1lib/activity/multiteamscore.py | 3 + .../bascenev1lib/activity/multiteamvictory.py | 3 + .../python/bascenev1lib/actor/background.py | 3 + .../ba_data/python/bascenev1lib/actor/bomb.py | 5 + .../bascenev1lib/actor/controlsguide.py | 3 + .../ba_data/python/bascenev1lib/actor/flag.py | 5 +- .../python/bascenev1lib/actor/image.py | 2 + .../bascenev1lib/actor/onscreencountdown.py | 2 + .../bascenev1lib/actor/onscreentimer.py | 2 + .../python/bascenev1lib/actor/playerspaz.py | 3 + .../python/bascenev1lib/actor/popuptext.py | 2 + .../python/bascenev1lib/actor/powerupbox.py | 3 + .../ba_data/python/bascenev1lib/actor/spaz.py | 8 +- .../python/bascenev1lib/actor/spazbot.py | 4 + .../ba_data/python/bascenev1lib/actor/text.py | 2 + .../python/bascenev1lib/actor/tipstext.py | 2 + .../python/bascenev1lib/actor/zoomtext.py | 2 + .../python/bascenev1lib/game/assault.py | 13 ++- .../bascenev1lib/game/capturetheflag.py | 14 ++- .../python/bascenev1lib/game/chosenone.py | 12 +- .../python/bascenev1lib/game/conquest.py | 14 ++- .../python/bascenev1lib/game/deathmatch.py | 13 ++- .../python/bascenev1lib/game/easteregghunt.py | 13 ++- .../python/bascenev1lib/game/elimination.py | 16 ++- .../python/bascenev1lib/game/football.py | 22 +++- .../python/bascenev1lib/game/hockey.py | 13 ++- .../python/bascenev1lib/game/keepaway.py | 13 ++- .../python/bascenev1lib/game/kingofthehill.py | 12 +- .../python/bascenev1lib/game/meteorshower.py | 11 +- .../python/bascenev1lib/game/ninjafight.py | 10 +- .../python/bascenev1lib/game/onslaught.py | 10 +- .../ba_data/python/bascenev1lib/game/race.py | 16 ++- .../python/bascenev1lib/game/runaround.py | 10 +- .../bascenev1lib/game/targetpractice.py | 13 ++- .../python/bascenev1lib/game/thelaststand.py | 9 +- .../ba_data/python/bascenev1lib/mainmenu.py | 4 + .../ba_data/python/bascenev1lib/maps.py | 59 ++++++++++ .../ba_data/python/bascenev1lib/tutorial.py | 5 + .../ba_data/python/bauiv1/_subsystem.py | 3 + src/assets/ba_data/python/bauiv1/_uitypes.py | 3 + .../python/bauiv1lib/account/viewer.py | 5 +- .../ba_data/python/bauiv1lib/achievements.py | 3 + .../python/bauiv1lib/characterpicker.py | 3 + .../ba_data/python/bauiv1lib/colorpicker.py | 4 + .../ba_data/python/bauiv1lib/fileselector.py | 3 + .../python/bauiv1lib/gather/abouttab.py | 3 + .../python/bauiv1lib/gather/manualtab.py | 11 +- .../python/bauiv1lib/gather/nearbytab.py | 6 +- .../python/bauiv1lib/gather/privatetab.py | 5 + .../python/bauiv1lib/gather/publictab.py | 7 ++ .../ba_data/python/bauiv1lib/getremote.py | 3 + .../ba_data/python/bauiv1lib/iconpicker.py | 3 + .../python/bauiv1lib/playlist/share.py | 3 + .../ba_data/python/bauiv1lib/playoptions.py | 2 + src/assets/ba_data/python/bauiv1lib/popup.py | 3 + src/assets/ba_data/python/bauiv1lib/qrcode.py | 5 +- .../python/bauiv1lib/resourcetypeinfo.py | 3 + .../python/bauiv1lib/teamnamescolors.py | 3 + .../python/bauiv1lib/tournamententry.py | 3 + .../python/bauiv1lib/tournamentscores.py | 3 + .../ba_data/python/bauiv1lib/trophies.py | 3 + src/ballistica/shared/ballistica.cc | 2 +- tests/test_efro/test_dataclassio.py | 3 + tests/test_efro/test_message.py | 3 + tools/bacommon/build.py | 2 +- tools/bacommon/cloud.py | 10 ++ tools/batools/build.py | 20 ++-- tools/batools/dummymodule.py | 5 + tools/efro/dataclassio/extras.py | 3 + tools/efro/error.py | 3 + tools/efro/log.py | 2 + tools/efro/message/_protocol.py | 1 + tools/efro/util.py | 8 +- tools/efrotools/jsontools.py | 4 + tools/efrotools/pybuild.py | 2 +- tools/efrotools/toolconfig.py | 2 +- 114 files changed, 686 insertions(+), 99 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index 47f74d23..398381a0 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -421,27 +421,27 @@ "build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26", "build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8", "build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55", - "build/assets/ba_data/data/langdata.json": "29a60e77c26b1f397617f8d8c8d652f9", + "build/assets/ba_data/data/langdata.json": "750e45f2f19a94a44703e3d31b9a8e96", "build/assets/ba_data/data/languages/arabic.json": "0db32e21b6d5337ccca478381744aa88", "build/assets/ba_data/data/languages/belarussian.json": "a112dfca3e188387516788bd8229c5b0", - "build/assets/ba_data/data/languages/chinese.json": "93f3ca9f90d86dc7c8d0923f5f11ef46", + "build/assets/ba_data/data/languages/chinese.json": "1360ffde06828b63ce4fe956c3c3cd1d", "build/assets/ba_data/data/languages/chinesetraditional.json": "319565f8a15667488f48dbce59278e39", "build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa", - "build/assets/ba_data/data/languages/czech.json": "c9d518a324870066b987b8f412881dd3", + "build/assets/ba_data/data/languages/czech.json": "7171420af6d662e3a47b64576850a384", "build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e", "build/assets/ba_data/data/languages/dutch.json": "b0900d572c9141897d53d6574c471343", "build/assets/ba_data/data/languages/english.json": "1c4037fea1066d39d6eced419f314f35", "build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880", - "build/assets/ba_data/data/languages/filipino.json": "0031cbb8eb6a638a94fb43c5d892346c", + "build/assets/ba_data/data/languages/filipino.json": "43e838754fe013b8bac75f75aef78cb3", "build/assets/ba_data/data/languages/french.json": "cc8ac601f5443dd539893728db983f5c", "build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad", "build/assets/ba_data/data/languages/gibberish.json": "b461539243e8efe3137137b886256ba7", "build/assets/ba_data/data/languages/greek.json": "287c0ec437b38772284ef9d3e4fb2fc3", - "build/assets/ba_data/data/languages/hindi.json": "8848f6b0caec0fcf9d85bc6e683809ec", + "build/assets/ba_data/data/languages/hindi.json": "5b6c8e988ffa84a7e26d120b6cd8e1a4", "build/assets/ba_data/data/languages/hungarian.json": "796a290a8c44a1e7635208c2ff5fdc6e", "build/assets/ba_data/data/languages/indonesian.json": "9103845242b572aa8ba48e24f81ddb68", "build/assets/ba_data/data/languages/italian.json": "f550810b6866ea9bcf1985b7228f8cff", - "build/assets/ba_data/data/languages/korean.json": "03fd99d5e1155e81053fc028f69df982", + "build/assets/ba_data/data/languages/korean.json": "4e3524327a0174250aff5e1ef4c0c597", "build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38", "build/assets/ba_data/data/languages/persian.json": "9728d631cf7d9ad3b209ae1244bb59c0", "build/assets/ba_data/data/languages/polish.json": "3a90b2d9e2c59305580c96f8098fc839", @@ -450,10 +450,10 @@ "build/assets/ba_data/data/languages/russian.json": "30d5f3d2415088e1fb6558fcd6ccfa98", "build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69", "build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef", - "build/assets/ba_data/data/languages/spanish.json": "08d9b39a519743da9a715c2524c3b6ca", + "build/assets/ba_data/data/languages/spanish.json": "e3e9ac8f96f52302a480c7e955aed71f", "build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac", "build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c", - "build/assets/ba_data/data/languages/thai.json": "77755219bbf5fb7eea0d6b226684f403", + "build/assets/ba_data/data/languages/thai.json": "9c425b420f0488a7f883da98947657ad", "build/assets/ba_data/data/languages/turkish.json": "2be25c89ca754341f27750e0d595f31e", "build/assets/ba_data/data/languages/ukrainian.json": "b54a38e93deebafa5706ba2d1f626892", "build/assets/ba_data/data/languages/venetian.json": "8e9714d98a85e428ce3543fc49188a46", @@ -950,7 +950,7 @@ "build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b", "build/assets/ba_data/python-site-packages/certifi/cacert.pem": "4422aed09ab445f7290df7d72a301a47", "build/assets/ba_data/python-site-packages/certifi/core.py": "1b505388f1475fabd1b60031f985271c", - "build/assets/ba_data/python-site-packages/typing_extensions.py": "2d974cad17a71505d86513d1322976a5", + "build/assets/ba_data/python-site-packages/typing_extensions.py": "188320d92e530be7ea345d3ce3be38de", "build/assets/ba_data/python-site-packages/yaml/__init__.py": "2b747e5772c203377222afc888ac6b71", "build/assets/ba_data/python-site-packages/yaml/composer.py": "cef871e1f5f99ba2a7c44941b70afb06", "build/assets/ba_data/python-site-packages/yaml/constructor.py": "8a15e361e34b79491c81553bb3534062", @@ -4060,50 +4060,50 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "c10468f9057fb8cd2e709c6e80def6e9", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "5516b57aae8220a2fd70eba1c16f8870", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "d9ce7ddd24986629636900f96f4222bb", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "e8e0be656ae7be7d6e1d17e748698dc9", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "a92a7cfb211f5b3a2fe0f4d654e08e36", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "3caf8d545a035d61a1243003ca393747", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "3ad3619c09d56d2ef16674ed491be57c", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "edadf7dd4af5e0ceae006b940ea5dbc9", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d3b5181d79b39f065e5606bb4aecaabc", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "8bfcdf2824cffd9fd3c687d8124577bd", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "04ebddddcb75119559140d7fa90ebd0d", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "3adc502be34f331121181bde43068c56", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "b8c93d439493340f0b073e1feb82c19e", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "32932c39b3411787d4774774c8c89065", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "624bbcfa0cd5722118cdd95951331b52", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "13434d81c0b527b4650f7f6ff0f2504f", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "6821b110792a519a4dd0df261b98a27c", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "0e4e320e63c13e2fc9dfdd6875cd15e9", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "0f4de05d8c4679612ac176e75e739f52", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "eca2fc0326e16691eb32e153a23d6b00", - "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "5fe258b43fa5226cc36c7d5ec01ae634", - "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "58c567a5574207cc12d9a79baa8a1dd6", - "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "5fe258b43fa5226cc36c7d5ec01ae634", - "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "58c567a5574207cc12d9a79baa8a1dd6", - "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "61dc6683f4cfae0d47374e2f9cf20714", - "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "96cb1662024c0b5c25a8f7d12514c5a7", - "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "61dc6683f4cfae0d47374e2f9cf20714", - "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "96cb1662024c0b5c25a8f7d12514c5a7", - "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "f4126afb38befff916e6b14c583a8fed", - "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "23479d054cfdb20a19e9dd73a980b05e", - "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "f4126afb38befff916e6b14c583a8fed", - "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "23479d054cfdb20a19e9dd73a980b05e", - "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "661a5a67cef33ff7cf3bd3a2dbaef3a4", - "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "86368a7a20ba8c687f59a6f248e2dbfc", - "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "776f5085781a71f7522717cce5332b8e", - "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "86368a7a20ba8c687f59a6f248e2dbfc", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "15bfb7b83525e22b559d70482723515d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "706088e9adc5392e83e0500720c48a4d", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "c97d4236e6ad7abd5469ae609b092cf2", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "0b9ae67ea21931d8279fae89fbc15e61", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "3f684648bb831c598850b74fda6485d1", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "188a678495c6f32d6b547648b1d050cd", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "54c208d519ea3a31d5a9ad60c55ff270", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "2399dc39ce72d88f6660c0d78f4f2442", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "26eea64d4509875c9a88da74f49e675c", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "0a39319a89364641f3bb0598821b4288", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "84567063607be0227ef779027e12d19d", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "f4458855192dedd13a28d36dc3962890", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "4c0679b0157c2dd63519e5225d99359d", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "335a3f06dc6dd361d6122fd9143124ae", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "041a300c9fa99c82395e1ebc66e81fe3", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "181145bf30e752991860acd0e44f972c", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "8531542c35242bcbffc0309cef10b2b8", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "48cdebbdea839f6b8fc8f5cb69d7f961", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "159003daac99048702c74120be565bad", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "51c9582a1efaae50e1c435c13c390855", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "d66c11ebe6d9035ea7e86b362f8505a1", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1f8113ffba1d000120bf83ac268c603b", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "6f2a68c0370061a2913278d97b039ecc", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "471e7f81fac96b4db752c5cdaeed7168", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "94916e80a9d7bc7801db666beceea026", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "1bc098ae93dd18143fb64ae5cbc33c19", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "da99cef03f12a6ff2c0065f4616262f2", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "14b67157a3bf57b9de067089476f79d5", + "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43", + "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "ee829cd5488e9750570dc6f602d65589", + "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "8709ad96140d71760c2f493ee8bd7c43", + "build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "ee829cd5488e9750570dc6f602d65589", + "build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "35fe69d96c154b97b534711dae9d8d3a", + "build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "2db876e543b3e93128ec421ea5cbb011", + "build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "35fe69d96c154b97b534711dae9d8d3a", + "build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "2db876e543b3e93128ec421ea5cbb011", + "build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "417ea0f30d203d5de0e235550fcd7ab8", + "build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "72d071e977c88454d0623c4a9fb34361", + "build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "417ea0f30d203d5de0e235550fcd7ab8", + "build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "72d071e977c88454d0623c4a9fb34361", + "build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "de1b228d95c47a7c296a853778715326", + "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "79117cbfdf695298e1d9ae997d990c4d", + "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "984f0990a8e4cca29a382d70e51cc051", + "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "79117cbfdf695298e1d9ae997d990c4d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "97a0aee0716397c0394c620b0cdc8cfa", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "5edf5fd129429079b24368da6c792c44", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "e453446a36102733a1f0db636fafb704", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "dfb843bbc924daf7a2e2a2eb6b4811df", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "09bb45bcbfad7c0f63b9494ceca669cc", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "c8d10517d61dc5c4d7c94a5eccecab4a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4944d18bb54894b0488cbdaa7b2ef06f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d17c4758367051e734601018b081f786", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/CHANGELOG.md b/CHANGELOG.md index f4aa736e..00f77a1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.33 (build 21760, api 8, 2024-01-16) +### 1.7.33 (build 21762, api 8, 2024-01-24) - Stress test input-devices are now a bit smarter; they won't press any buttons while UIs are up (this could cause lots of chaos if it happened). - Added a 'Show Demos When Idle' option in advanced settings. If enabled, the @@ -11,6 +11,15 @@ - Players now get points for killing bots with their own bombs by catching it and throwing it back at them. This is actually old logic but was disabled due to a logic flaw, but should be fixed now. (Thanks VinniTR!) +- Updated the 'Settings->Advanced->Enter Code' functionality to talk to the V2 + master server (V1 is still used as a fallback). +- Adopted the `@override` decorator in all Python code and set up Mypy to + enforce its usage. Currently `override` comes from `typing_extensions` module + but when we upgrade to Python 3.12 soon it will come from the standard + `typing` module. This decorator should be familiar to users of other + languages; I feel it helps keep logic more understandable and should help us + catch problems where a base class changes or removes a method and child + classes forget to adapt to the change. ### 1.7.32 (build 21741, api 8, 2023-12-20) - Fixed a screen message that no one will ever see (Thanks vishal332008?...) diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index 2b0191f1..f7fb9071 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -11,6 +11,7 @@ from typing import TYPE_CHECKING, TypeVar from concurrent.futures import ThreadPoolExecutor from functools import cached_property +from typing_extensions import override from efro.call import tpartial import _babase @@ -127,6 +128,7 @@ class App: statically in a spinoff project. """ + @override def app_mode_for_intent( self, intent: AppIntent ) -> type[AppMode] | None: diff --git a/src/assets/ba_data/python/babase/_apputils.py b/src/assets/ba_data/python/babase/_apputils.py index 59d76481..ce911c90 100644 --- a/src/assets/ba_data/python/babase/_apputils.py +++ b/src/assets/ba_data/python/babase/_apputils.py @@ -10,9 +10,11 @@ from threading import Thread from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override from efro.call import tpartial from efro.log import LogLevel from efro.dataclassio import ioprepped, dataclass_to_json, dataclass_from_json + import _babase from babase._appsubsystem import AppSubsystem @@ -386,6 +388,7 @@ class AppHealthMonitor(AppSubsystem): self._response = False self._first_check = True + @override def on_app_loading(self) -> None: # If any traceback dumps happened last run, log and clear them. log_dumped_app_state(from_previous_run=True) @@ -449,10 +452,12 @@ class AppHealthMonitor(AppSubsystem): self._first_check = False + @override def on_app_suspend(self) -> None: assert _babase.in_logic_thread() self._running = False + @override def on_app_unsuspend(self) -> None: assert _babase.in_logic_thread() self._running = True diff --git a/src/assets/ba_data/python/babase/_devconsole.py b/src/assets/ba_data/python/babase/_devconsole.py index fb63c9e7..47580b81 100644 --- a/src/assets/ba_data/python/babase/_devconsole.py +++ b/src/assets/ba_data/python/babase/_devconsole.py @@ -8,6 +8,8 @@ from typing import TYPE_CHECKING from dataclasses import dataclass import logging +from typing_extensions import override + import _babase if TYPE_CHECKING: @@ -96,6 +98,7 @@ class DevConsoleTab: class DevConsoleTabPython(DevConsoleTab): """The Python dev-console tab.""" + @override def refresh(self) -> None: self.python_terminal() @@ -103,6 +106,7 @@ class DevConsoleTabPython(DevConsoleTab): class DevConsoleTabTest(DevConsoleTab): """Test dev-console tab.""" + @override def refresh(self) -> None: import random diff --git a/src/assets/ba_data/python/babase/_emptyappmode.py b/src/assets/ba_data/python/babase/_emptyappmode.py index f3905b71..3573769a 100644 --- a/src/assets/ba_data/python/babase/_emptyappmode.py +++ b/src/assets/ba_data/python/babase/_emptyappmode.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override from bacommon.app import AppExperience import _babase @@ -18,15 +19,18 @@ if TYPE_CHECKING: class EmptyAppMode(AppMode): """An empty app mode that can be used as a fallback/etc.""" + @override @classmethod def get_app_experience(cls) -> AppExperience: return AppExperience.EMPTY + @override @classmethod def _supports_intent(cls, intent: AppIntent) -> bool: # We support default and exec intents currently. return isinstance(intent, AppIntentExec | AppIntentDefault) + @override def handle_intent(self, intent: AppIntent) -> None: if isinstance(intent, AppIntentExec): _babase.empty_app_mode_handle_intent_exec(intent.code) @@ -34,10 +38,12 @@ class EmptyAppMode(AppMode): assert isinstance(intent, AppIntentDefault) _babase.empty_app_mode_handle_intent_default() + @override def on_activate(self) -> None: # Let the native layer do its thing. _babase.on_empty_app_mode_activate() + @override def on_deactivate(self) -> None: # Let the native layer do its thing. _babase.on_empty_app_mode_deactivate() diff --git a/src/assets/ba_data/python/babase/_env.py b/src/assets/ba_data/python/babase/_env.py index 2af28c23..124caa27 100644 --- a/src/assets/ba_data/python/babase/_env.py +++ b/src/assets/ba_data/python/babase/_env.py @@ -9,6 +9,7 @@ import logging import warnings from typing import TYPE_CHECKING +from typing_extensions import override from efro.log import LogLevel if TYPE_CHECKING: @@ -216,6 +217,7 @@ def _feed_logs_to_babase(log_handler: LogHandler) -> None: class _CustomHelper: """Replacement 'help' that behaves better for our setup.""" + @override def __repr__(self) -> str: return 'Type help(object) for help about object.' diff --git a/src/assets/ba_data/python/babase/_general.py b/src/assets/ba_data/python/babase/_general.py index 206ac036..2d2738da 100644 --- a/src/assets/ba_data/python/babase/_general.py +++ b/src/assets/ba_data/python/babase/_general.py @@ -10,6 +10,7 @@ import logging import inspect from typing import TYPE_CHECKING, TypeVar, Protocol, NewType +from typing_extensions import override from efro.terminal import Clr import _babase @@ -178,6 +179,7 @@ class _WeakCall: def __call__(self, *args_extra: Any) -> Any: return self._call(*self._args + args_extra, **self._keywds) + @override def __str__(self) -> str: return ( '' diff --git a/src/assets/ba_data/python/babase/_language.py b/src/assets/ba_data/python/babase/_language.py index 059e60ab..3983a7a7 100644 --- a/src/assets/ba_data/python/babase/_language.py +++ b/src/assets/ba_data/python/babase/_language.py @@ -8,6 +8,8 @@ import json import logging from typing import TYPE_CHECKING, overload +from typing_extensions import override + import _babase from babase._appsubsystem import AppSubsystem @@ -217,6 +219,7 @@ class LanguageSubsystem(AppSubsystem): color=(0, 1, 0), ) + @override def do_apply_app_config(self) -> None: assert _babase.in_logic_thread() assert isinstance(_babase.app.config, dict) @@ -598,9 +601,11 @@ class Lstr: _error.print_exception('_get_json failed for', self.args) return 'JSON_ERR' + @override def __str__(self) -> str: return '' + @override def __repr__(self) -> str: return '' @@ -648,5 +653,6 @@ class AttrDict(dict): assert not isinstance(val, bytes) return val + @override def __setattr__(self, attr: str, value: Any) -> None: raise AttributeError() diff --git a/src/assets/ba_data/python/babase/_login.py b/src/assets/ba_data/python/babase/_login.py index 39cfa0ed..67968440 100644 --- a/src/assets/ba_data/python/babase/_login.py +++ b/src/assets/ba_data/python/babase/_login.py @@ -9,6 +9,7 @@ import logging from dataclasses import dataclass from typing import TYPE_CHECKING, final +from typing_extensions import override from bacommon.login import LoginType import _babase @@ -353,6 +354,7 @@ class LoginAdapterNative(LoginAdapter): self._sign_in_attempt_num = 123 self._sign_in_attempts: dict[int, Callable[[str | None], None]] = {} + @override def get_sign_in_token( self, completion_cb: Callable[[str | None], None] ) -> None: @@ -363,6 +365,7 @@ class LoginAdapterNative(LoginAdapter): self.login_type.value, attempt_id ) + @override def on_back_end_active_change(self, active: bool) -> None: _babase.login_adapter_back_end_active_change( self.login_type.value, active diff --git a/src/assets/ba_data/python/babase/_plugin.py b/src/assets/ba_data/python/babase/_plugin.py index 692840b1..d83050b9 100644 --- a/src/assets/ba_data/python/babase/_plugin.py +++ b/src/assets/ba_data/python/babase/_plugin.py @@ -8,6 +8,8 @@ import logging import importlib.util from typing import TYPE_CHECKING +from typing_extensions import override + import _babase from babase._appsubsystem import AppSubsystem @@ -158,6 +160,7 @@ class PluginSubsystem(AppSubsystem): if config_changed: _babase.app.config.commit() + @override def on_app_running(self) -> None: # Load up our plugins and go ahead and call their on_app_running # calls. @@ -170,6 +173,7 @@ class PluginSubsystem(AppSubsystem): _error.print_exception('Error in plugin on_app_running()') + @override def on_app_suspend(self) -> None: for plugin in self.active_plugins: try: @@ -179,6 +183,7 @@ class PluginSubsystem(AppSubsystem): _error.print_exception('Error in plugin on_app_suspend()') + @override def on_app_unsuspend(self) -> None: for plugin in self.active_plugins: try: @@ -188,6 +193,7 @@ class PluginSubsystem(AppSubsystem): _error.print_exception('Error in plugin on_app_unsuspend()') + @override def on_app_shutdown(self) -> None: for plugin in self.active_plugins: try: @@ -197,6 +203,7 @@ class PluginSubsystem(AppSubsystem): _error.print_exception('Error in plugin on_app_shutdown()') + @override def on_app_shutdown_complete(self) -> None: for plugin in self.active_plugins: try: diff --git a/src/assets/ba_data/python/babase/_ui.py b/src/assets/ba_data/python/babase/_ui.py index 6f6b0595..6457eadf 100644 --- a/src/assets/ba_data/python/babase/_ui.py +++ b/src/assets/ba_data/python/babase/_ui.py @@ -5,6 +5,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from babase._stringedit import StringEditAdapter import _babase @@ -24,9 +26,11 @@ class DevConsoleStringEditAdapter(StringEditAdapter): description, initial_text, max_length, screen_space_center ) + @override def _do_apply(self, new_text: str) -> None: _babase.set_dev_console_input_text(new_text) _babase.dev_console_input_adapter_finish() + @override def _do_cancel(self) -> None: _babase.dev_console_input_adapter_finish() diff --git a/src/assets/ba_data/python/baclassic/_benchmark.py b/src/assets/ba_data/python/baclassic/_benchmark.py index 42e64636..23033eef 100644 --- a/src/assets/ba_data/python/baclassic/_benchmark.py +++ b/src/assets/ba_data/python/baclassic/_benchmark.py @@ -7,6 +7,7 @@ import random from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override import babase import bascenev1 import _baclassic @@ -43,6 +44,7 @@ def run_cpu_benchmark() -> None: cfg['Graphics Quality'] = self._old_quality cfg.apply() + @override def on_player_request(self, player: bascenev1.SessionPlayer) -> bool: return False diff --git a/src/assets/ba_data/python/baclassic/_net.py b/src/assets/ba_data/python/baclassic/_net.py index a76258df..04d3fb6c 100644 --- a/src/assets/ba_data/python/baclassic/_net.py +++ b/src/assets/ba_data/python/baclassic/_net.py @@ -9,6 +9,7 @@ import threading from enum import Enum from typing import TYPE_CHECKING +from typing_extensions import override import babase import bascenev1 @@ -68,6 +69,7 @@ class MasterServerV1CallThread(threading.Thread): with self._context: self._callback(arg) + @override def run(self) -> None: # pylint: disable=consider-using-with # pylint: disable=too-many-branches diff --git a/src/assets/ba_data/python/baclassic/_subsystem.py b/src/assets/ba_data/python/baclassic/_subsystem.py index 755c4dd8..bb9bbadd 100644 --- a/src/assets/ba_data/python/baclassic/_subsystem.py +++ b/src/assets/ba_data/python/baclassic/_subsystem.py @@ -8,6 +8,7 @@ import random import logging import weakref +from typing_extensions import override from efro.dataclassio import dataclass_from_dict import babase import bauiv1 @@ -149,6 +150,7 @@ class ClassicSubsystem(babase.AppSubsystem): assert isinstance(self._env['legacy_user_agent_string'], str) return self._env['legacy_user_agent_string'] + @override def on_app_loading(self) -> None: from bascenev1lib.actor import spazappearance from bascenev1lib import maps as stdmaps @@ -230,13 +232,16 @@ class ClassicSubsystem(babase.AppSubsystem): self.accounts.on_app_loading() + @override def on_app_suspend(self) -> None: self.accounts.on_app_suspend() + @override def on_app_unsuspend(self) -> None: self.accounts.on_app_unsuspend() self.music.on_app_unsuspend() + @override def on_app_shutdown(self) -> None: self.music.on_app_shutdown() diff --git a/src/assets/ba_data/python/baclassic/macmusicapp.py b/src/assets/ba_data/python/baclassic/macmusicapp.py index 27b0e126..12fe6846 100644 --- a/src/assets/ba_data/python/baclassic/macmusicapp.py +++ b/src/assets/ba_data/python/baclassic/macmusicapp.py @@ -8,6 +8,7 @@ import threading from collections import deque from typing import TYPE_CHECKING +from typing_extensions import override import babase from baclassic._music import MusicPlayer @@ -27,6 +28,7 @@ class MacMusicAppMusicPlayer(MusicPlayer): self._thread = _MacMusicAppThread() self._thread.start() + @override def on_select_entry( self, callback: Callable[[Any], None], @@ -40,6 +42,7 @@ class MacMusicAppMusicPlayer(MusicPlayer): callback, current_entry, selection_target_name ) + @override def on_set_volume(self, volume: float) -> None: self._thread.set_volume(volume) @@ -47,6 +50,7 @@ class MacMusicAppMusicPlayer(MusicPlayer): """Asynchronously fetch the list of available iTunes playlists.""" self._thread.get_playlists(callback) + @override def on_play(self, entry: Any) -> None: assert babase.app.classic is not None music = babase.app.classic.music @@ -59,9 +63,11 @@ class MacMusicAppMusicPlayer(MusicPlayer): entry_type, ) + @override def on_stop(self) -> None: self._thread.play_playlist(None) + @override def on_app_shutdown(self) -> None: self._thread.shutdown() @@ -77,6 +83,7 @@ class _MacMusicAppThread(threading.Thread): self._current_playlist: str | None = None self._orig_volume: int | None = None + @override def run(self) -> None: """Run the Music.app thread.""" babase.set_thread_name('BA_MacMusicAppThread') diff --git a/src/assets/ba_data/python/baclassic/osmusic.py b/src/assets/ba_data/python/baclassic/osmusic.py index d808000d..f2198ce5 100644 --- a/src/assets/ba_data/python/baclassic/osmusic.py +++ b/src/assets/ba_data/python/baclassic/osmusic.py @@ -9,6 +9,7 @@ import logging import threading from typing import TYPE_CHECKING +from typing_extensions import override import babase from baclassic._music import MusicPlayer @@ -33,6 +34,7 @@ class OSMusicPlayer(MusicPlayer): # FIXME: should ask the C++ layer for these; just hard-coding for now. return ['mp3', 'ogg', 'm4a', 'wav', 'flac', 'mid'] + @override def on_select_entry( self, callback: Callable[[Any], None], @@ -48,9 +50,11 @@ class OSMusicPlayer(MusicPlayer): callback, current_entry, selection_target_name ) + @override def on_set_volume(self, volume: float) -> None: babase.music_player_set_volume(volume) + @override def on_play(self, entry: Any) -> None: assert babase.app.classic is not None music = babase.app.classic.music @@ -99,11 +103,13 @@ class OSMusicPlayer(MusicPlayer): self._actually_playing = True babase.music_player_play(result) + @override def on_stop(self) -> None: self._want_to_play = False self._actually_playing = False babase.music_player_stop() + @override def on_app_shutdown(self) -> None: babase.music_player_shutdown() @@ -120,6 +126,7 @@ class _PickFolderSongThread(threading.Thread): self._callback = callback self._path = path + @override def run(self) -> None: do_log_error = True try: diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index d1521b91..01c47c91 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21760 +TARGET_BALLISTICA_BUILD = 21762 TARGET_BALLISTICA_VERSION = '1.7.33' diff --git a/src/assets/ba_data/python/baplus/_subsystem.py b/src/assets/ba_data/python/baplus/_subsystem.py index cc657a00..567f3cd1 100644 --- a/src/assets/ba_data/python/baplus/_subsystem.py +++ b/src/assets/ba_data/python/baplus/_subsystem.py @@ -5,15 +5,18 @@ from __future__ import annotations from typing import TYPE_CHECKING -import _baplus +from typing_extensions import override from babase import AppSubsystem +import _baplus + if TYPE_CHECKING: from typing import Callable, Any - from baplus._cloud import CloudSubsystem from babase import AccountV2Subsystem + from baplus._cloud import CloudSubsystem + class PlusSubsystem(AppSubsystem): """Subsystem for plus functionality in the app. @@ -33,6 +36,7 @@ class PlusSubsystem(AppSubsystem): accounts: AccountV2Subsystem cloud: CloudSubsystem + @override def on_app_loading(self) -> None: _baplus.on_app_loading() self.accounts.on_app_loading() diff --git a/src/assets/ba_data/python/bascenev1/_activitytypes.py b/src/assets/ba_data/python/bascenev1/_activitytypes.py index c0e410e1..9b46b3eb 100644 --- a/src/assets/ba_data/python/bascenev1/_activitytypes.py +++ b/src/assets/ba_data/python/bascenev1/_activitytypes.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -34,11 +35,13 @@ class EndSessionActivity(Activity[EmptyPlayer, EmptyTeam]): self.inherits_vr_camera_offset = True self.inherits_vr_overlay_center = True + @override def on_transition_in(self) -> None: super().on_transition_in() babase.fade_screen(False) babase.lock_all_input() + @override def on_begin(self) -> None: # pylint: disable=cyclic-import @@ -77,6 +80,7 @@ class JoinActivity(Activity[EmptyPlayer, EmptyTeam]): self._tips_text: bascenev1.Actor | None = None self._join_info: JoinInfo | None = None + @override def on_transition_in(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.tipstext import TipsText @@ -110,6 +114,7 @@ class TransitionActivity(Activity[EmptyPlayer, EmptyTeam]): super().__init__(settings) self._background: bascenev1.Actor | None = None + @override def on_transition_in(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.background import Background @@ -119,6 +124,7 @@ class TransitionActivity(Activity[EmptyPlayer, EmptyTeam]): fade_time=0.5, start_faded=False, show_logo=False ) + @override def on_begin(self) -> None: super().on_begin() @@ -152,6 +158,7 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): self._custom_continue_message: babase.Lstr | None = None self._server_transitioning: bool | None = None + @override def on_player_join(self, player: EmptyPlayer) -> None: super().on_player_join(player) time_till_assign = max( @@ -164,6 +171,7 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): time_till_assign, babase.WeakCall(self._safe_assign, player) ) + @override def on_transition_in(self) -> None: from bascenev1lib.actor.tipstext import TipsText from bascenev1lib.actor.background import Background @@ -176,6 +184,7 @@ class ScoreScreenActivity(Activity[EmptyPlayer, EmptyTeam]): self._tips_text = TipsText() setmusic(self.default_music) + @override def on_begin(self) -> None: # pylint: disable=cyclic-import from bascenev1lib.actor.text import Text diff --git a/src/assets/ba_data/python/bascenev1/_appmode.py b/src/assets/ba_data/python/bascenev1/_appmode.py index 9408865d..481fb4e6 100644 --- a/src/assets/ba_data/python/bascenev1/_appmode.py +++ b/src/assets/ba_data/python/bascenev1/_appmode.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override from bacommon.app import AppExperience from babase import ( app, @@ -23,15 +24,18 @@ if TYPE_CHECKING: class SceneV1AppMode(AppMode): """Our app-mode.""" + @override @classmethod def get_app_experience(cls) -> AppExperience: return AppExperience.MELEE + @override @classmethod def _supports_intent(cls, intent: AppIntent) -> bool: # We support default and exec intents currently. return isinstance(intent, AppIntentExec | AppIntentDefault) + @override def handle_intent(self, intent: AppIntent) -> None: if isinstance(intent, AppIntentExec): _bascenev1.handle_app_intent_exec(intent.code) @@ -39,14 +43,17 @@ class SceneV1AppMode(AppMode): assert isinstance(intent, AppIntentDefault) _bascenev1.handle_app_intent_default() + @override def on_activate(self) -> None: # Let the native layer do its thing. _bascenev1.on_app_mode_activate() + @override def on_deactivate(self) -> None: # Let the native layer do its thing. _bascenev1.on_app_mode_deactivate() + @override def on_app_active_changed(self) -> None: # If we've gone inactive, bring up the main menu, which has the # side effect of pausing the action (when possible). diff --git a/src/assets/ba_data/python/bascenev1/_coopgame.py b/src/assets/ba_data/python/bascenev1/_coopgame.py index 2c684f85..e0af5158 100644 --- a/src/assets/ba_data/python/bascenev1/_coopgame.py +++ b/src/assets/ba_data/python/bascenev1/_coopgame.py @@ -6,6 +6,7 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING, TypeVar +from typing_extensions import override import babase import _bascenev1 @@ -31,6 +32,7 @@ class CoopGameActivity(GameActivity[PlayerT, TeamT]): # We can assume our session is a CoopSession. session: bascenev1.CoopSession + @override @classmethod def supports_session_type( cls, sessiontype: type[bascenev1.Session] @@ -49,6 +51,7 @@ class CoopGameActivity(GameActivity[PlayerT, TeamT]): self._life_warning_beep_timer: bascenev1.Timer | None = None self._warn_beeps_sound = _bascenev1.getsound('warnBeeps') + @override def on_begin(self) -> None: super().on_begin() @@ -139,6 +142,7 @@ class CoopGameActivity(GameActivity[PlayerT, TeamT]): ) vval -= 55 + @override def spawn_player_spaz( self, player: PlayerT, diff --git a/src/assets/ba_data/python/bascenev1/_coopsession.py b/src/assets/ba_data/python/bascenev1/_coopsession.py index 72a67919..f1d59ae4 100644 --- a/src/assets/ba_data/python/bascenev1/_coopsession.py +++ b/src/assets/ba_data/python/bascenev1/_coopsession.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -97,6 +98,7 @@ class CoopSession(Session): """Get the game instance currently being played.""" return self._current_game_instance + @override def should_allow_mid_activity_joins( self, activity: bascenev1.Activity ) -> bool: @@ -174,9 +176,11 @@ class CoopSession(Session): self._tutorial_activity = _bascenev1.newactivity(TutorialActivity) + @override def get_custom_menu_entries(self) -> list[dict[str, Any]]: return self._custom_menu_ui + @override def on_player_leave(self, sessionplayer: bascenev1.SessionPlayer) -> None: super().on_player_leave(sessionplayer) @@ -256,6 +260,7 @@ class CoopSession(Session): activity.end(results={'outcome': 'restart'}, force=True) # noinspection PyUnresolvedReferences + @override def on_activity_end( self, activity: bascenev1.Activity, results: Any ) -> None: diff --git a/src/assets/ba_data/python/bascenev1/_dependency.py b/src/assets/ba_data/python/bascenev1/_dependency.py index bbc956c0..0a2f49f2 100644 --- a/src/assets/ba_data/python/bascenev1/_dependency.py +++ b/src/assets/ba_data/python/bascenev1/_dependency.py @@ -7,6 +7,7 @@ from __future__ import annotations import weakref from typing import Generic, TypeVar, TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -313,6 +314,7 @@ class AssetPackage(DependencyComponent): self.package_id = entry.config print(f'LOADING ASSET PACKAGE {self.package_id}') + @override @classmethod def dep_is_present(cls, config: Any = None) -> bool: assert isinstance(config, str) diff --git a/src/assets/ba_data/python/bascenev1/_dualteamsession.py b/src/assets/ba_data/python/bascenev1/_dualteamsession.py index 4b4ab102..82807684 100644 --- a/src/assets/ba_data/python/bascenev1/_dualteamsession.py +++ b/src/assets/ba_data/python/bascenev1/_dualteamsession.py @@ -5,6 +5,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -32,6 +33,7 @@ class DualTeamSession(MultiTeamSession): babase.increment_analytics_count('Teams session start') super().__init__() + @override def _switch_to_score_screen(self, results: bascenev1.GameResults) -> None: # pylint: disable=cyclic-import from bascenev1lib.activity.multiteamvictory import ( diff --git a/src/assets/ba_data/python/bascenev1/_freeforallsession.py b/src/assets/ba_data/python/bascenev1/_freeforallsession.py index 6c71d1b4..2718377c 100644 --- a/src/assets/ba_data/python/bascenev1/_freeforallsession.py +++ b/src/assets/ba_data/python/bascenev1/_freeforallsession.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -53,6 +54,7 @@ class FreeForAllSession(MultiTeamSession): babase.increment_analytics_count('Free-for-all session start') super().__init__() + @override def _switch_to_score_screen(self, results: bascenev1.GameResults) -> None: # pylint: disable=cyclic-import from efro.util import asserttype diff --git a/src/assets/ba_data/python/bascenev1/_gameactivity.py b/src/assets/ba_data/python/bascenev1/_gameactivity.py index ad9bf0a5..1557ffc1 100644 --- a/src/assets/ba_data/python/bascenev1/_gameactivity.py +++ b/src/assets/ba_data/python/bascenev1/_gameactivity.py @@ -9,6 +9,7 @@ import random import logging from typing import TYPE_CHECKING, TypeVar +from typing_extensions import override import babase import _bascenev1 @@ -377,6 +378,7 @@ class GameActivity(Activity[PlayerT, TeamT]): """ return '' + @override def on_transition_in(self) -> None: super().on_transition_in() @@ -488,6 +490,7 @@ class GameActivity(Activity[PlayerT, TeamT]): self.end_game() + @override def on_begin(self) -> None: super().on_begin() @@ -536,12 +539,14 @@ class GameActivity(Activity[PlayerT, TeamT]): max(5, data_t[0]['timeRemaining']) ) + @override def on_player_join(self, player: PlayerT) -> None: super().on_player_join(player) # By default, just spawn a dude. self.spawn_player(player) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, PlayerDiedMessage): # pylint: disable=cyclic-import @@ -835,6 +840,7 @@ class GameActivity(Activity[PlayerT, TeamT]): animate(combine, 'input3', {0: 0, 1.0: 1, 4.0: 1, 5.0: 0}) _bascenev1.timer(5.0, tnode.delete) + @override def end( self, results: Any = None, delay: float = 0.0, force: bool = False ) -> None: diff --git a/src/assets/ba_data/python/bascenev1/_level.py b/src/assets/ba_data/python/bascenev1/_level.py index 725c962e..2f1906e6 100644 --- a/src/assets/ba_data/python/bascenev1/_level.py +++ b/src/assets/ba_data/python/bascenev1/_level.py @@ -7,6 +7,7 @@ import copy import weakref from typing import TYPE_CHECKING +from typing_extensions import override import babase if TYPE_CHECKING: @@ -38,6 +39,7 @@ class Level: self._index: int | None = None self._score_version_string: str | None = None + @override def __repr__(self) -> str: cls = type(self) return f"<{cls.__module__}.{cls.__name__} '{self._name}'>" diff --git a/src/assets/ba_data/python/bascenev1/_map.py b/src/assets/ba_data/python/bascenev1/_map.py index 818098fd..832632fc 100644 --- a/src/assets/ba_data/python/bascenev1/_map.py +++ b/src/assets/ba_data/python/bascenev1/_map.py @@ -6,6 +6,7 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bascenev1 @@ -353,9 +354,11 @@ class Map(Actor): return self.flag_points_default[:3] return self.flag_points[team_index % len(self.flag_points)][:3] + @override def exists(self) -> bool: return bool(self.node) + @override def handlemessage(self, msg: Any) -> Any: from bascenev1 import _messages diff --git a/src/assets/ba_data/python/bascenev1/_multiteamsession.py b/src/assets/ba_data/python/bascenev1/_multiteamsession.py index 2c787915..06a5a2e1 100644 --- a/src/assets/ba_data/python/bascenev1/_multiteamsession.py +++ b/src/assets/ba_data/python/bascenev1/_multiteamsession.py @@ -8,7 +8,9 @@ import random import logging from typing import TYPE_CHECKING +from typing_extensions import override import babase + import _bascenev1 from bascenev1._session import Session @@ -160,6 +162,7 @@ class MultiTeamSession(Session): """Returns which game in the series is currently being played.""" return self._game_number + @override def on_team_join(self, team: bascenev1.SessionTeam) -> None: team.customdata['previous_score'] = team.customdata['score'] = 0 @@ -178,6 +181,7 @@ class MultiTeamSession(Session): self._next_game_spec['settings'], ) + @override def on_activity_end( self, activity: bascenev1.Activity, results: Any ) -> None: diff --git a/src/assets/ba_data/python/bascenev1/_nodeactor.py b/src/assets/ba_data/python/bascenev1/_nodeactor.py index 2e9a1483..7b3551e7 100644 --- a/src/assets/ba_data/python/bascenev1/_nodeactor.py +++ b/src/assets/ba_data/python/bascenev1/_nodeactor.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from bascenev1._messages import DieMessage from bascenev1._actor import Actor @@ -28,6 +30,7 @@ class NodeActor(Actor): super().__init__() self.node = node + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, DieMessage): if self.node: @@ -35,5 +38,6 @@ class NodeActor(Actor): return None return super().handlemessage(msg) + @override def exists(self) -> bool: return bool(self.node) diff --git a/src/assets/ba_data/python/bascenev1/_teamgame.py b/src/assets/ba_data/python/bascenev1/_teamgame.py index d438dbca..e835bd0e 100644 --- a/src/assets/ba_data/python/bascenev1/_teamgame.py +++ b/src/assets/ba_data/python/bascenev1/_teamgame.py @@ -7,6 +7,7 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING, TypeVar +from typing_extensions import override import babase import _bascenev1 @@ -35,6 +36,7 @@ class TeamGameActivity(GameActivity[PlayerT, TeamT]): bascenev1.Player has their own bascenev1.Team) """ + @override @classmethod def supports_session_type( cls, sessiontype: type[bascenev1.Session] @@ -57,6 +59,7 @@ class TeamGameActivity(GameActivity[PlayerT, TeamT]): if isinstance(self.session, FreeForAllSession): self.show_kill_points = False + @override def on_transition_in(self) -> None: # pylint: disable=cyclic-import from bascenev1._coopsession import CoopSession @@ -85,6 +88,7 @@ class TeamGameActivity(GameActivity[PlayerT, TeamT]): ).autoretain() setattr(self.session, attrname, True) + @override def on_begin(self) -> None: super().on_begin() try: @@ -104,6 +108,7 @@ class TeamGameActivity(GameActivity[PlayerT, TeamT]): except Exception: logging.exception('Error in on_begin.') + @override def spawn_player_spaz( self, player: PlayerT, diff --git a/src/assets/ba_data/python/bascenev1lib/activity/coopjoin.py b/src/assets/ba_data/python/bascenev1lib/activity/coopjoin.py index 0777e8f1..55f3fd8e 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/coopjoin.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/coopjoin.py @@ -4,6 +4,7 @@ from __future__ import annotations +from typing_extensions import override import bascenev1 as bs @@ -18,6 +19,7 @@ class CoopJoinActivity(bs.JoinActivity): session = self.session assert isinstance(session, bs.CoopSession) + @override def on_transition_in(self) -> None: from bascenev1lib.actor.controlsguide import ControlsGuide from bascenev1lib.actor.text import Text diff --git a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py index 8b335a19..a88c418b 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/coopscore.py @@ -9,6 +9,7 @@ import random import logging from typing import TYPE_CHECKING +from typing_extensions import override from bacommon.login import LoginType import bascenev1 as bs import bauiv1 as bui @@ -186,6 +187,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): self._victory: bool = settings['outcome'] == 'victory' + @override def __del__(self) -> None: super().__del__() @@ -194,6 +196,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): with bui.ContextRef.empty(): bui.containerwidget(edit=self._root_ui, transition='out_left') + @override def on_transition_in(self) -> None: from bascenev1lib.actor import background # FIXME NO BSSTD @@ -574,6 +577,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): self._player_press, ) + @override def on_player_join(self, player: bs.Player) -> None: super().on_player_join(player) @@ -585,6 +589,7 @@ class CoopScoreScreen(bs.Activity[bs.Player, bs.Team]): bs.timer(time_till_assign, bs.WeakCall(self._safe_assign, player)) + @override def on_begin(self) -> None: # FIXME: Clean this up. # pylint: disable=too-many-statements diff --git a/src/assets/ba_data/python/bascenev1lib/activity/drawscore.py b/src/assets/ba_data/python/bascenev1lib/activity/drawscore.py index 2d260dfd..d6e1b289 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/drawscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/drawscore.py @@ -4,7 +4,9 @@ from __future__ import annotations +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity from bascenev1lib.actor.zoomtext import ZoomText @@ -14,6 +16,7 @@ class DrawScoreScreenActivity(MultiTeamScoreScreenActivity): default_music = None # Awkward silence... + @override def on_begin(self) -> None: bs.set_analytics_screen('Draw Score Screen') super().on_begin() diff --git a/src/assets/ba_data/python/bascenev1lib/activity/dualteamscore.py b/src/assets/ba_data/python/bascenev1lib/activity/dualteamscore.py index c369e17b..2df370bd 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/dualteamscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/dualteamscore.py @@ -4,7 +4,9 @@ from __future__ import annotations +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity from bascenev1lib.actor.zoomtext import ZoomText @@ -17,6 +19,7 @@ class TeamVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): self._winner: bs.SessionTeam = settings['winner'] assert isinstance(self._winner, bs.SessionTeam) + @override def on_begin(self) -> None: bs.set_analytics_screen('Teams Score Screen') super().on_begin() diff --git a/src/assets/ba_data/python/bascenev1lib/activity/freeforallvictory.py b/src/assets/ba_data/python/bascenev1lib/activity/freeforallvictory.py index 45d116ac..cf82d4ad 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/freeforallvictory.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/freeforallvictory.py @@ -6,9 +6,11 @@ from __future__ import annotations from typing import TYPE_CHECKING -from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity +from typing_extensions import override import bascenev1 as bs +from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity + if TYPE_CHECKING: from typing import Any @@ -23,6 +25,7 @@ class FreeForAllVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): self.transition_time = 0.5 self._cymbal_sound = bs.getsound('cymbal') + @override def on_begin(self) -> None: # pylint: disable=too-many-locals # pylint: disable=too-many-statements diff --git a/src/assets/ba_data/python/bascenev1lib/activity/multiteamjoin.py b/src/assets/ba_data/python/bascenev1lib/activity/multiteamjoin.py index 2870c1fd..ff8f74be 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/multiteamjoin.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/multiteamjoin.py @@ -4,7 +4,9 @@ from __future__ import annotations +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.actor.text import Text @@ -15,6 +17,7 @@ class MultiTeamJoinActivity(bs.JoinActivity): super().__init__(settings) self._next_up_text: Text | None = None + @override def on_transition_in(self) -> None: from bascenev1lib.actor.controlsguide import ControlsGuide diff --git a/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py b/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py index ef2ba012..7b754014 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/multiteamscore.py @@ -3,7 +3,9 @@ """Functionality related to teams mode score screen.""" from __future__ import annotations +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.actor.text import Text from bascenev1lib.actor.image import Image @@ -18,6 +20,7 @@ class MultiTeamScoreScreenActivity(bs.ScoreScreenActivity): self._show_up_next: bool = True + @override def on_begin(self) -> None: super().on_begin() session = self.session diff --git a/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py b/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py index 203f0516..afc2a26b 100644 --- a/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py +++ b/src/assets/ba_data/python/bascenev1lib/activity/multiteamvictory.py @@ -4,7 +4,9 @@ from __future__ import annotations +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.activity.multiteamscore import MultiTeamScoreScreenActivity @@ -22,6 +24,7 @@ class TeamSeriesVictoryScoreScreenActivity(MultiTeamScoreScreenActivity): self._tips_text = None self._default_show_tips = False + @override def on_begin(self) -> None: # pylint: disable=too-many-branches # pylint: disable=too-many-locals diff --git a/src/assets/ba_data/python/bascenev1lib/actor/background.py b/src/assets/ba_data/python/bascenev1lib/actor/background.py index 2ad629a2..d5625a27 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/background.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/background.py @@ -9,6 +9,7 @@ import weakref import logging from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -104,6 +105,7 @@ class Background(bs.Actor): timeval += random.random() * 0.1 bs.animate(cmb, 'input1', keys, loop=True) + @override def __del__(self) -> None: # Normal actors don't get sent DieMessages when their # activity is shutting down, but we still need to do so @@ -138,6 +140,7 @@ class Background(bs.Actor): ) bs.timer(self.fade_time + 0.1, self.node.delete) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/bomb.py b/src/assets/ba_data/python/bascenev1lib/actor/bomb.py index 00cb4e76..058057d0 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/bomb.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/bomb.py @@ -10,7 +10,9 @@ from __future__ import annotations import random from typing import TYPE_CHECKING, TypeVar +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.gameutils import SharedObjects if TYPE_CHECKING: @@ -661,6 +663,7 @@ class Blast(bs.Actor): bs.timer(0.4, _extra_debris_sound) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired @@ -935,6 +938,7 @@ class Bomb(bs.Actor): else None ) + @override def on_expire(self) -> None: super().on_expire() @@ -1140,6 +1144,7 @@ class Bomb(bs.Actor): if msg.srcnode: pass + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, ExplodeMessage): self.explode() diff --git a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py index 23c4a977..f3068f0e 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/controlsguide.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -547,9 +548,11 @@ class ControlsGuide(bs.Actor): self._update_timer = None self._dead = True + @override def exists(self) -> bool: return not self._dead + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/flag.py b/src/assets/ba_data/python/bascenev1lib/actor/flag.py index 7c8f5364..cd24c9ef 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/flag.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/flag.py @@ -7,9 +7,11 @@ from __future__ import annotations from dataclasses import dataclass from typing import TYPE_CHECKING -from bascenev1lib.gameutils import SharedObjects +from typing_extensions import override import bascenev1 as bs +from bascenev1lib.gameutils import SharedObjects + if TYPE_CHECKING: from typing import Any, Sequence @@ -328,6 +330,7 @@ class Flag(bs.Actor): 1.0, bs.WeakCall(self._hide_score_text) ) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/image.py b/src/assets/ba_data/python/bascenev1lib/actor/image.py index 4fc61bfa..00e71d0c 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/image.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/image.py @@ -7,6 +7,7 @@ from __future__ import annotations from enum import Enum from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -165,6 +166,7 @@ class Image(bs.Actor): bs.WeakCall(self.handlemessage, bs.DieMessage()), ) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/onscreencountdown.py b/src/assets/ba_data/python/bascenev1lib/actor/onscreencountdown.py index 7c1a9042..68c477b6 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/onscreencountdown.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/onscreencountdown.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -72,6 +73,7 @@ class OnScreenCountdown(bs.Actor): ) self._timer = bs.Timer(1.0, self._update, repeat=True) + @override def on_expire(self) -> None: super().on_expire() diff --git a/src/assets/ba_data/python/bascenev1lib/actor/onscreentimer.py b/src/assets/ba_data/python/bascenev1lib/actor/onscreentimer.py index 6f3b8dfa..192fecc2 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/onscreentimer.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/onscreentimer.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING import logging +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -93,6 +94,7 @@ class OnScreenTimer(bs.Actor): """Shortcut for start time in seconds.""" return self.getstarttime() + @override def handlemessage(self, msg: Any) -> Any: # if we're asked to die, just kill our node/timer if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py b/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py index 4902e57f..2ea3ead7 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/playerspaz.py @@ -6,7 +6,9 @@ from __future__ import annotations from typing import TYPE_CHECKING, TypeVar, overload +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.actor.spaz import Spaz if TYPE_CHECKING: @@ -183,6 +185,7 @@ class PlayerSpaz(Spaz): ' non-connected player' ) + @override def handlemessage(self, msg: Any) -> Any: # FIXME: Tidy this up. # pylint: disable=too-many-branches diff --git a/src/assets/ba_data/python/bascenev1lib/actor/popuptext.py b/src/assets/ba_data/python/bascenev1lib/actor/popuptext.py index c5c1dccd..6fdd41d6 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/popuptext.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/popuptext.py @@ -7,6 +7,7 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -118,6 +119,7 @@ class PopupText(bs.Actor): lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage()) ) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/powerupbox.py b/src/assets/ba_data/python/bascenev1lib/actor/powerupbox.py index 893cb2df..1b95e4df 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/powerupbox.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/powerupbox.py @@ -7,7 +7,9 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.gameutils import SharedObjects if TYPE_CHECKING: @@ -278,6 +280,7 @@ class PowerupBox(bs.Actor): if self.node: self.node.flashing = True + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired diff --git a/src/assets/ba_data/python/bascenev1lib/actor/spaz.py b/src/assets/ba_data/python/bascenev1lib/actor/spaz.py index 71a31a4c..ad914b8c 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/spaz.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/spaz.py @@ -9,11 +9,13 @@ import random import logging from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.bomb import Bomb, Blast from bascenev1lib.actor.powerupbox import PowerupBoxFactory from bascenev1lib.actor.spazfactory import SpazFactory from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence, Callable @@ -228,9 +230,11 @@ class Spaz(bs.Actor): self.punch_callback: Callable[[Spaz], Any] | None = None self.pick_up_powerup_callback: Callable[[Spaz], Any] | None = None + @override def exists(self) -> bool: return bool(self.node) + @override def on_expire(self) -> None: super().on_expire() @@ -249,6 +253,7 @@ class Spaz(bs.Actor): assert not self.expired self._dropped_bomb_callbacks.append(call) + @override def is_alive(self) -> bool: """ Method override; returns whether ol' spaz is still kickin'. @@ -694,6 +699,7 @@ class Spaz(bs.Actor): else: self.shield_decay_timer = None + @override def handlemessage(self, msg: Any) -> Any: # pylint: disable=too-many-return-statements # pylint: disable=too-many-statements diff --git a/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py b/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py index 75d0eeb3..bdd8c271 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/spazbot.py @@ -10,6 +10,7 @@ import weakref import logging from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs from bascenev1lib.actor.spaz import Spaz @@ -489,6 +490,7 @@ class SpazBot(Spaz): self.on_punch_press() self.on_punch_release() + @override def on_punched(self, damage: int) -> None: """ Method override; sends bs.SpazBotPunchedMessage @@ -496,6 +498,7 @@ class SpazBot(Spaz): """ bs.getactivity().handlemessage(SpazBotPunchedMessage(self, damage)) + @override def on_expire(self) -> None: super().on_expire() @@ -503,6 +506,7 @@ class SpazBot(Spaz): # no chance of them keeping activities or other things alive. self.update_callback = None + @override def handlemessage(self, msg: Any) -> Any: # pylint: disable=too-many-branches assert not self.expired diff --git a/src/assets/ba_data/python/bascenev1lib/actor/text.py b/src/assets/ba_data/python/bascenev1lib/actor/text.py index 1a274d64..15698510 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/text.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/text.py @@ -7,6 +7,7 @@ from __future__ import annotations from enum import Enum from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -221,6 +222,7 @@ class Text(bs.Actor): bs.WeakCall(self.handlemessage, bs.DieMessage()), ) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py b/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py index ede00802..7a6335fc 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/tipstext.py @@ -6,6 +6,7 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -95,6 +96,7 @@ class TipsText(bs.Actor): ) self.node.text = next_tip + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/actor/zoomtext.py b/src/assets/ba_data/python/bascenev1lib/actor/zoomtext.py index e50a16a9..12cdb757 100644 --- a/src/assets/ba_data/python/bascenev1lib/actor/zoomtext.py +++ b/src/assets/ba_data/python/bascenev1lib/actor/zoomtext.py @@ -8,6 +8,7 @@ import random import logging from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs if TYPE_CHECKING: @@ -158,6 +159,7 @@ class ZoomText(bs.Actor): if lifespan is not None: bs.timer(lifespan, bs.WeakCall(self.handlemessage, bs.DieMessage())) + @override def handlemessage(self, msg: Any) -> Any: assert not self.expired if isinstance(msg, bs.DieMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/game/assault.py b/src/assets/ba_data/python/bascenev1lib/game/assault.py index 183a017f..12eb1229 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/assault.py +++ b/src/assets/ba_data/python/bascenev1lib/game/assault.py @@ -10,11 +10,13 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.flag import Flag from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -71,10 +73,12 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): bs.BoolSetting('Epic Mode', default=False), ] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -96,16 +100,19 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH ) + @override def get_instance_description(self) -> str | Sequence: if self._score_to_win == 1: return 'Touch the enemy flag.' return 'Touch the enemy flag ${ARG1} times.', self._score_to_win + @override def get_instance_description_short(self) -> str | Sequence: if self._score_to_win == 1: return 'touch 1 flag' return 'touch ${ARG1} flags', self._score_to_win + @override def create_team(self, sessionteam: bs.SessionTeam) -> Team: shared = SharedObjects.get() base_pos = self.map.get_flag_position(sessionteam.id) @@ -151,16 +158,19 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): return team + @override def on_team_join(self, team: Team) -> None: # Can't do this in create_team because the team's color/etc. have # not been wired up yet at that point. self._update_scoreboard() + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) self.setup_standard_powerup_drops() + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): super().handlemessage(msg) # Augment standard. @@ -249,6 +259,7 @@ class AssaultGame(bs.TeamGameActivity[Player, Team]): if player_team.score >= self._score_to_win: self.end_game() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: diff --git a/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py b/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py index 4e5da2d6..837c3be1 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py +++ b/src/assets/ba_data/python/bascenev1lib/game/capturetheflag.py @@ -10,6 +10,9 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.flag import ( @@ -19,7 +22,6 @@ from bascenev1lib.actor.flag import ( FlagDroppedMessage, FlagDiedMessage, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -141,10 +143,12 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): bs.BoolSetting('Epic Mode', default=False), ] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -173,16 +177,19 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FLAG_CATCHER ) + @override def get_instance_description(self) -> str | Sequence: if self._score_to_win == 1: return 'Steal the enemy flag.' return 'Steal the enemy flag ${ARG1} times.', self._score_to_win + @override def get_instance_description_short(self) -> str | Sequence: if self._score_to_win == 1: return 'return 1 flag' return 'return ${ARG1} flags', self._score_to_win + @override def create_team(self, sessionteam: bs.SessionTeam) -> Team: # Create our team instance and its initial values. @@ -272,12 +279,14 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): return team + @override def on_team_join(self, team: Team) -> None: # Can't do this in create_team because the team's color/etc. have # not been wired up yet at that point. self._spawn_flag_for_team(team) self._update_scoreboard() + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) @@ -406,6 +415,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): if team.score >= self._score_to_win: self.end_game() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -532,6 +542,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): bs.animate(light, 'intensity', {0.0: 0, 0.25: 2.0, 0.5: 0}, loop=True) bs.timer(length, light.delete) + @override def spawn_player_spaz( self, player: Player, @@ -576,6 +587,7 @@ class CaptureTheFlagGame(bs.TeamGameActivity[Player, Team]): team, team.score, self._score_to_win ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): super().handlemessage(msg) # Augment standard behavior. diff --git a/src/assets/ba_data/python/bascenev1lib/game/chosenone.py b/src/assets/ba_data/python/bascenev1lib/game/chosenone.py index 81576190..aba373d7 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/chosenone.py +++ b/src/assets/ba_data/python/bascenev1lib/game/chosenone.py @@ -10,11 +10,13 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.flag import Flag from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -83,6 +85,7 @@ class ChosenOneGame(bs.TeamGameActivity[Player, Team]): ] scoreconfig = bs.ScoreConfig(label='Time Held') + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -121,20 +124,25 @@ class ChosenOneGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.CHOSEN_ONE ) + @override def get_instance_description(self) -> str | Sequence: return 'There can be only one.' + @override def create_team(self, sessionteam: bs.SessionTeam) -> Team: return Team(time_remaining=self._chosen_one_time) + @override def on_team_join(self, team: Team) -> None: self._update_scoreboard() + @override def on_player_leave(self, player: Player) -> None: super().on_player_leave(player) if self._get_chosen_one_player() is player: self._set_chosen_one_player(None) + @override def on_begin(self) -> None: super().on_begin() shared = SharedObjects.get() @@ -251,6 +259,7 @@ class ChosenOneGame(bs.TeamGameActivity[Player, Team]): logging.error('got nonexistent player as chosen one in _tick') self._set_chosen_one_player(None) + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -335,6 +344,7 @@ class ChosenOneGame(bs.TeamGameActivity[Player, Team]): 'position', light.node, 'position' ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. diff --git a/src/assets/ba_data/python/bascenev1lib/game/conquest.py b/src/assets/ba_data/python/bascenev1lib/game/conquest.py index 8b1589c1..d50041f6 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/conquest.py +++ b/src/assets/ba_data/python/bascenev1lib/game/conquest.py @@ -10,12 +10,14 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.flag import Flag from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.gameutils import SharedObjects from bascenev1lib.actor.respawnicon import RespawnIcon -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -108,10 +110,12 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): bs.BoolSetting('Epic Mode', default=False), ] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -143,16 +147,20 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): ), ) + @override def get_instance_description(self) -> str | Sequence: return 'Secure all ${ARG1} flags.', len(self.map.flag_points) + @override def get_instance_description_short(self) -> str | Sequence: return 'secure all ${ARG1} flags', len(self.map.flag_points) + @override def on_team_join(self, team: Team) -> None: if self.has_begun(): self._update_scores() + @override def on_player_join(self, player: Player) -> None: player.respawn_timer = None @@ -160,6 +168,7 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): if player.team.flags_held > 0: self.spawn_player(player) + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) @@ -221,6 +230,7 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): team, team.flags_held, len(self._flags) ) + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -272,6 +282,7 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): ): self.spawn_player(otherplayer) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. @@ -287,6 +298,7 @@ class ConquestGame(bs.TeamGameActivity[Player, Team]): else: super().handlemessage(msg) + @override def spawn_player(self, player: Player) -> bs.Actor: # We spawn players at different places based on what flags are held. return self.spawn_player_spaz( diff --git a/src/assets/ba_data/python/bascenev1lib/game/deathmatch.py b/src/assets/ba_data/python/bascenev1lib/game/deathmatch.py index ccbadd8d..7721b636 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/deathmatch.py +++ b/src/assets/ba_data/python/bascenev1lib/game/deathmatch.py @@ -9,9 +9,11 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -38,6 +40,7 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]): # Print messages when players die since it matters here. announce_player_deaths = True + @override @classmethod def get_available_settings( cls, sessiontype: type[bs.Session] @@ -87,12 +90,14 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]): return settings + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) or issubclass( sessiontype, bs.FreeForAllSession ) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -116,16 +121,20 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.TO_THE_DEATH ) + @override def get_instance_description(self) -> str | Sequence: return 'Crush ${ARG1} of your enemies.', self._score_to_win + @override def get_instance_description_short(self) -> str | Sequence: return 'kill ${ARG1} enemies', self._score_to_win + @override def on_team_join(self, team: Team) -> None: if self.has_begun(): self._update_scoreboard() + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) @@ -137,6 +146,7 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]): ) self._update_scoreboard() + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. @@ -197,6 +207,7 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]): team, team.score, self._score_to_win ) + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: diff --git a/src/assets/ba_data/python/bascenev1lib/game/easteregghunt.py b/src/assets/ba_data/python/bascenev1lib/game/easteregghunt.py index 4eb2d5b5..e7159f8d 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/easteregghunt.py +++ b/src/assets/ba_data/python/bascenev1lib/game/easteregghunt.py @@ -10,6 +10,9 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.bomb import Bomb from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.spazbot import SpazBotSet, BouncyBot, SpazBotDiedMessage @@ -17,7 +20,6 @@ from bascenev1lib.actor.onscreencountdown import OnScreenCountdown from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.respawnicon import RespawnIcon from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any @@ -51,11 +53,13 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): scoreconfig = bs.ScoreConfig(label='Score', scoretype=bs.ScoreType.POINTS) # We're currently hard-coded for one map. + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: return ['Tower D'] # We support teams, free-for-all, and co-op sessions. + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return ( @@ -93,11 +97,13 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FORWARD_MARCH ) + @override def on_team_join(self, team: Team) -> None: if self.has_begun(): self._update_scoreboard() # Called when our game actually starts. + @override def on_begin(self) -> None: from bascenev1lib.maps import TowerD @@ -118,6 +124,7 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): self._spawn_evil_bunny() # Overriding the default character spawning. + @override def spawn_player(self, player: Player) -> bs.Actor: spaz = self.spawn_player_spaz(player) spaz.connect_controls_to_player() @@ -191,6 +198,7 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): self._eggs.append(Egg(position=(xpos, ypos, zpos))) # Various high-level game events come through this method. + @override def handlemessage(self, msg: Any) -> Any: # Respawn dead players. if isinstance(msg, bs.PlayerDiedMessage): @@ -231,6 +239,7 @@ class EasterEggHuntGame(bs.TeamGameActivity[Player, Team]): for team in self.teams: self._scoreboard.set_team_value(team, team.score) + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -271,9 +280,11 @@ class Egg(bs.Actor): }, ) + @override def exists(self) -> bool: return bool(self.node) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.DieMessage): if self.node: diff --git a/src/assets/ba_data/python/bascenev1lib/game/elimination.py b/src/assets/ba_data/python/bascenev1lib/game/elimination.py index 51b09895..a7f9429f 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/elimination.py +++ b/src/assets/ba_data/python/bascenev1lib/game/elimination.py @@ -10,9 +10,11 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.spazfactory import SpazFactory from bascenev1lib.actor.scoreboard import Scoreboard -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -157,6 +159,7 @@ class Icon(bs.Actor): if lives == 0: bs.timer(0.6, self.update_for_lives) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.DieMessage): self.node.delete() @@ -194,6 +197,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): allow_mid_activity_joins = False + @override @classmethod def get_available_settings( cls, sessiontype: type[bs.Session] @@ -238,12 +242,14 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): ) return settings + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) or issubclass( sessiontype, bs.FreeForAllSession ) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -269,6 +275,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SURVIVAL ) + @override def get_instance_description(self) -> str | Sequence: return ( 'Last team standing wins.' @@ -276,6 +283,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): else 'Last one standing wins.' ) + @override def get_instance_description_short(self) -> str | Sequence: return ( 'last team standing wins' @@ -283,6 +291,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): else 'last one standing wins' ) + @override def on_player_join(self, player: Player) -> None: player.lives = self._lives_per_player @@ -299,6 +308,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): if self.has_begun(): self._update_icons() + @override def on_begin(self) -> None: super().on_begin() self._start_time = bs.time() @@ -469,6 +479,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): return points[-1][1] return None + @override def spawn_player(self, player: Player) -> bs.Actor: actor = self.spawn_player_spaz(player, self._get_spawn_point(player)) if not self._solo_mode: @@ -495,6 +506,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): position=player.node.position, ).autoretain() + @override def on_player_leave(self, player: Player) -> None: super().on_player_leave(player) player.icons = [] @@ -518,6 +530,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): def _get_total_team_lives(self, team: Team) -> int: return sum(player.lives for player in team.players) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. @@ -588,6 +601,7 @@ class EliminationGame(bs.TeamGameActivity[Player, Team]): and any(player.lives > 0 for player in team.players) ] + @override def end_game(self) -> None: if self.has_ended(): return diff --git a/src/assets/ba_data/python/bascenev1lib/game/football.py b/src/assets/ba_data/python/bascenev1lib/game/football.py index 5a286a63..1c99555b 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/football.py +++ b/src/assets/ba_data/python/bascenev1lib/game/football.py @@ -1,5 +1,6 @@ # Released under the MIT License. See LICENSE for details. # +# pylint: disable=too-many-lines """Implements football games (both co-op and teams varieties).""" # ba_meta require api 8 @@ -12,6 +13,9 @@ import random import logging from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.bomb import TNTSpawner from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard @@ -39,7 +43,6 @@ from bascenev1lib.actor.spazbot import ( StickyBot, ExplodeyBot, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -128,11 +131,13 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): bs.BoolSetting('Epic Mode', default=False), ] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: # We only support two-team play. return issubclass(sessiontype, bs.DualTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -170,6 +175,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.FOOTBALL ) + @override def get_instance_description(self) -> str | Sequence: touchdowns = self._score_to_win / 7 @@ -181,6 +187,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): return 'Score ${ARG1} touchdowns.', touchdowns return 'Score a touchdown.' + @override def get_instance_description_short(self) -> str | Sequence: touchdowns = self._score_to_win / 7 touchdowns = math.ceil(touchdowns) @@ -188,6 +195,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): return 'score ${ARG1} touchdowns', touchdowns return 'score a touchdown' + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) @@ -224,6 +232,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): self._update_scoreboard() self._chant_sound.play() + @override def on_team_join(self, team: Team) -> None: self._update_scoreboard() @@ -285,6 +294,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): bs.cameraflash(duration=10.0) self._update_scoreboard() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -298,6 +308,7 @@ class FootballTeamGame(bs.TeamGameActivity[Player, Team]): team, team.score, self._score_to_win ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, FlagPickedUpMessage): assert isinstance(msg.flag, FootballFlag) @@ -379,9 +390,11 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): default_music = bs.MusicType.FOOTBALL # FIXME: Need to update co-op games to use getscoreconfig. + @override def get_score_type(self) -> str: return 'time' + @override def get_instance_description(self) -> str | Sequence: touchdowns = self._score_to_win / 7 touchdowns = math.ceil(touchdowns) @@ -389,6 +402,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): return 'Score ${ARG1} touchdowns.', touchdowns return 'Score a touchdown.' + @override def get_instance_description_short(self) -> str | Sequence: touchdowns = self._score_to_win / 7 touchdowns = math.ceil(touchdowns) @@ -444,6 +458,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): self._flag_respawn_light: bs.Actor | None = None self._flag: FootballFlag | None = None + @override def on_transition_in(self) -> None: super().on_transition_in() self._scoreboard = Scoreboard() @@ -480,6 +495,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): ) self._chant_sound.play() + @override def on_begin(self) -> None: # FIXME: Split this up a bit. # pylint: disable=too-many-statements @@ -795,11 +811,13 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): if i == 0: bs.cameraflash(duration=10.0) + @override def end_game(self) -> None: bs.setmusic(None) self._bots.final_celebrate() bs.timer(0.001, bs.Call(self.do_end, 'defeat')) + @override def on_continue(self) -> None: # Subtract one touchdown from the bots and get them moving again. assert self._bot_team is not None @@ -897,6 +915,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): }, ) + @override def handlemessage(self, msg: Any) -> Any: """handle high-level game messages""" if isinstance(msg, bs.PlayerDiedMessage): @@ -959,6 +978,7 @@ class FootballCoopGame(bs.CoopGameActivity[Player, Team]): del player # Unused. self._player_has_punched = True + @override def spawn_player(self, player: Player) -> bs.Actor: spaz = self.spawn_player_spaz( player, position=self.map.get_start_position(player.team.id) diff --git a/src/assets/ba_data/python/bascenev1lib/game/hockey.py b/src/assets/ba_data/python/bascenev1lib/game/hockey.py index b61b7dfd..64487e5a 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/hockey.py +++ b/src/assets/ba_data/python/bascenev1lib/game/hockey.py @@ -9,11 +9,13 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.powerupbox import PowerupBoxFactory from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -58,6 +60,7 @@ class Puck(bs.Actor): ) bs.animate(self.node, 'mesh_scale', {0: 0, 0.2: 1.3, 0.26: 1}) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.DieMessage): if self.node: @@ -152,10 +155,12 @@ class HockeyGame(bs.TeamGameActivity[Player, Team]): bs.BoolSetting('Epic Mode', default=False), ] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -231,16 +236,19 @@ class HockeyGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.HOCKEY ) + @override def get_instance_description(self) -> str | Sequence: if self._score_to_win == 1: return 'Score a goal.' return 'Score ${ARG1} goals.', self._score_to_win + @override def get_instance_description_short(self) -> str | Sequence: if self._score_to_win == 1: return 'score a goal' return 'score ${ARG1} goals', self._score_to_win + @override def on_begin(self) -> None: super().on_begin() @@ -281,6 +289,7 @@ class HockeyGame(bs.TeamGameActivity[Player, Team]): self._update_scoreboard() self._chant_sound.play() + @override def on_team_join(self, team: Team) -> None: self._update_scoreboard() @@ -364,6 +373,7 @@ class HockeyGame(bs.TeamGameActivity[Player, Team]): bs.cameraflash(duration=10.0) self._update_scoreboard() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -375,6 +385,7 @@ class HockeyGame(bs.TeamGameActivity[Player, Team]): for team in self.teams: self._scoreboard.set_team_value(team, team.score, winscore) + @override def handlemessage(self, msg: Any) -> Any: # Respawn dead players if they're still in the game. if isinstance(msg, bs.PlayerDiedMessage): diff --git a/src/assets/ba_data/python/bascenev1lib/game/keepaway.py b/src/assets/ba_data/python/bascenev1lib/game/keepaway.py index bc80b77d..416723e1 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/keepaway.py +++ b/src/assets/ba_data/python/bascenev1lib/game/keepaway.py @@ -11,6 +11,9 @@ import logging from enum import Enum from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.flag import ( @@ -19,7 +22,6 @@ from bascenev1lib.actor.flag import ( FlagDiedMessage, FlagPickedUpMessage, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -86,12 +88,14 @@ class KeepAwayGame(bs.TeamGameActivity[Player, Team]): ] scoreconfig = bs.ScoreConfig(label='Time Held') + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.DualTeamSession) or issubclass( sessiontype, bs.FreeForAllSession ) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -129,18 +133,23 @@ class KeepAwayGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.KEEP_AWAY ) + @override def get_instance_description(self) -> str | Sequence: return 'Carry the flag for ${ARG1} seconds.', self._hold_time + @override def get_instance_description_short(self) -> str | Sequence: return 'carry the flag for ${ARG1} seconds', self._hold_time + @override def create_team(self, sessionteam: bs.SessionTeam) -> Team: return Team(timeremaining=self._hold_time) + @override def on_team_join(self, team: Team) -> None: self._update_scoreboard() + @override def on_begin(self) -> None: super().on_begin() self.setup_standard_time_limit(self._time_limit) @@ -181,6 +190,7 @@ class KeepAwayGame(bs.TeamGameActivity[Player, Team]): if scoreteam.timeremaining <= 0: self.end_game() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -268,6 +278,7 @@ class KeepAwayGame(bs.TeamGameActivity[Player, Team]): team, team.timeremaining, self._hold_time, countdown=True ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. diff --git a/src/assets/ba_data/python/bascenev1lib/game/kingofthehill.py b/src/assets/ba_data/python/bascenev1lib/game/kingofthehill.py index 6492d823..907b4341 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/kingofthehill.py +++ b/src/assets/ba_data/python/bascenev1lib/game/kingofthehill.py @@ -11,11 +11,13 @@ import weakref from enum import Enum from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.flag import Flag from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -84,10 +86,12 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): ] scoreconfig = bs.ScoreConfig(label='Time Held') + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.MultiTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -144,15 +148,19 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC if self._epic_mode else bs.MusicType.SCARY ) + @override def get_instance_description(self) -> str | Sequence: return 'Secure the flag for ${ARG1} seconds.', self._hold_time + @override def get_instance_description_short(self) -> str | Sequence: return 'secure the flag for ${ARG1} seconds', self._hold_time + @override def create_team(self, sessionteam: bs.SessionTeam) -> Team: return Team(time_remaining=self._hold_time) + @override def on_begin(self) -> None: super().on_begin() shared = SharedObjects.get() @@ -223,6 +231,7 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): if scoring_team.time_remaining <= 0: self.end_game() + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -283,6 +292,7 @@ class KingOfTheHillGame(bs.TeamGameActivity[Player, Team]): team, team.time_remaining, self._hold_time, countdown=True ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): super().handlemessage(msg) # Augment default. diff --git a/src/assets/ba_data/python/bascenev1lib/game/meteorshower.py b/src/assets/ba_data/python/bascenev1lib/game/meteorshower.py index 35e0566d..a9a70ae0 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/meteorshower.py +++ b/src/assets/ba_data/python/bascenev1lib/game/meteorshower.py @@ -10,9 +10,11 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.bomb import Bomb from bascenev1lib.actor.onscreentimer import OnScreenTimer -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -49,11 +51,13 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): allow_mid_activity_joins = False # We're currently hard-coded for one map. + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: return ['Rampage'] # We support teams, free-for-all, and co-op sessions. + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return ( @@ -77,6 +81,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): if self._epic_mode: self.slow_motion = True + @override def on_begin(self) -> None: super().on_begin() @@ -100,6 +105,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): # Check for immediate end (if we've only got 1 player, etc). bs.timer(5.0, self._check_end_game) + @override def on_player_leave(self, player: Player) -> None: # Augment default behavior. super().on_player_leave(player) @@ -108,6 +114,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): self._check_end_game() # overriding the default character spawning.. + @override def spawn_player(self, player: Player) -> bs.Actor: spaz = self.spawn_player_spaz(player) @@ -122,6 +129,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): return spaz # Various high-level game events come through this method. + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment standard behavior. @@ -213,6 +221,7 @@ class MeteorShowerGame(bs.TeamGameActivity[Player, Team]): def _decrement_meteor_time(self) -> None: self._meteor_time = max(0.01, self._meteor_time * 0.9) + @override def end_game(self) -> None: cur_time = bs.time() assert self._timer is not None diff --git a/src/assets/ba_data/python/bascenev1lib/game/ninjafight.py b/src/assets/ba_data/python/bascenev1lib/game/ninjafight.py index 501e920b..98ca8d0b 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/ninjafight.py +++ b/src/assets/ba_data/python/bascenev1lib/game/ninjafight.py @@ -10,13 +10,15 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.spazbot import ( SpazBotSet, ChargerBot, SpazBotDiedMessage, ) from bascenev1lib.actor.onscreentimer import OnScreenTimer -import bascenev1 as bs if TYPE_CHECKING: from typing import Any @@ -44,6 +46,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): ) default_music = bs.MusicType.TO_THE_DEATH + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: # For now we're hard-coding spawn positions and whatnot @@ -51,6 +54,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): # a specific map. return ['Courtyard'] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: # We currently support Co-Op only. @@ -67,6 +71,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): self._preset = str(settings['preset']) # Called when our game actually begins. + @override def on_begin(self) -> None: super().on_begin() is_pro = self._preset == 'pro' @@ -123,6 +128,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): ) # Called for each spawning player. + @override def spawn_player(self, player: Player) -> bs.Actor: # Let's spawn close to the center. spawn_center = (0, 3, -2) @@ -144,6 +150,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): self.end_game() # Called for miscellaneous messages. + @override def handlemessage(self, msg: Any) -> Any: # A player has died. if isinstance(msg, bs.PlayerDiedMessage): @@ -166,6 +173,7 @@ class NinjaFightGame(bs.TeamGameActivity[Player, Team]): # When this is called, we should fill out results and end the game # *regardless* of whether is has been won. (this may be called due # to a tournament ending or other external reason). + @override def end_game(self) -> None: # Stop our on-screen timer so players can see what they got. assert self._timer is not None diff --git a/src/assets/ba_data/python/bascenev1lib/game/onslaught.py b/src/assets/ba_data/python/bascenev1lib/game/onslaught.py index 2e8f98e4..d4644130 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/onslaught.py +++ b/src/assets/ba_data/python/bascenev1lib/game/onslaught.py @@ -17,6 +17,9 @@ from enum import Enum, unique from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.popuptext import PopupText from bascenev1lib.actor.bomb import TNTSpawner from bascenev1lib.actor.playerspaz import PlayerSpazHurtMessage @@ -45,7 +48,6 @@ from bascenev1lib.actor.spazbot import ( BrawlerBotPro, BomberBotProShielded, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -222,6 +224,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): self._land_mine_kills = 0 self._tnt_kills = 0 + @override def on_transition_in(self) -> None: super().on_transition_in() customdata = bs.getsession().customdata @@ -286,6 +289,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): label=bs.Lstr(resource='scoreText'), score_split=0.5 ) + @override def on_begin(self) -> None: super().on_begin() player_count = len(self.players) @@ -825,6 +829,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): break entry_count += 1 + @override def spawn_player(self, player: Player) -> bs.Actor: # We keep track of who got hurt each wave for score purposes. player.has_been_hurt = False @@ -1414,6 +1419,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): assert self._scoreboard is not None self._scoreboard.set_team_value(self.teams[0], score, max_score=None) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, PlayerSpazHurtMessage): msg.spaz.getplayer(Player, True).has_been_hurt = True @@ -1526,6 +1532,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): def _set_can_end_wave(self) -> None: self._can_end_wave = True + @override def end_game(self) -> None: # Tell our bots to celebrate just to rub it in. assert self._bots is not None @@ -1534,6 +1541,7 @@ class OnslaughtGame(bs.CoopGameActivity[Player, Team]): self.do_end('defeat', delay=2.0) bs.setmusic(None) + @override def on_continue(self) -> None: for player in self.players: if not player.is_alive(): diff --git a/src/assets/ba_data/python/bascenev1lib/game/race.py b/src/assets/ba_data/python/bascenev1lib/game/race.py index 2dd20f73..4a35fa4c 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/race.py +++ b/src/assets/ba_data/python/bascenev1lib/game/race.py @@ -12,11 +12,13 @@ import logging from typing import TYPE_CHECKING from dataclasses import dataclass +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.bomb import Bomb from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.gameutils import SharedObjects -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -84,6 +86,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): label='Time', lower_is_better=True, scoretype=bs.ScoreType.MILLISECONDS ) + @override @classmethod def get_available_settings( cls, sessiontype: type[bs.Session] @@ -133,10 +136,12 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): ) return settings + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: return issubclass(sessiontype, bs.MultiTeamSession) + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: assert bs.app.classic is not None @@ -179,6 +184,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): bs.MusicType.EPIC_RACE if self._epic_mode else bs.MusicType.RACE ) + @override def get_instance_description(self) -> str | Sequence: if ( isinstance(self.session, bs.DualTeamSession) @@ -192,11 +198,13 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): return 'Run ${ARG1} laps.' + t_str, self._laps return 'Run 1 lap.' + t_str + @override def get_instance_description_short(self) -> str | Sequence: if self._laps > 1: return 'run ${ARG1} laps', self._laps return 'run 1 lap' + @override def on_transition_in(self) -> None: super().on_transition_in() shared = SharedObjects.get() @@ -379,9 +387,11 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): except Exception: logging.exception('Error printing lap.') + @override def on_team_join(self, team: Team) -> None: self._update_scoreboard() + @override def on_player_leave(self, player: Player) -> None: super().on_player_leave(player) @@ -442,6 +452,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): show_value=False, ) + @override def on_begin(self) -> None: from bascenev1lib.actor.onscreentimer import OnScreenTimer @@ -670,6 +681,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): self._flash_mine(m_index) bs.timer(0.95, bs.Call(self._make_mine, m_index)) + @override def spawn_player(self, player: Player) -> bs.Actor: if player.team.finished: # FIXME: This is not type-safe! @@ -758,6 +770,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): self.end_game() return + @override def end_game(self) -> None: # Stop updating our time text, and set it to show the exact last # finish time if we have one. (so users don't get upset if their @@ -787,6 +800,7 @@ class RaceGame(bs.TeamGameActivity[Player, Team]): announce_winning_team=isinstance(self.session, bs.DualTeamSession), ) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): # Augment default behavior. diff --git a/src/assets/ba_data/python/bascenev1lib/game/runaround.py b/src/assets/ba_data/python/bascenev1lib/game/runaround.py index 6640601f..b970d354 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/runaround.py +++ b/src/assets/ba_data/python/bascenev1lib/game/runaround.py @@ -16,6 +16,9 @@ from enum import Enum from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.popuptext import PopupText from bascenev1lib.actor.bomb import TNTSpawner from bascenev1lib.actor.scoreboard import Scoreboard @@ -40,7 +43,6 @@ from bascenev1lib.actor.spazbot import ( BomberBotPro, BrawlerBotPro, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -194,6 +196,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): self._flawless_bonus: int | None = None self._wave_update_timer: bs.Timer | None = None + @override def on_transition_in(self) -> None: super().on_transition_in() self._scoreboard = Scoreboard( @@ -211,6 +214,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): ) ) + @override def on_begin(self) -> None: super().on_begin() player_count = len(self.players) @@ -571,6 +575,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): ), ) + @override def on_continue(self) -> None: self._lives = 3 assert self._lives_text is not None @@ -578,6 +583,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): self._lives_text.node.text = str(self._lives) self._bots.start_moving() + @override def spawn_player(self, player: Player) -> bs.Actor: pos = ( self._spawn_center[0] + random.uniform(-1.5, 1.5), @@ -654,6 +660,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): ), ).autoretain() + @override def end_game(self) -> None: bs.pushcall(bs.Call(self.do_end, 'defeat')) bs.setmusic(None) @@ -1286,6 +1293,7 @@ class RunaroundGame(bs.CoopGameActivity[Player, Team]): # Revert to normal bot behavior otherwise.. return False + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerScoredMessage): self._score += msg.score diff --git a/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py b/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py index c39f9706..fdff48f2 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py +++ b/src/assets/ba_data/python/bascenev1lib/game/targetpractice.py @@ -10,11 +10,13 @@ from __future__ import annotations import random from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.scoreboard import Scoreboard from bascenev1lib.actor.onscreencountdown import OnScreenCountdown from bascenev1lib.actor.bomb import Bomb from bascenev1lib.actor.popuptext import PopupText -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -49,10 +51,12 @@ class TargetPracticeGame(bs.TeamGameActivity[Player, Team]): ] default_music = bs.MusicType.FORWARD_MARCH + @override @classmethod def get_supported_maps(cls, sessiontype: type[bs.Session]) -> list[str]: return ['Doom Shroom'] + @override @classmethod def supports_session_type(cls, sessiontype: type[bs.Session]) -> bool: # We support any teams or versus sessions. @@ -70,10 +74,12 @@ class TargetPracticeGame(bs.TeamGameActivity[Player, Team]): self._enable_impact_bombs = bool(settings['Enable Impact Bombs']) self._enable_triple_bombs = bool(settings['Enable Triple Bombs']) + @override def on_team_join(self, team: Team) -> None: if self.has_begun(): self.update_scoreboard() + @override def on_begin(self) -> None: super().on_begin() self.update_scoreboard() @@ -86,6 +92,7 @@ class TargetPracticeGame(bs.TeamGameActivity[Player, Team]): self._countdown = OnScreenCountdown(60, endcall=self.end_game) bs.timer(4.0, self._countdown.start) + @override def spawn_player(self, player: Player) -> bs.Actor: spawn_center = (0, 3, -5) pos = ( @@ -169,6 +176,7 @@ class TargetPracticeGame(bs.TeamGameActivity[Player, Team]): # Clear out targets that have died. self._targets = [t for t in self._targets if t] + @override def handlemessage(self, msg: Any) -> Any: # When players die, respawn them. if isinstance(msg, bs.PlayerDiedMessage): @@ -188,6 +196,7 @@ class TargetPracticeGame(bs.TeamGameActivity[Player, Team]): for team in self.teams: self._scoreboard.set_team_value(team, team.score) + @override def end_game(self) -> None: results = bs.GameResults() for team in self.teams: @@ -252,9 +261,11 @@ class Target(bs.Actor): bs.animate_array(loc3, 'size', 1, {0.1: [0.0], 0.3: [self._r3 * 2.0]}) bs.getsound('laserReverse').play() + @override def exists(self) -> bool: return bool(self._nodes) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.DieMessage): for node in self._nodes: diff --git a/src/assets/ba_data/python/bascenev1lib/game/thelaststand.py b/src/assets/ba_data/python/bascenev1lib/game/thelaststand.py index 5eb32fac..7752c3fa 100644 --- a/src/assets/ba_data/python/bascenev1lib/game/thelaststand.py +++ b/src/assets/ba_data/python/bascenev1lib/game/thelaststand.py @@ -9,6 +9,9 @@ import logging from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override +import bascenev1 as bs + from bascenev1lib.actor.playerspaz import PlayerSpaz from bascenev1lib.actor.bomb import TNTSpawner from bascenev1lib.actor.scoreboard import Scoreboard @@ -29,7 +32,6 @@ from bascenev1lib.actor.spazbot import ( StickyBot, ExplodeyBot, ) -import bascenev1 as bs if TYPE_CHECKING: from typing import Any, Sequence @@ -109,6 +111,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): ExplodeyBot: SpawnInfo(0.05, 0.02, 0.002), } + @override def on_transition_in(self) -> None: super().on_transition_in() bs.timer(1.3, self._new_wave_sound.play) @@ -116,6 +119,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): label=bs.Lstr(resource='scoreText'), score_split=0.5 ) + @override def on_begin(self) -> None: super().on_begin() @@ -129,6 +133,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): position=self._tntspawnpos, respawn_time=10.0 ) + @override def spawn_player(self, player: Player) -> bs.Actor: pos = ( self._spawn_center[0] + random.uniform(-1.5, 1.5), @@ -290,6 +295,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): assert self._scoreboard is not None self._scoreboard.set_team_value(self.teams[0], score, max_score=None) + @override def handlemessage(self, msg: Any) -> Any: if isinstance(msg, bs.PlayerDiedMessage): player = msg.getplayer(Player) @@ -327,6 +333,7 @@ class TheLastStandGame(bs.CoopGameActivity[Player, Team]): else: super().handlemessage(msg) + @override def end_game(self) -> None: # Tell our bots to celebrate just to rub it in. self._bots.final_celebrate() diff --git a/src/assets/ba_data/python/bascenev1lib/mainmenu.py b/src/assets/ba_data/python/bascenev1lib/mainmenu.py index 7b7acfbf..8041176e 100644 --- a/src/assets/ba_data/python/bascenev1lib/mainmenu.py +++ b/src/assets/ba_data/python/bascenev1lib/mainmenu.py @@ -10,6 +10,7 @@ import random import weakref from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs import bauiv1 as bui @@ -44,6 +45,7 @@ class MainMenuActivity(bs.Activity[bs.Player, bs.Team]): self._news: NewsDisplay | None = None self._attract_mode_timer: bs.Timer | None = None + @override def on_transition_in(self) -> None: # pylint: disable=too-many-locals # pylint: disable=too-many-statements @@ -1139,6 +1141,7 @@ class MainMenuSession(bs.Session): self._locked = False self.setactivity(bs.newactivity(MainMenuActivity)) + @override def on_activity_end(self, activity: bs.Activity, results: Any) -> None: if self._locked: bui.unlock_all_input() @@ -1146,6 +1149,7 @@ class MainMenuSession(bs.Session): # Any ending activity leads us into the main menu one. self.setactivity(bs.newactivity(MainMenuActivity)) + @override def on_player_request(self, player: bs.SessionPlayer) -> bool: # Reject all player requests. return False diff --git a/src/assets/ba_data/python/bascenev1lib/maps.py b/src/assets/ba_data/python/bascenev1lib/maps.py index 26349f56..d4731145 100644 --- a/src/assets/ba_data/python/bascenev1lib/maps.py +++ b/src/assets/ba_data/python/bascenev1lib/maps.py @@ -7,7 +7,9 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs + from bascenev1lib.gameutils import SharedObjects if TYPE_CHECKING: @@ -22,15 +24,18 @@ class HockeyStadium(bs.Map): name = 'Hockey Stadium' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'hockey', 'team_flag', 'keep_away'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'hockeyStadiumPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -114,15 +119,18 @@ class FootballStadium(bs.Map): name = 'Football Stadium' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'football', 'team_flag', 'keep_away'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'footballStadiumPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -164,6 +172,7 @@ class FootballStadium(bs.Map): gnode.vr_camera_offset = (0, -0.8, -1.1) gnode.vr_near_clip = 0.5 + @override def is_point_near_edge(self, point: bs.Vec3, running: bool = False) -> bool: box_position = self.defs.boxes['edge_box'][0:3] box_scale = self.defs.boxes['edge_box'][6:9] @@ -181,16 +190,19 @@ class Bridgit(bs.Map): name = 'Bridgit' dataname = 'bridgit' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" # print('getting playtypes', cls._getdata()['play_types']) return ['melee', 'team_flag', 'keep_away'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'bridgitPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -286,6 +298,7 @@ class BigG(bs.Map): name = 'Big G' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" @@ -298,10 +311,12 @@ class BigG(bs.Map): 'conquest', ] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'bigGPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -397,15 +412,18 @@ class Roundabout(bs.Map): name = 'Roundabout' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'roundaboutPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -502,15 +520,18 @@ class MonkeyFace(bs.Map): name = 'Monkey Face' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'monkeyFacePreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -607,6 +628,7 @@ class ZigZag(bs.Map): name = 'Zigzag' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" @@ -618,10 +640,12 @@ class ZigZag(bs.Map): 'king_of_the_hill', ] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'zigzagPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -715,15 +739,18 @@ class ThePad(bs.Map): name = 'The Pad' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag', 'king_of_the_hill'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'thePadPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -804,15 +831,18 @@ class DoomShroom(bs.Map): name = 'Doom Shroom' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'doomShroomPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -881,6 +911,7 @@ class DoomShroom(bs.Map): gnode.vignette_outer = (0.76, 0.76, 0.76) gnode.vignette_inner = (0.95, 0.95, 0.99) + @override def is_point_near_edge(self, point: bs.Vec3, running: bool = False) -> bool: xpos = point.x zpos = point.z @@ -900,15 +931,18 @@ class LakeFrigid(bs.Map): name = 'Lake Frigid' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag', 'race'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'lakeFrigidPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -987,15 +1021,18 @@ class TipTop(bs.Map): name = 'Tip Top' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag', 'king_of_the_hill'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'tipTopPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1065,15 +1102,18 @@ class CragCastle(bs.Map): name = 'Crag Castle' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag', 'conquest'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'cragCastlePreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1158,15 +1198,18 @@ class TowerD(bs.Map): name = 'Tower D' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return [] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'towerDPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1256,6 +1299,7 @@ class TowerD(bs.Map): gnode.vignette_outer = (0.7, 0.73, 0.7) gnode.vignette_inner = (0.95, 0.95, 0.95) + @override def is_point_near_edge(self, point: bs.Vec3, running: bool = False) -> bool: # see if we're within edge_box boxes = self.defs.boxes @@ -1281,6 +1325,7 @@ class HappyThoughts(bs.Map): name = 'Happy Thoughts' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" @@ -1292,10 +1337,12 @@ class HappyThoughts(bs.Map): 'king_of_the_hill', ] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'alwaysLandPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1310,6 +1357,7 @@ class HappyThoughts(bs.Map): } return data + @override @classmethod def get_music_type(cls) -> bs.MusicType: return bs.MusicType.FLYING @@ -1397,15 +1445,18 @@ class StepRightUp(bs.Map): name = 'Step Right Up' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag', 'conquest'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'stepRightUpPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1477,15 +1528,18 @@ class Courtyard(bs.Map): name = 'Courtyard' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'courtyardPreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1576,6 +1630,7 @@ class Courtyard(bs.Map): gnode.vignette_outer = (0.6, 0.6, 0.64) gnode.vignette_inner = (0.95, 0.95, 0.93) + @override def is_point_near_edge(self, point: bs.Vec3, running: bool = False) -> bool: # count anything off our ground level as safe (for our platforms) # see if we're within edge_box @@ -1593,15 +1648,18 @@ class Rampage(bs.Map): name = 'Rampage' + @override @classmethod def get_play_types(cls) -> list[str]: """Return valid play types for this map.""" return ['melee', 'keep_away', 'team_flag'] + @override @classmethod def get_preview_texture_name(cls) -> str: return 'rampagePreview' + @override @classmethod def on_preload(cls) -> Any: data: dict[str, Any] = { @@ -1681,6 +1739,7 @@ class Rampage(bs.Map): gnode.vignette_outer = (0.62, 0.64, 0.69) gnode.vignette_inner = (0.97, 0.95, 0.93) + @override def is_point_near_edge(self, point: bs.Vec3, running: bool = False) -> bool: box_position = self.defs.boxes['edge_box'][0:3] box_scale = self.defs.boxes['edge_box'][6:9] diff --git a/src/assets/ba_data/python/bascenev1lib/tutorial.py b/src/assets/ba_data/python/bascenev1lib/tutorial.py index e51c4a8d..86aa6411 100644 --- a/src/assets/ba_data/python/bascenev1lib/tutorial.py +++ b/src/assets/ba_data/python/bascenev1lib/tutorial.py @@ -19,6 +19,7 @@ import logging from collections import deque from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs from bascenev1lib.actor.spaz import Spaz @@ -234,11 +235,13 @@ class TutorialActivity(bs.Activity[Player, Team]): self._read_entries_timer: bs.Timer | None = None self._entry_timer: bs.Timer | None = None + @override def on_transition_in(self) -> None: super().on_transition_in() bs.setmusic(bs.MusicType.CHAR_SELECT, continuous=True) self.map = self._map_type() + @override def on_begin(self) -> None: super().on_begin() @@ -2513,6 +2516,7 @@ class TutorialActivity(bs.Activity[Player, Team]): self._skip_text.color = (1, 1, 1) self._issued_warning = False + @override def on_player_join(self, player: Player) -> None: super().on_player_join(player) @@ -2527,6 +2531,7 @@ class TutorialActivity(bs.Activity[Player, Team]): bs.Call(self._player_pressed_button, player), ) + @override def on_player_leave(self, player: Player) -> None: if not all(self.players): logging.error( diff --git a/src/assets/ba_data/python/bauiv1/_subsystem.py b/src/assets/ba_data/python/bauiv1/_subsystem.py index 3c6b1e77..34d7f5af 100644 --- a/src/assets/ba_data/python/bauiv1/_subsystem.py +++ b/src/assets/ba_data/python/bauiv1/_subsystem.py @@ -8,7 +8,9 @@ import logging import inspect from typing import TYPE_CHECKING +from typing_extensions import override import babase + import _bauiv1 if TYPE_CHECKING: @@ -82,6 +84,7 @@ class UIV1Subsystem(babase.AppSubsystem): """Current ui scale for the app.""" return self._uiscale + @override def on_app_loading(self) -> None: from bauiv1._uitypes import UIController, ui_upkeep diff --git a/src/assets/ba_data/python/bauiv1/_uitypes.py b/src/assets/ba_data/python/bauiv1/_uitypes.py index 5cbd14e2..2f93f227 100644 --- a/src/assets/ba_data/python/bauiv1/_uitypes.py +++ b/src/assets/ba_data/python/bauiv1/_uitypes.py @@ -9,6 +9,7 @@ import weakref from dataclasses import dataclass from typing import TYPE_CHECKING +from typing_extensions import override import babase import _bauiv1 @@ -264,12 +265,14 @@ class TextWidgetStringEditAdapter(babase.StringEditAdapter): description, initial_text, max_length, screen_space_center ) + @override def _do_apply(self, new_text: str) -> None: if self.widget: _bauiv1.textwidget( edit=self.widget, text=new_text, adapter_finished=True ) + @override def _do_cancel(self) -> None: if self.widget: _bauiv1.textwidget(edit=self.widget, adapter_finished=True) diff --git a/src/assets/ba_data/python/bauiv1lib/account/viewer.py b/src/assets/ba_data/python/bauiv1lib/account/viewer.py index 914bd930..9046a805 100644 --- a/src/assets/ba_data/python/bauiv1lib/account/viewer.py +++ b/src/assets/ba_data/python/bauiv1lib/account/viewer.py @@ -7,9 +7,11 @@ from __future__ import annotations from typing import TYPE_CHECKING import logging -from bauiv1lib.popup import PopupWindow, PopupMenuWindow +from typing_extensions import override import bauiv1 as bui +from bauiv1lib.popup import PopupWindow, PopupMenuWindow + if TYPE_CHECKING: from typing import Any @@ -596,6 +598,7 @@ class AccountViewerWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/achievements.py b/src/assets/ba_data/python/bauiv1lib/achievements.py index 1c8cc673..df2345d5 100644 --- a/src/assets/ba_data/python/bauiv1lib/achievements.py +++ b/src/assets/ba_data/python/bauiv1lib/achievements.py @@ -4,6 +4,8 @@ from __future__ import annotations +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -229,6 +231,7 @@ class AchievementsWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/characterpicker.py b/src/assets/ba_data/python/bauiv1lib/characterpicker.py index b4bdd635..92194e2b 100644 --- a/src/assets/ba_data/python/bauiv1lib/characterpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/characterpicker.py @@ -7,6 +7,8 @@ from __future__ import annotations import math from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -208,6 +210,7 @@ class CharacterPicker(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/colorpicker.py b/src/assets/ba_data/python/bauiv1lib/colorpicker.py index 904c9e33..30887432 100644 --- a/src/assets/ba_data/python/bauiv1lib/colorpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/colorpicker.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -170,6 +172,7 @@ class ColorPicker(PopupWindow): self._delegate.color_picker_closing(self) bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: if not self._transitioning_out: bui.getsound('swish').play() @@ -338,6 +341,7 @@ class ColorPickerExact(PopupWindow): self._delegate.color_picker_closing(self) bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: if not self._transitioning_out: bui.getsound('swish').play() diff --git a/src/assets/ba_data/python/bauiv1lib/fileselector.py b/src/assets/ba_data/python/bauiv1lib/fileselector.py index 17263119..e9cf0ca6 100644 --- a/src/assets/ba_data/python/bauiv1lib/fileselector.py +++ b/src/assets/ba_data/python/bauiv1lib/fileselector.py @@ -10,6 +10,8 @@ import logging from threading import Thread from typing import TYPE_CHECKING +from typing_extensions import override + import bauiv1 as bui if TYPE_CHECKING: @@ -204,6 +206,7 @@ class FileSelectorWindow(bui.Window): self._callback = callback self._path = path + @override def run(self) -> None: try: starttime = time.time() diff --git a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py index b61ed339..1257c4bd 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/abouttab.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.gather import GatherTab import bauiv1 as bui @@ -16,6 +18,7 @@ if TYPE_CHECKING: class AboutGatherTab(GatherTab): """The about tab in the gather UI""" + @override def on_activate( self, parent_widget: bui.Widget, diff --git a/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py b/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py index e09968b1..d7f3205e 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/manualtab.py @@ -6,13 +6,13 @@ from __future__ import annotations import logging -from threading import Thread -from typing import TYPE_CHECKING, cast - from enum import Enum +from threading import Thread from dataclasses import dataclass +from typing import TYPE_CHECKING, cast from bauiv1lib.gather import GatherTab +from typing_extensions import override import bauiv1 as bui import bascenev1 as bs @@ -42,6 +42,7 @@ class _HostLookupThread(Thread): self._port = port self._call = call + @override def run(self) -> None: result: str | None try: @@ -101,6 +102,7 @@ class ManualGatherTab(GatherTab): self._party_edit_port_text: bui.Widget | None = None self._no_parties_added_text: bui.Widget | None = None + @override def on_activate( self, parent_widget: bui.Widget, @@ -180,10 +182,12 @@ class ManualGatherTab(GatherTab): return self._container + @override def save_state(self) -> None: assert bui.app.classic is not None bui.app.ui_v1.window_states[type(self)] = State(sub_tab=self._sub_tab) + @override def restore_state(self) -> None: assert bui.app.classic is not None state = bui.app.ui_v1.window_states.get(type(self)) @@ -771,6 +775,7 @@ class ManualGatherTab(GatherTab): text=bui.Lstr(resource='gatherWindow.noPartiesAddedText'), ) + @override def on_deactivate(self) -> None: self._access_check_timer = None diff --git a/src/assets/ba_data/python/bauiv1lib/gather/nearbytab.py b/src/assets/ba_data/python/bauiv1lib/gather/nearbytab.py index 146fcc7a..7393f6bd 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/nearbytab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/nearbytab.py @@ -7,10 +7,12 @@ from __future__ import annotations import weakref from typing import TYPE_CHECKING -from bauiv1lib.gather import GatherTab +from typing_extensions import override import bauiv1 as bui import bascenev1 as bs +from bauiv1lib.gather import GatherTab + if TYPE_CHECKING: from typing import Any @@ -104,6 +106,7 @@ class NearbyGatherTab(GatherTab): self._net_scanner: NetScanner | None = None self._container: bui.Widget | None = None + @override def on_activate( self, parent_widget: bui.Widget, @@ -156,5 +159,6 @@ class NearbyGatherTab(GatherTab): bui.widget(edit=scrollw, autoselect=True, up_widget=tab_button) return self._container + @override def on_deactivate(self) -> None: self._net_scanner = None diff --git a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py index e66cd6c1..8b6cf7fb 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/privatetab.py @@ -13,6 +13,7 @@ from enum import Enum from dataclasses import dataclass from typing import TYPE_CHECKING, cast +from typing_extensions import override from efro.dataclassio import dataclass_from_dict, dataclass_to_dict from bacommon.net import ( PrivateHostingState, @@ -81,6 +82,7 @@ class PrivateGatherTab(GatherTab): logging.exception('Error building hosting config.') self._hostingconfig = PrivateHostingConfig() + @override def on_activate( self, parent_widget: bui.Widget, @@ -253,6 +255,7 @@ class PrivateGatherTab(GatherTab): return hcfg + @override def on_deactivate(self) -> None: self._update_timer = None @@ -995,10 +998,12 @@ class PrivateGatherTab(GatherTab): self._debug_server_comm('got connect response error') bui.getsound('error').play() + @override def save_state(self) -> None: assert bui.app.classic is not None bui.app.ui_v1.window_states[type(self)] = copy.deepcopy(self._state) + @override def restore_state(self) -> None: assert bui.app.classic is not None state = bui.app.ui_v1.window_states.get(type(self)) diff --git a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py index e1619436..83b3b534 100644 --- a/src/assets/ba_data/python/bauiv1lib/gather/publictab.py +++ b/src/assets/ba_data/python/bauiv1lib/gather/publictab.py @@ -13,6 +13,7 @@ from enum import Enum from dataclasses import dataclass from typing import TYPE_CHECKING, cast +from typing_extensions import override from bauiv1lib.gather import GatherTab import bauiv1 as bui import bascenev1 as bs @@ -247,6 +248,7 @@ class AddrFetchThread(Thread): super().__init__() self._call = call + @override def run(self) -> None: sock: socket.socket | None = None try: @@ -284,6 +286,7 @@ class PingThread(Thread): self._port = port self._call = call + @override def run(self) -> None: assert bui.app.classic is not None bui.app.classic.ping_thread_count += 1 @@ -392,6 +395,7 @@ class PublicGatherTab(GatherTab): self._pending_party_infos: list[dict[str, Any]] = [] self._last_sub_scroll_height = 0.0 + @override def on_activate( self, parent_widget: bui.Widget, @@ -478,9 +482,11 @@ class PublicGatherTab(GatherTab): ) return self._container + @override def on_deactivate(self) -> None: self._update_timer = None + @override def save_state(self) -> None: # Save off a small number of parties with the lowest ping; we'll # display these immediately when our UI comes back up which should @@ -496,6 +502,7 @@ class PublicGatherTab(GatherTab): have_valid_server_list=self._have_valid_server_list, ) + @override def restore_state(self) -> None: assert bui.app.classic is not None state = bui.app.ui_v1.window_states.get(type(self)) diff --git a/src/assets/ba_data/python/bauiv1lib/getremote.py b/src/assets/ba_data/python/bauiv1lib/getremote.py index 194725f7..0cea25ae 100644 --- a/src/assets/ba_data/python/bauiv1lib/getremote.py +++ b/src/assets/ba_data/python/bauiv1lib/getremote.py @@ -4,6 +4,8 @@ from __future__ import annotations +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -77,6 +79,7 @@ class GetBSRemoteWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/iconpicker.py b/src/assets/ba_data/python/bauiv1lib/iconpicker.py index e3cace22..260bbdec 100644 --- a/src/assets/ba_data/python/bauiv1lib/iconpicker.py +++ b/src/assets/ba_data/python/bauiv1lib/iconpicker.py @@ -7,6 +7,8 @@ from __future__ import annotations import math from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -186,6 +188,7 @@ class IconPicker(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/playlist/share.py b/src/assets/ba_data/python/bauiv1lib/playlist/share.py index d52d1e7f..480aba52 100644 --- a/src/assets/ba_data/python/bauiv1lib/playlist/share.py +++ b/src/assets/ba_data/python/bauiv1lib/playlist/share.py @@ -7,6 +7,8 @@ from __future__ import annotations import time from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.promocode import PromoCodeWindow import bauiv1 as bui @@ -55,6 +57,7 @@ class SharePlaylistImportWindow(PromoCodeWindow): edit=self._root_widget, transition=self._transition_out ) + @override def _do_enter(self) -> None: plus = bui.app.plus assert plus is not None diff --git a/src/assets/ba_data/python/bauiv1lib/playoptions.py b/src/assets/ba_data/python/bauiv1lib/playoptions.py index ea58e4d6..b2d42b21 100644 --- a/src/assets/ba_data/python/bauiv1lib/playoptions.py +++ b/src/assets/ba_data/python/bauiv1lib/playoptions.py @@ -7,6 +7,7 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING +from typing_extensions import override import bascenev1 as bs import bauiv1 as bui @@ -440,6 +441,7 @@ class PlayOptionsWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition=transition) + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/popup.py b/src/assets/ba_data/python/bauiv1lib/popup.py index 34c591ca..b53cfc93 100644 --- a/src/assets/ba_data/python/bauiv1lib/popup.py +++ b/src/assets/ba_data/python/bauiv1lib/popup.py @@ -7,6 +7,8 @@ from __future__ import annotations import weakref from typing import TYPE_CHECKING +from typing_extensions import override + import bauiv1 as bui if TYPE_CHECKING: @@ -275,6 +277,7 @@ class PopupMenuWindow(PopupWindow): delegate.popup_menu_closing(self) bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: if not self._transitioning_out: bui.getsound('swish').play() diff --git a/src/assets/ba_data/python/bauiv1lib/qrcode.py b/src/assets/ba_data/python/bauiv1lib/qrcode.py index 3d92eaf8..467bab7f 100644 --- a/src/assets/ba_data/python/bauiv1lib/qrcode.py +++ b/src/assets/ba_data/python/bauiv1lib/qrcode.py @@ -3,9 +3,11 @@ """Provides functionality for displaying QR codes.""" from __future__ import annotations -from bauiv1lib.popup import PopupWindow +from typing_extensions import override import bauiv1 as bui +from bauiv1lib.popup import PopupWindow + class QRCodeWindow(PopupWindow): """Popup window that shows a QR code.""" @@ -58,6 +60,7 @@ class QRCodeWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py index c40b708d..6c3fc587 100644 --- a/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py +++ b/src/assets/ba_data/python/bauiv1lib/resourcetypeinfo.py @@ -4,6 +4,8 @@ from __future__ import annotations +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -53,6 +55,7 @@ class ResourceTypeInfoWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py b/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py index 2334e09b..3fe95459 100644 --- a/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py +++ b/src/assets/ba_data/python/bauiv1lib/teamnamescolors.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING, cast +from typing_extensions import override + from bauiv1lib.popup import PopupWindow from bauiv1lib.colorpicker import ColorPicker import bauiv1 as bui @@ -217,6 +219,7 @@ class TeamNamesColorsWindow(PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition=transition) + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/tournamententry.py b/src/assets/ba_data/python/bauiv1lib/tournamententry.py index d00c37dd..90996bc0 100644 --- a/src/assets/ba_data/python/bauiv1lib/tournamententry.py +++ b/src/assets/ba_data/python/bauiv1lib/tournamententry.py @@ -7,6 +7,8 @@ from __future__ import annotations import logging from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -749,6 +751,7 @@ class TournamentEntryWindow(PopupWindow): if self._on_close_call is not None: self._on_close_call() + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._on_cancel() diff --git a/src/assets/ba_data/python/bauiv1lib/tournamentscores.py b/src/assets/ba_data/python/bauiv1lib/tournamentscores.py index 9d756318..ebd44de7 100644 --- a/src/assets/ba_data/python/bauiv1lib/tournamentscores.py +++ b/src/assets/ba_data/python/bauiv1lib/tournamentscores.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib.popup import PopupWindow import bauiv1 as bui @@ -244,6 +246,7 @@ class TournamentScoresWindow(PopupWindow): if self._on_close_call is not None: self._on_close_call() + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/assets/ba_data/python/bauiv1lib/trophies.py b/src/assets/ba_data/python/bauiv1lib/trophies.py index b746d05c..e605ad7c 100644 --- a/src/assets/ba_data/python/bauiv1lib/trophies.py +++ b/src/assets/ba_data/python/bauiv1lib/trophies.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING +from typing_extensions import override + from bauiv1lib import popup import bauiv1 as bui @@ -213,6 +215,7 @@ class TrophiesWindow(popup.PopupWindow): self._transitioning_out = True bui.containerwidget(edit=self.root_widget, transition='out_scale') + @override def on_popup_cancel(self) -> None: bui.getsound('swish').play() self._transition_out() diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index fa6f3b9a..75f4b12f 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int { namespace ballistica { // These are set automatically via script; don't modify them here. -const int kEngineBuildNumber = 21760; +const int kEngineBuildNumber = 21762; const char* kEngineVersion = "1.7.33"; const int kEngineApiVersion = 8; diff --git a/tests/test_efro/test_dataclassio.py b/tests/test_efro/test_dataclassio.py index 28e53eb8..1c91d47d 100644 --- a/tests/test_efro/test_dataclassio.py +++ b/tests/test_efro/test_dataclassio.py @@ -10,6 +10,7 @@ import datetime from dataclasses import field, dataclass from typing import TYPE_CHECKING, Any, Sequence, Annotated +from typing_extensions import override import pytest from efro.util import utc_now @@ -855,10 +856,12 @@ def test_extended_data() -> None: class _TestClass2(IOExtendedData): vals: tuple[int, int] + @override @classmethod def will_input(cls, data: dict) -> None: data['vals'] = data['vals'][:2] + @override def will_output(self) -> None: self.vals = (0, 0) diff --git a/tests/test_efro/test_message.py b/tests/test_efro/test_message.py index f29c5fd8..7027dfe6 100644 --- a/tests/test_efro/test_message.py +++ b/tests/test_efro/test_message.py @@ -11,6 +11,7 @@ import asyncio from typing import TYPE_CHECKING, overload, assert_type from dataclasses import dataclass +from typing_extensions import override import pytest from efro.error import CleanError, RemoteError, CommunicationError from efro.dataclassio import ioprepped @@ -39,6 +40,7 @@ class _TMsg1(Message): ival: int + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [_TResp1] @@ -51,6 +53,7 @@ class _TMsg2(Message): sval: str + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [_TResp1, _TResp2] diff --git a/tools/bacommon/build.py b/tools/bacommon/build.py index 0ffcd3fb..7e26ed55 100644 --- a/tools/bacommon/build.py +++ b/tools/bacommon/build.py @@ -21,7 +21,7 @@ class BuildInfoSet: @dataclass class Entry: - """Info about a particular build.""" + """Info about a particular app build.""" filename: Annotated[str, IOAttrs('fname')] size: Annotated[int, IOAttrs('size')] diff --git a/tools/bacommon/cloud.py b/tools/bacommon/cloud.py index 024ae231..dd14bb5b 100644 --- a/tools/bacommon/cloud.py +++ b/tools/bacommon/cloud.py @@ -7,6 +7,7 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING, Annotated from enum import Enum +from typing_extensions import override from efro.message import Message, Response from efro.dataclassio import ioprepped, IOAttrs from bacommon.transfer import DirectoryManifest @@ -21,6 +22,7 @@ if TYPE_CHECKING: class LoginProxyRequestMessage(Message): """Request send to the cloud to ask for a login-proxy.""" + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [LoginProxyRequestResponse] @@ -49,6 +51,7 @@ class LoginProxyStateQueryMessage(Message): proxyid: Annotated[str, IOAttrs('p')] proxykey: Annotated[str, IOAttrs('k')] + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [LoginProxyStateQueryResponse] @@ -85,6 +88,7 @@ class LoginProxyCompleteMessage(Message): class PingMessage(Message): """Standard ping.""" + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [PingResponse] @@ -103,6 +107,7 @@ class TestMessage(Message): testfoo: Annotated[int, IOAttrs('f')] + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [TestResponse] @@ -123,6 +128,7 @@ class PromoCodeMessage(Message): code: Annotated[str, IOAttrs('c')] + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [PromoCodeResponse] @@ -157,6 +163,7 @@ class WorkspaceFetchMessage(Message): workspaceid: Annotated[str, IOAttrs('w')] state: Annotated[WorkspaceFetchState, IOAttrs('s')] + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [WorkspaceFetchResponse] @@ -183,6 +190,7 @@ class WorkspaceFetchResponse(Response): class MerchAvailabilityMessage(Message): """Can we show merch link?""" + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [MerchAvailabilityResponse] @@ -208,6 +216,7 @@ class SignInMessage(Message): description: Annotated[str, IOAttrs('d', soft_default='-')] apptime: Annotated[float, IOAttrs('at', soft_default=-1.0)] + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [SignInResponse] @@ -226,6 +235,7 @@ class SignInResponse(Response): class ManageAccountMessage(Message): """Message asking for a manage-account url.""" + @override @classmethod def get_response_types(cls) -> list[type[Response] | None]: return [ManageAccountResponse] diff --git a/tools/batools/build.py b/tools/batools/build.py index e9bd8b2d..1bc59689 100644 --- a/tools/batools/build.py +++ b/tools/batools/build.py @@ -43,25 +43,25 @@ class PyRequirement: # remove our custom module based stuff soon if nobody complains, which # would free us to theoretically move to a requirements.txt based setup. PY_REQUIREMENTS = [ - PyRequirement(pipname='mypy', minversion=[1, 7, 0]), - PyRequirement(pipname='pylint', minversion=[3, 0, 2]), + PyRequirement(pipname='mypy', minversion=[1, 8, 0]), + PyRequirement(pipname='pylint', minversion=[3, 0, 3]), PyRequirement(pipname='cpplint', minversion=[1, 6, 1]), - PyRequirement(pipname='pytest', minversion=[7, 4, 2]), + PyRequirement(pipname='pytest', minversion=[7, 4, 4]), PyRequirement(pipname='pytz', minversion=[2023, 3]), PyRequirement(pipname='ansiwrap', minversion=[0, 8, 4]), PyRequirement(pipname='requests', minversion=[2, 31, 0]), - PyRequirement(pipname='pdoc', minversion=[14, 1, 0]), + PyRequirement(pipname='pdoc', minversion=[14, 4, 0]), PyRequirement(pipname='PyYAML', minversion=[6, 0, 1]), - PyRequirement(pipname='black', minversion=[23, 9, 1]), - PyRequirement(pipname='typing_extensions', minversion=[4, 8, 0]), + PyRequirement(pipname='black', minversion=[23, 12, 1]), + PyRequirement(pipname='typing_extensions', minversion=[4, 9, 0]), PyRequirement(pipname='types-filelock', minversion=[3, 2, 7]), - PyRequirement(pipname='types-requests', minversion=[2, 31, 0, 6]), + PyRequirement(pipname='types-requests', minversion=[2, 31, 0, 20240106]), PyRequirement(pipname='types-pytz', minversion=[2023, 3, 1, 1]), PyRequirement(pipname='types-PyYAML', minversion=[6, 0, 12, 12]), - PyRequirement(pipname='certifi', minversion=[2023, 7, 22]), + PyRequirement(pipname='certifi', minversion=[2023, 11, 17]), PyRequirement(pipname='types-certifi', minversion=[2021, 10, 8, 3]), - PyRequirement(pipname='pbxproj', minversion=[3, 5, 0]), - PyRequirement(pipname='filelock', minversion=[3, 12, 4]), + PyRequirement(pipname='pbxproj', minversion=[4, 0, 0]), + PyRequirement(pipname='filelock', minversion=[3, 13, 1]), PyRequirement(pipname='python-daemon', minversion=[3, 0, 1]), ] diff --git a/tools/batools/dummymodule.py b/tools/batools/dummymodule.py index 7fbf618e..5a29b870 100755 --- a/tools/batools/dummymodule.py +++ b/tools/batools/dummymodule.py @@ -408,13 +408,16 @@ def _special_class_cases(classname: str) -> str: ' return self\n' '\n' ' # (for index access)\n' + ' @override\n' ' def __getitem__(self, typeargs: Any) -> Any:\n' ' return 0.0\n' '\n' + ' @override\n' ' def __len__(self) -> int:\n' ' return 3\n' '\n' ' # (for iterator access)\n' + ' @override\n' ' def __iter__(self) -> Any:\n' ' return self\n' '\n' @@ -886,6 +889,8 @@ class Generator: '\n' f'from typing import {typing_imports}\n' '\n' + f'from typing_extensions import override\n' + '\n' f'{enum_import_lines}' 'if TYPE_CHECKING:\n' f' from typing import {typing_imports_tc}\n' diff --git a/tools/efro/dataclassio/extras.py b/tools/efro/dataclassio/extras.py index 327f829e..c54b0c0d 100644 --- a/tools/efro/dataclassio/extras.py +++ b/tools/efro/dataclassio/extras.py @@ -7,6 +7,8 @@ from __future__ import annotations import dataclasses from typing import TYPE_CHECKING +from typing_extensions import override + if TYPE_CHECKING: from typing import Any @@ -32,6 +34,7 @@ class DataclassDiff: self._obj1 = obj1 self._obj2 = obj2 + @override def __repr__(self) -> str: return dataclass_diff(self._obj1, self._obj2) diff --git a/tools/efro/error.py b/tools/efro/error.py index 7f902162..f0e561b7 100644 --- a/tools/efro/error.py +++ b/tools/efro/error.py @@ -6,6 +6,8 @@ from __future__ import annotations from typing import TYPE_CHECKING import errno +from typing_extensions import override + if TYPE_CHECKING: from typing import Any @@ -82,6 +84,7 @@ class RemoteError(Exception): super().__init__(msg) self._peer_desc = peer_desc + @override def __str__(self) -> str: s = ''.join(str(arg) for arg in self.args) # Indent so we can more easily tell what is the remote part when diff --git a/tools/efro/log.py b/tools/efro/log.py index 77b89996..680d94e8 100644 --- a/tools/efro/log.py +++ b/tools/efro/log.py @@ -15,6 +15,7 @@ from dataclasses import dataclass, field from typing import TYPE_CHECKING, Annotated from threading import Thread, current_thread, Lock +from typing_extensions import override from efro.util import utc_now from efro.call import tpartial from efro.terminal import Clr @@ -306,6 +307,7 @@ class LogHandler(logging.Handler): """Submit a call to be run in the logging background thread.""" self._event_loop.call_soon_threadsafe(call) + @override def emit(self, record: logging.LogRecord) -> None: # pylint: disable=too-many-branches if __debug__: diff --git a/tools/efro/message/_protocol.py b/tools/efro/message/_protocol.py index 04c1dea5..8daa8d88 100644 --- a/tools/efro/message/_protocol.py +++ b/tools/efro/message/_protocol.py @@ -386,6 +386,7 @@ class MessageProtocol: f'\n' f'from typing import TYPE_CHECKING{ovld}{ovld2}\n' f'\n' + # f'from typing_extensions import override\n' f'{import_lines}' f'\n' f'if TYPE_CHECKING:\n' diff --git a/tools/efro/util.py b/tools/efro/util.py index 807d4c00..f5815429 100644 --- a/tools/efro/util.py +++ b/tools/efro/util.py @@ -185,6 +185,12 @@ def data_size_str(bytecount: int, compact: bool = False) -> str: sane file sizes. """ # pylint: disable=too-many-return-statements + + # Special case: handle negatives. + if bytecount < 0: + val = data_size_str(-bytecount, compact=compact) + return f'-{val}' + if bytecount <= 999: suffix = 'B' if compact else 'bytes' return f'{bytecount} {suffix}' @@ -200,7 +206,7 @@ def data_size_str(bytecount: int, compact: bool = False) -> str: return f'{mbytecount:.0f} MB' gbytecount = bytecount / (1024 * 1024 * 1024) if round(gbytecount, 1) < 10.0: - return f'{mbytecount:.1f} GB' + return f'{gbytecount:.1f} GB' return f'{gbytecount:.0f} GB' diff --git a/tools/efrotools/jsontools.py b/tools/efrotools/jsontools.py index 86cd1033..708bf382 100644 --- a/tools/efrotools/jsontools.py +++ b/tools/efrotools/jsontools.py @@ -7,6 +7,8 @@ from __future__ import annotations import json from typing import TYPE_CHECKING +from typing_extensions import override + if TYPE_CHECKING: from typing import Any @@ -30,6 +32,7 @@ class NoIndentEncoder(json.JSONEncoder): del self.kwargs['indent'] self._replacement_map: dict = {} + @override def default(self, o: Any) -> Any: import uuid @@ -40,6 +43,7 @@ class NoIndentEncoder(json.JSONEncoder): return '@@%s@@' % (key,) return super().default(o) + @override def encode(self, o: Any) -> Any: result = super().encode(o) for k, v in self._replacement_map.items(): diff --git a/tools/efrotools/pybuild.py b/tools/efrotools/pybuild.py index 50d5ac8c..1177ec79 100644 --- a/tools/efrotools/pybuild.py +++ b/tools/efrotools/pybuild.py @@ -46,7 +46,7 @@ XZ_VER_APPLE = '5.4.4' # Android repo doesn't seem to be getting updated much so manually # bumping various versions to keep things up to date. -ZLIB_VER_ANDROID = '1.3' +ZLIB_VER_ANDROID = '1.3.1' XZ_VER_ANDROID = '5.4.5' BZIP2_VER_ANDROID = '1.0.8' GDBM_VER_ANDROID = '1.23' diff --git a/tools/efrotools/toolconfig.py b/tools/efrotools/toolconfig.py index deb43613..82690847 100644 --- a/tools/efrotools/toolconfig.py +++ b/tools/efrotools/toolconfig.py @@ -183,7 +183,7 @@ def _filter_tool_config(projroot: Path, cfg: str) -> str: no_implicit_reexport = True enable_error_code = redundant-expr, truthy-bool, \ -truthy-function, unused-awaitable +truthy-function, unused-awaitable, explicit-override """ ).strip()