Merge branch 'efroemling:master' into master

This commit is contained in:
Loup 2024-04-28 11:01:02 +05:30 committed by GitHub
commit 43dfac5044
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 678 additions and 612 deletions

110
.efrocachemap generated
View File

@ -945,29 +945,11 @@
"build/assets/ba_data/meshes/zoeTorso.bob": "26a1007e98902178d8c62fd7069d5da5",
"build/assets/ba_data/meshes/zoeUpperArm.bob": "a8a881010ac1ee9ec5ca872d5c5e853a",
"build/assets/ba_data/meshes/zoeUpperLeg.bob": "95b2502f74c70f934927f67cd505c3ad",
"build/assets/ba_data/python-site-packages/_yaml/__init__.py": "b09d1968d73a04d6cf20e4e79657a6e7",
"build/assets/ba_data/python-site-packages/certifi/__init__.py": "98360d9e66de68a618eed6098a65405b",
"build/assets/ba_data/python-site-packages/certifi/__main__.py": "ef02e73f8581609df189a9f61aca365b",
"build/assets/ba_data/python-site-packages/certifi/cacert.pem": "4e587dca9ab75057ffef6658ed385ff2",
"build/assets/ba_data/python-site-packages/certifi/core.py": "c1b8c102093ea26587619677c7ec6016",
"build/assets/ba_data/python-site-packages/typing_extensions.py": "f1af94a03caf6fc79be0aedc8ab03090",
"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",
"build/assets/ba_data/python-site-packages/yaml/cyaml.py": "9b11cba12e6f1cf2efe1725a20d7e1e5",
"build/assets/ba_data/python-site-packages/yaml/dumper.py": "b2cb6b4883f3504bb0255bfce6c3b09f",
"build/assets/ba_data/python-site-packages/yaml/emitter.py": "4c9bec47c3d0398c452f43a4344b2e71",
"build/assets/ba_data/python-site-packages/yaml/error.py": "e419d0e3ccb94a42881b565d285b6c9a",
"build/assets/ba_data/python-site-packages/yaml/events.py": "3e36b40c15962a78747acde2d434518d",
"build/assets/ba_data/python-site-packages/yaml/loader.py": "46f0fc4e2aef0b002bf56c87340a2650",
"build/assets/ba_data/python-site-packages/yaml/nodes.py": "43e867bb7f3cd06e0108837d9fd2a892",
"build/assets/ba_data/python-site-packages/yaml/parser.py": "d5225a0995e6802f440f7bc0bce34905",
"build/assets/ba_data/python-site-packages/yaml/reader.py": "a73be6f8420c9d02c8fe88c06c4b4dab",
"build/assets/ba_data/python-site-packages/yaml/representer.py": "8af292de41185af996c8f35ca1a96663",
"build/assets/ba_data/python-site-packages/yaml/resolver.py": "79802aa2c45560625a19e0eab318e45e",
"build/assets/ba_data/python-site-packages/yaml/scanner.py": "09239836ea50e81db330635e71460baa",
"build/assets/ba_data/python-site-packages/yaml/serializer.py": "baf67e938b13a5a3625d50d8b56180d7",
"build/assets/ba_data/python-site-packages/yaml/tokens.py": "9530e25e7cc2dfa36cff6fddc1578d9a",
"build/assets/ba_data/textures/achievementBoxer.dds": "5b5c461e67f3a92105b56fe264a7dd28",
"build/assets/ba_data/textures/achievementBoxer.ktx": "1055e009423ea1d0bc3b172f9d7328bb",
"build/assets/ba_data/textures/achievementBoxer.pvr": "48f212189a6d83d29be410613b4f0005",
@ -2595,8 +2577,8 @@
"build/assets/pylib-android/_pylong.py": "e057ab3c9eea264704dff2af204884f8",
"build/assets/pylib-android/_sitebuiltins.py": "8b5e3f6e73917962fa014ad2c4a55e61",
"build/assets/pylib-android/_strptime.py": "8c65b46a50f13ca2389b19b32b7f2996",
"build/assets/pylib-android/_sysconfigdata__linux_.py": "90ccf964f2bb27f565a4e9d1f2298701",
"build/assets/pylib-android/_sysconfigdata_d_linux_.py": "5b0f120dabd3236bbf39e7630d6f97c4",
"build/assets/pylib-android/_sysconfigdata__linux_.py": "e112c946a141bcf18e0656a14a52ca71",
"build/assets/pylib-android/_sysconfigdata_d_linux_.py": "063295bed5c2c6f30d323abb2cf82fd9",
"build/assets/pylib-android/_threading_local.py": "4a9688e3987d7d692db46feb9214945e",
"build/assets/pylib-android/_weakrefset.py": "e4fa8532ace46dfbc35149c41ea497f7",
"build/assets/pylib-android/abc.py": "a0daa1ed187eee8690c1e8438b97da90",
@ -4056,50 +4038,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": "9d6c7dcd7bf389dcbe29cfc7937d9a56",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "4f40db9f40f1c16799254b2c94696942",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2d224e9438975458e1952af0c2b0d533",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "ad311de40204ae2c96af8b7159fc4b28",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "403fe6bd30d80cf4ecefd47dba093f09",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "d9b98710fe088d506543a50294c5a3a4",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "29c87115ee8771a4a0bc17317a4a127a",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "27a27244b971b48dc545b40a3011ef1a",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "5c7540dc387ae395dd73eeb0eaea28ba",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "81bd15d634824d149e50774b3233a31e",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "37b5d59fb91dca52f1adec53e31b084f",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "af1a00445c5801b194f02ccd9398004d",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "75f400ca9e44557aa1c68aeb87b411f7",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "aa7f3acd8b8a5161fc74897b6f24d307",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "40c465bbefbb7a76abe944a237606965",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "a4ab928602e225bf6cab87fe66418420",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "386448718b4cc1df3b4ddb4792a3a38c",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "59eec91d53ef39b46c69d6955f7920c8",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "57e8c777723b873c7e90ad5d7655de15",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "67899fad5203c451e5e3411bd887100b",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "11668f7191dc8d4e2b03db15ff2a4241",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b190199ce8b8fe122993d14fb7e8e813",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "11668f7191dc8d4e2b03db15ff2a4241",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "b190199ce8b8fe122993d14fb7e8e813",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "d33507e6163f7afb54334dc6141d074b",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "15d57b7d0c2fae7695e008650a37b7f7",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "d33507e6163f7afb54334dc6141d074b",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "15d57b7d0c2fae7695e008650a37b7f7",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "6d5af317e8e9fc6d4eabeab31623e109",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "19e9dab275cd13cc3030de1b0f1f08c9",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "6d5af317e8e9fc6d4eabeab31623e109",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "19e9dab275cd13cc3030de1b0f1f08c9",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "3769b38b590a8a5623749771900e60fe",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "4fab22abc481a97e884cce9d67b35c6b",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "7c536b056d78148a302c975bf9238118",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "4fab22abc481a97e884cce9d67b35c6b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8072b0140655621c07fd97cab9e9ca2d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "758e51a2b6f52436796c607371221bbc",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "240aea32d29d4cc6260c5be61faad5c7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "30ea6e77aa5e33949bba018acbbe0b93",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "8dfb5b9a723189015c9b3eaf73816f90",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "2b82beecc22a653fc8881e76b1c9adcb",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "29893062fd160d20b621ead316232961",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "ed2ce864584e0ed9d6427bf4b1c5743c",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d74d998608b2be90551db0c1d96fe9bb",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "a98a74989bea6f6020df62a1e9df0f79",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "36f14bbd6ae38e97ff423d9d767e31c2",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "28a717bce15f9fdf6fb99483beacc19a",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fcca800df7adf35b34463e01077db1b6",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5a595984e6e663e4ead1b17fc84146e5",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "3631577e0dfa072c0e9bb603a6b5edf0",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e78b348e2b6709ef974630745d61f886",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "f51357176081a05cab1f31141d3e3edc",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "f51d29b9ed8fecb4262c925a03f7f9cb",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "f10ecde53794acf04f1ff748fe44a317",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "ae2d6b9b5648d03461564c4816d3152c",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "7545271b4990e75a372e05a6d732d244",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "bd8ccf40c3e6bdcf3cf5697b7078c5b0",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "8abba03f2364a3a5a76547f442cfc878",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "94a53e1f34519b22b3f37e53bc9f2aa9",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "6fb53a4580ba643e3e9e89f75a780fba",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ec871cfb272bee1848c5a7be5149f8b1",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "a9df11c9d43cb96ab6a3ee642658bc2c",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "159fd444515da2af0cac7818f2ba1a54",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "e40234644df79316d71808a731ba14f0",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "8563857336ffcf40abfeac81fc3955eb",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "e40234644df79316d71808a731ba14f0",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "8563857336ffcf40abfeac81fc3955eb",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "07033318a9b2b299128906c61342f391",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "403c3f754e7d900b044a9f06658fffde",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "07033318a9b2b299128906c61342f391",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "403c3f754e7d900b044a9f06658fffde",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "5cbf318e235fc9218abd1df4bca567c4",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "4989c44cc8c9854a9a1dc6bf1b633796",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "5cbf318e235fc9218abd1df4bca567c4",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "4989c44cc8c9854a9a1dc6bf1b633796",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "c40665a3e7f727e0fb7350e21bfd64aa",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "9768548c6dfdff65fb25661540025ffe",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "1a0cc7e78dc66dec6ee85a8a0d68aefd",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "9768548c6dfdff65fb25661540025ffe",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "8f9d11a98898066b9c492a62cb539843",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "994f00aa1718157f2c3ecf252218afb7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4fbd801cc96d084a1c399f44de40c6e7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "3c696fd17f85168472bb298eeeb23b58",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "cf6d352320bdaa081c8a8de122eac7ec",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "a02405ac7586f175ca2daf69d1965446",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "b8b98848ba5e0da6dee7336a6cd5284c",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "883cc779e54b299245d4e01ea061f2e8",
"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",

View File

@ -14,8 +14,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-gui-debug-build
- name: Upload the build
@ -31,8 +31,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-server-debug-build
- name: Upload the build
@ -48,8 +48,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-linux-arm64-gui-debug-build
- name: Upload the build
@ -65,8 +65,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-linux-arm64-server-debug-build
- name: Upload the build
@ -82,8 +82,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-mac-x86-64-gui-debug-build
- name: Upload the build
@ -99,8 +99,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-mac-x86-64-server-debug-build
- name: Upload the build
@ -116,8 +116,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-mac-arm64-gui-debug-build
- name: Upload the build
@ -133,8 +133,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-mac-arm64-server-debug-build
- name: Upload the build
@ -150,8 +150,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-windows-x86-gui-debug-build
- name: Upload the build
@ -167,8 +167,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make prefab-windows-x86-server-debug-build
- name: Upload the build
@ -184,8 +184,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Make the build
run: make docs-sphinx
- name: Upload the build

View File

@ -22,7 +22,7 @@ jobs:
with:
python-version: '3.12'
- name: Install dependencies
run: make prereqs
run: make env
- name: Run checks
run: BA_PCOMMANDBATCH_BUILD_REQUIRE=1 make check
@ -36,7 +36,7 @@ jobs:
with:
python-version: '3.12'
- name: Install dependencies
run: make prereqs
run: make env
- name: Assemble monolithic server build
run: make cmake-server-build
- name: Run tests
@ -54,7 +54,7 @@ jobs:
with:
python-version: '3.12'
- name: Install dependencies
run: make prereqs
run: make env
- name: Build spinoff project with only core featureset
run: make spinoff-test-core
- name: Build spinoff project with core and base featuresets
@ -72,7 +72,7 @@ jobs:
with:
python-version: '3.12'
- name: Install dependencies
run: make prereqs
run: make env
- name: Create poo feature-set
run: tools/spinoff fset-copy template_fs poo
- name: Add new feature-set to project

View File

@ -15,8 +15,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip requirements
run: make prereqs
- name: Setup project environment
run: make env
- name: Build documentation
run: make docs-sphinx
- name: Upload the build

1
.gitignore vendored
View File

@ -33,6 +33,7 @@ _fulltest_buildfile_*
ballistica_files/
tools/pcommand
tools/cloudshell
tools/bacloud
**/.#*
# Environment files

View File

@ -679,7 +679,6 @@
<w>cval</w>
<w>cwdg</w>
<w>cxxabi</w>
<w>cyaml</w>
<w>cycledelay</w>
<w>cygwinccompiler</w>
<w>dandroid</w>
@ -2019,7 +2018,6 @@
<w>objset</w>
<w>objsizes</w>
<w>objt</w>
<w>objtoyaml</w>
<w>objtype</w>
<w>objtypes</w>
<w>obval</w>
@ -3411,4 +3409,4 @@
<w>zval</w>
</words>
</dictionary>
</component>
</component>

View File

@ -1,9 +1,12 @@
### 1.7.34 (build 21804, api 8, 2024-04-23)
### 1.7.35 (build 21824, api 8, 2024-04-26)
### 1.7.34 (build 21823, api 8, 2024-04-26)
- Bumped Python version from 3.11 to 3.12 for all builds and project tools. One
of the things this means is that we can use `typing.override` instead of the
`typing_extensions` version so the annoying requirement of installing
`typing_extensions.override` version so the annoying requirement of installing
`typing_extensions` first thing when setting up the repo introduced a few
versions back is finally no longer a thing.
versions back is finally no longer a thing. I'll try to be careful to avoid
falling back into that situation in the future.
- The project now maintains its own Python virtual environment in `.venv` where
it automatically installs whatever Python packages it needs instead of asking
the user to do so in their own environment. This should greatly simplify
@ -29,6 +32,30 @@
- `_bascenev1.protocol_version()` now properly throws an exception if called
while scene-v1 is not active.
- The `efro.dataclassio` system now supports `datetime.timedelta` values.
- Usage of `pcommandbatch` is now disabled by default. To enable it, set the env
var `BA_PCOMMANDBATCH_ENABLE=1`. This is primarily due to rare sporadic
failures I have observed or have been informed of, possibly involving socket
exhaustion or other hard-to-debug OS conditions. For now I am still
considering `pcommandbatch` supported and may continue to use it myself, but
its speed gains may not be worth its added complexity indefinitely. As core
counts keep increasing in the future, the time expense of spinning up a new
Python process per pcommand decreases, making pcommandbatch less of a win.
Please holler if you have any thoughts on this.
- Renamed the `prereqs` Makefile target to `env`. This is more concise and feels
more accurate now that the target sets up things such as the Python virtual
environment and generally gets the project environment ready to use.
- (build 21810) Fixed an issue where AppSubsystems could get inited multiple
times (due to functools.cached_property no longer being thread-safe in Python
3.12).
- The server config file is now in `toml` format instead of `yaml`. Python has
built in support for reading `toml` as of 3.11 which means we don't have to
bundle extra packages, and `toml` has more of a clean minimal design that
works well for config files. Also I plan to use it for AssetPackage
configuration stuff so this keeps things consistent.
- The server config can now be set to a `.json` file as an alternative to the
default `.toml`. This can be handy when procedurally generating server
configs. If no `--config` path is explicitly passed, it will look for
`config.json` and `config.toml` in the same dir as the script in that order.
### 1.7.33 (build 21795, api 8, 2024-03-24)
- Stress test input-devices are now a bit smarter; they won't press any buttons

289
Makefile
View File

@ -25,7 +25,7 @@
################################################################################
# List targets in this Makefile and basic descriptions for them.
help: prereqs
help: env
@$(PCOMMAND) makefile_target_list Makefile
# Set env-var BA_ENABLE_COMPILE_COMMANDS_DB=1 to enable creating/updating a
@ -40,82 +40,83 @@ endif
# which.
PCOMMAND = tools/pcommand
PCOMMANDBATCHBIN = .cache/pcommandbatch/pcommandbatch
ifeq ($(BA_PCOMMANDBATCH_DISABLE),1)
PCOMMANDBATCH = $(PCOMMAND)
else
ifeq ($(BA_PCOMMANDBATCH_ENABLE),0)
PCOMMANDBATCH = $(PCOMMANDBATCHBIN)
else
PCOMMANDBATCH = $(PCOMMAND)
endif
# Prereq targets that should be safe to run anytime; even if project-files
# are out of date.
PREREQS_SAFE = .cache/checkenv $(PCOMMANDBATCHBIN) .dir-locals.el .mypy.ini \
ENV_REQS_SAFE = .cache/checkenv $(PCOMMANDBATCHBIN) .dir-locals.el .mypy.ini \
.pyrightconfig.json .pylintrc .clang-format \
ballisticakit-cmake/.clang-format .editorconfig tools/cloudshell
ballisticakit-cmake/.clang-format .editorconfig tools/cloudshell \
tools/bacloud
# Prereq targets that may break if the project needs updating should go here.
# An example is compile-command-databases; these might try to run cmake and
# fail if the CMakeList files don't match what's on disk. If such a target was
# included in PREREQS_SAFE it would try to build *before* project updates
# included in ENV_REQS_SAFE it would try to build *before* project updates
# which would leave us stuck in a broken state.
PREREQS_POST_UPDATE_ONLY = $(PREREQ_COMPILE_COMMANDS_DB)
ENV_REQS_POST_UPDATE_ONLY = $(PREREQ_COMPILE_COMMANDS_DB)
# Target that should be built before building almost any other target. This
# installs tool config files, sets up the Python virtual environment, etc.
prereqs: $(PREREQS_SAFE) $(PREREQS_POST_UPDATE_ONLY)
env: $(ENV_REQS_SAFE) $(ENV_REQS_POST_UPDATE_ONLY)
# Set of prereqs safe to run if the project state is dirty.
prereqs-pre-update: $(PREREQS_SAFE)
env-pre-update: $(ENV_REQS_SAFE)
prereqs-clean:
rm -rf $(PREREQS_SAFE) $(PREREQS_POST_UPDATE_ONLY)
env-clean:
rm -rf $(ENV_REQS_SAFE) $(ENV_REQS_POST_UPDATE_ONLY)
# Build all assets for all platforms.
assets: prereqs meta
assets: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS)
# Build assets required for cmake builds (linux, mac).
assets-cmake: prereqs meta
assets-cmake: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) cmake
# Build only script assets for cmake builds (linux, mac).
assets-cmake-scripts: prereqs meta
assets-cmake-scripts: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) scripts-cmake
# Build assets required for server builds.
assets-server: prereqs meta
assets-server: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) server
# Build assets required for WINDOWS_PLATFORM windows builds.
assets-windows: prereqs meta
assets-windows: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-$(WINDOWS_PLATFORM)
# Build assets required for Win32 windows builds.
assets-windows-Win32: prereqs meta
assets-windows-Win32: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-Win32
# Build assets required for x64 windows builds.
assets-windows-x64: prereqs meta
assets-windows-x64: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) win-x64
# Build assets required for mac xcode builds
assets-mac: prereqs meta
assets-mac: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) mac
# Build assets required for ios.
assets-ios: prereqs meta
assets-ios: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) ios
# Build assets required for android.
assets-android: prereqs meta
assets-android: env meta
@$(PCOMMAND) lazybuild assets_src $(LAZYBUILDDIR)/$@ \
cd src/assets \&\& $(MAKE) -j$(CPUS) android
@ -125,7 +126,7 @@ assets-clean:
cd src/assets && $(MAKE) clean
# Build resources.
resources: prereqs meta
resources: env meta
@$(PCOMMAND) lazybuild resources_src $(LAZYBUILDDIR)/$@ \
cd src/resources \&\& $(MAKE) -j$(CPUS)
@ -138,7 +139,7 @@ resources-clean:
#
# Meta builds can affect sources used by asset builds, resource builds, and
# compiles, so it should be listed as a dependency of any of those.
meta: prereqs
meta: env
@$(PCOMMAND) lazybuild meta_src $(LAZYBUILDDIR)/$@ \
cd src/meta \&\& $(MAKE) -j$(CPUS)
@ -149,13 +150,13 @@ meta-clean:
# Remove ALL files and directories that aren't managed by git (except for a
# few things such as localconfig.json).
clean: prereqs
clean: env
$(CHECK_CLEAN_SAFETY)
rm -rf build # Kill this ourself; can confuse git if contains other repos.
git clean -dfx $(ROOT_CLEAN_IGNORES)
# Show what clean would delete without actually deleting it.
clean-list: prereqs
clean-list: env
$(CHECK_CLEAN_SAFETY)
@echo Would remove build # Handle this part ourself; can confuse git.
git clean -dnx $(ROOT_CLEAN_IGNORES)
@ -163,22 +164,22 @@ clean-list: prereqs
# Build/update dummy python modules.
#
# IMPORTANT - building this target can kick off full builds/cleans and so it
# should not be built in parallel with other targets. See py_check_prereqs
# should not be built in parallel with other targets. See py_check_prepass
# target for more info.
dummymodules: prereqs meta
dummymodules: env meta
@$(PCOMMAND) lazybuild dummymodules_src $(LAZYBUILDDIR)/$@ \
rm -rf build/dummymodules \&\& $(PCOMMAND) gen_dummy_modules
dummymodules-clean: prereqs
dummymodules-clean: env
rm -f $(LAZYBUILDDIR)/dummymodules
rm -rf build/dummymodules
# Build the project's Python virtual environment. This should happen
# automatically as a dependency of the prereqs target.
venv: .venv/efro_venv_complete
# automatically as a dependency of the env target.
venv: .venv/.efro_venv_complete
# Update pip requirements to latest versions.
venv-upgrade: prereqs
venv-upgrade: env
$(PCOMMAND) requirements_upgrade config/requirements.txt
venv-clean:
@ -188,13 +189,13 @@ venv-clean:
#
# IMPORTANT: Docs generation targets may themselves run builds, so they should
# be run alone serially and never in parallel alongside other builds.
docs: prereqs
docs: env
$(MAKE) docs-pdoc
docs-pdoc: prereqs
docs-pdoc: env
@$(PCOMMAND) gen_docs_pdoc
docs-sphinx: prereqs
docs-sphinx: env
$(MAKE) dummymodules
@$(PCOMMAND) gen_docs_sphinx
@ -202,11 +203,11 @@ docs-sphinx-clean:
rm -rf .cache/sphinx
rm -rf build/sphinx
pcommandbatch_speed_test: prereqs
@$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCH)
pcommandbatch_speed_test: env
@$(PCOMMAND) pcommandbatch_speed_test $(PCOMMANDBATCHBIN)
# Tell make which of these targets don't represent files.
.PHONY: help prereqs prereqs-pre-update prereqs-clean assets assets-cmake \
.PHONY: help env env-pre-update env-clean assets assets-cmake \
assets-cmake-scripts assets-windows assets-windows-Win32 \
assets-windows-x64 assets-mac assets-ios assets-android assets-clean \
resources resources-clean meta meta-clean clean clean-list \
@ -235,11 +236,11 @@ prefab-gui-release: prefab-gui-release-build
$($(shell $(WSLU) $(PCOMMAND) prefab_run_var gui-release))
# Assemble a debug build for this platform.
prefab-gui-debug-build: prereqs
prefab-gui-debug-build: env
$(WSLU) $(PCOMMAND) make_prefab gui-debug
# Assemble a release build for this platform.
prefab-gui-release-build: prereqs
prefab-gui-release-build: env
$(WSLU) $(PCOMMAND) make_prefab gui-release
# Assemble & run a server debug build for this platform.
@ -251,11 +252,11 @@ prefab-server-release: prefab-server-release-build
$($(shell $(WSLU) $(PCOMMAND) prefab_run_var server-release))
# Assemble a server debug build for this platform.
prefab-server-debug-build: prereqs
prefab-server-debug-build: env
$(WSLU) $(PCOMMAND) make_prefab server-debug
# Assemble a server release build for this platform.
prefab-server-release-build: prereqs
prefab-server-release-build: env
$(WSLU) $(PCOMMAND) make_prefab server-release
# Clean all prefab builds.
@ -283,11 +284,11 @@ prefab-mac-arm64-gui-debug: prefab-mac-arm64-gui-debug-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64
$(RUN_PREFAB_MAC_ARM64_GUI_DEBUG)
prefab-mac-x86-64-gui-debug-build: prereqs assets-cmake \
prefab-mac-x86-64-gui-debug-build: env assets-cmake \
build/prefab/full/mac_x86_64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_x86_64_gui/debug
prefab-mac-arm64-gui-debug-build: prereqs assets-cmake \
prefab-mac-arm64-gui-debug-build: env assets-cmake \
build/prefab/full/mac_arm64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/mac_arm64_gui/debug
@ -313,11 +314,11 @@ prefab-mac-arm64-gui-release: prefab-mac-arm64-gui_release-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64
$(RUN_PREFAB_MAC_ARM64_GUI_RELEASE)
prefab-mac-x86-64-gui-release-build: prereqs assets-cmake \
prefab-mac-x86-64-gui-release-build: env assets-cmake \
build/prefab/full/mac_x86_64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/mac_x86_64_gui/release
prefab-mac-arm64-gui-release-build: prereqs assets-cmake \
prefab-mac-arm64-gui-release-build: env assets-cmake \
build/prefab/full/mac_arm64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/mac_arm64_gui/release
@ -343,11 +344,11 @@ prefab-mac-arm64-server-debug: prefab-mac-arm64-server-debug-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64
$(RUN_PREFAB_MAC_ARM64_SERVER_DEBUG)
prefab-mac-x86-64-server-debug-build: prereqs assets-server \
prefab-mac-x86-64-server-debug-build: env assets-server \
build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_x86_64_server/debug
prefab-mac-arm64-server-debug-build: prereqs assets-server \
prefab-mac-arm64-server-debug-build: env assets-server \
build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug build/prefab/full/mac_arm64_server/debug
@ -373,12 +374,12 @@ prefab-mac-arm64-server-release: prefab-mac-arm64-server-release-build
@$(PCOMMAND) ensure_prefab_platform mac_arm64
$(RUN_PREFAB_MAC_ARM64_SERVER_RELEASE)
prefab-mac-x86-64-server-release-build: prereqs assets-server \
prefab-mac-x86-64-server-release-build: env assets-server \
build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/mac_x86_64_server/release
prefab-mac-arm64-server-release-build: prereqs assets-server \
prefab-mac-arm64-server-release-build: env assets-server \
build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/mac_arm64_server/release
@ -405,11 +406,11 @@ prefab-linux-arm64-gui-debug: prefab-linux-arm64-gui-debug-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
$(RUN_PREFAB_LINUX_ARM64_GUI_DEBUG)
prefab-linux-x86-64-gui-debug-build: prereqs assets-cmake \
prefab-linux-x86-64-gui-debug-build: env assets-cmake \
build/prefab/full/linux_x86_64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_x86_64_gui/debug
prefab-linux-arm64-gui-debug-build: prereqs assets-cmake \
prefab-linux-arm64-gui-debug-build: env assets-cmake \
build/prefab/full/linux_arm64_gui/debug/ballisticakit
@$(STAGE_BUILD) -cmake -debug build/prefab/full/linux_arm64_gui/debug
@ -435,11 +436,11 @@ prefab-linux-arm64-gui-release: prefab-linux-arm64-gui-release-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
$(RUN_PREFAB_LINUX_ARM64_GUI_RELEASE)
prefab-linux-x86-64-gui-release-build: prereqs assets-cmake \
prefab-linux-x86-64-gui-release-build: env assets-cmake \
build/prefab/full/linux_x86_64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/linux_x86_64_gui/release
prefab-linux-arm64-gui-release-build: prereqs assets-cmake \
prefab-linux-arm64-gui-release-build: env assets-cmake \
build/prefab/full/linux_arm64_gui/release/ballisticakit
@$(STAGE_BUILD) -cmake -release build/prefab/full/linux_arm64_gui/release
@ -465,12 +466,12 @@ prefab-linux-arm64-server-debug: prefab-linux-arm64-server-debug-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
$(RUN_PREFAB_LINUX_ARM64_SERVER_DEBUG)
prefab-linux-x86-64-server-debug-build: prereqs assets-server \
prefab-linux-x86-64-server-debug-build: env assets-server \
build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug \
build/prefab/full/linux_x86_64_server/debug
prefab-linux-arm64-server-debug-build: prereqs assets-server \
prefab-linux-arm64-server-debug-build: env assets-server \
build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -debug \
build/prefab/full/linux_arm64_server/debug
@ -497,12 +498,12 @@ prefab-linux-arm64-server-release: prefab-linux-arm64-server-release-build
@$(WSLL) $(PCOMMAND) ensure_prefab_platform linux_arm64
$(RUN_PREFAB_LINUX_ARM64_SERVER_RELEASE)
prefab-linux-x86-64-server-release-build: prereqs assets-server \
prefab-linux-x86-64-server-release-build: env assets-server \
build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/linux_x86_64_server/release
prefab-linux-arm64-server-release-build: prereqs assets-server \
prefab-linux-arm64-server-release-build: env assets-server \
build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless
@$(STAGE_BUILD) -cmakeserver -release \
build/prefab/full/linux_arm64_server/release
@ -522,7 +523,7 @@ prefab-windows-x86-gui-debug: prefab-windows-x86-gui-debug-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
$(RUN_PREFAB_WINDOWS_X86_GUI_DEBUG)
prefab-windows-x86-gui-debug-build: prereqs assets-windows-$(WINPLAT_X86) \
prefab-windows-x86-gui-debug-build: env assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe
@$(STAGE_BUILD) -win-$(WINPLAT_X86) -debug \
build/prefab/full/windows_x86_gui/debug
@ -545,7 +546,7 @@ prefab-windows-x86-gui-release: prefab-windows-x86-gui-release-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
$(RUN_PREFAB_WINDOWS_X86_GUI_RELEASE)
prefab-windows-x86-gui-release-build: prereqs \
prefab-windows-x86-gui-release-build: env \
assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_gui/release/BallisticaKit.exe
@$(STAGE_BUILD) -win-$(WINPLAT_X86) -release \
@ -570,7 +571,7 @@ prefab-windows-x86-server-debug: prefab-windows-x86-server-debug-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
$(RUN_PREFAB_WINDOWS_X86_SERVER_DEBUG)
prefab-windows-x86-server-debug-build: prereqs \
prefab-windows-x86-server-debug-build: env \
assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe
@$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -debug \
@ -595,7 +596,7 @@ prefab-windows-x86-server-release: prefab-windows-x86-server-release-build
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
$(RUN_PREFAB_WINDOWS_X86_SERVER_RELEASE)
prefab-windows-x86-server-release-build: prereqs \
prefab-windows-x86-server-release-build: env \
assets-windows-$(WINPLAT_X86) \
build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe
@$(STAGE_BUILD) -winserver-$(WINPLAT_X86) -release \
@ -651,51 +652,51 @@ build/prefab/lib/windows/Release_%/BallisticaKitHeadlessPlus.pdb: .efrocachemap
SPINOFF_TEST_TARGET ?= core
# Run a given spinoff test.
spinoff-test: prereqs
spinoff-test: env
$(PCOMMAND) spinoff_test $(SPINOFF_TEST_TARGET) $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check core feature set alone.
spinoff-test-core: prereqs
spinoff-test-core: env
$(PCOMMAND) spinoff_test core $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check base feature set alone.
spinoff-test-base: prereqs
spinoff-test-base: env
$(PCOMMAND) spinoff_test base $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check plus feature set alone.
spinoff-test-plus: prereqs
spinoff-test-plus: env
$(PCOMMAND) spinoff_test plus $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check classic feature set alone.
spinoff-test-classic: prereqs
spinoff-test-classic: env
$(PCOMMAND) spinoff_test classic $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check template_fs feature set alone.
spinoff-test-template_fs: prereqs
spinoff-test-template_fs: env
$(PCOMMAND) spinoff_test template_fs $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check ui_v1 feature set alone.
spinoff-test-ui_v1: prereqs
spinoff-test-ui_v1: env
$(PCOMMAND) spinoff_test ui_v1 $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check ui_v1_lib feature set alone.
spinoff-test-ui_v1_lib: prereqs
spinoff-test-ui_v1_lib: env
$(PCOMMAND) spinoff_test ui_v1_lib $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check scene_v1 feature set alone.
spinoff-test-scene_v1: prereqs
spinoff-test-scene_v1: env
$(PCOMMAND) spinoff_test scene_v1 $(SPINOFF_TEST_EXTRA_ARGS)
# Build and check scene_v1_lib feature set alone.
spinoff-test-scene_v1_lib: prereqs
spinoff-test-scene_v1_lib: env
$(PCOMMAND) spinoff_test scene_v1_lib $(SPINOFF_TEST_EXTRA_ARGS)
# Blow away all spinoff-test builds.
spinoff-test-clean: prereqs
spinoff-test-clean: env
rm -rf build/spinofftest
# Grab the current parent project and sync it into ourself.
spinoff-update: prereqs
spinoff-update: env
@$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update
@$(PCOMMANDBATCH) echo BLU Pulling current parent project...
@ -706,7 +707,7 @@ spinoff-update: prereqs
@$(PCOMMANDBATCH) echo GRN Spinoff update successful!
# Upgrade to latest parent project and sync it into ourself.
spinoff-upgrade: prereqs
spinoff-upgrade: env
@$(PCOMMAND) spinoff_check_submodule_parent
$(MAKE) update
@$(PCOMMANDBATCH) echo BLU Pulling latest parent project...
@ -729,15 +730,15 @@ spinoff-upgrade: prereqs
################################################################################
# Update any project files that need it (does NOT build projects).
update: prereqs-pre-update
update: env-pre-update
@$(PCOMMAND) update_project
# Though not technically necessary, let's keep things like tool-configs
# immediately updated so our editors/etc. better reflect the current state.
@$(MAKE) -j$(CPUS) prereqs
@$(MAKE) -j$(CPUS) env
@$(PCOMMANDBATCH) echo GRN Update-Project: SUCCESS!
# Don't update but fail if anything needs it.
update-check: prereqs-pre-update
update-check: env-pre-update
@$(PCOMMAND) update_project --check
@$(PCOMMANDBATCH) echo GRN Check-Project: Everything up to date.
@ -752,33 +753,33 @@ update-check: prereqs-pre-update
################################################################################
# Run formatting on all files in the project considered 'dirty'.
format: prereqs
format: env
@$(MAKE) -j$(CPUS) format-code format-scripts format-makefile
@$(PCOMMANDBATCH) echo BLD Formatting complete for $(notdir $(CURDIR))!
# Same but always formats; ignores dirty state.
format-full: prereqs
format-full: env
@$(MAKE) -j$(CPUS) format-code-full format-scripts-full format-makefile
@$(PCOMMANDBATCH) echo BLD Formatting complete for $(notdir $(CURDIR))!
# Run formatting for compiled code sources (.cc, .h, etc.).
format-code: prereqs
format-code: env
@$(PCOMMAND) formatcode
# Same but always formats; ignores dirty state.
format-code-full: prereqs
format-code-full: env
@$(PCOMMAND) formatcode -full
# Runs formatting for scripts (.py, etc).
format-scripts: prereqs
format-scripts: env
@$(PCOMMAND) formatscripts
# Same but always formats; ignores dirty state.
format-scripts-full: prereqs
format-scripts-full: env
@$(PCOMMAND) formatscripts -full
# Runs formatting on the project Makefile.
format-makefile: prereqs
format-makefile: env
@$(PCOMMAND) formatmakefile
.PHONY: format format-full format-code format-code-full format-scripts \
@ -792,67 +793,67 @@ format-makefile: prereqs
################################################################################
# Run all project checks. (static analysis)
check: py_check_prereqs
check: py_check_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as check but no caching (all files are checked).
check-full: py_check_prereqs
check-full: py_check_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as 'check' plus optional/slow extra checks.
check2: py_check_prereqs
check2: py_check_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint pylint mypy
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Same as check2 but no caching (all files are checked).
check2-full: py_check_prereqs
check2-full: py_check_prepass
@$(DMAKE) -j$(CPUS) update-check cpplint-full pylint-full mypy-full
@$(PCOMMANDBATCH) echo SGRN BLD ALL CHECKS PASSED!
# Run Cpplint checks on all C/C++ code.
cpplint: prereqs meta
cpplint: env meta
@$(PCOMMAND) cpplint
# Run Cpplint checks without caching (all files are checked).
cpplint-full: prereqs meta
cpplint-full: env meta
@$(PCOMMAND) cpplint -full
# Run Pylint checks on all Python Code.
pylint: py_check_prereqs
pylint: py_check_prepass
@$(PCOMMAND) pylint
# Run Pylint checks without caching (all files are checked).
pylint-full: py_check_prereqs
pylint-full: py_check_prepass
@$(PCOMMAND) pylint -full
# Run Mypy checks on all Python code.
mypy: py_check_prereqs
mypy: py_check_prepass
@$(PCOMMAND) mypy
# Run Mypy checks without caching (all files are checked).
mypy-full: py_check_prereqs
mypy-full: py_check_prepass
@$(PCOMMAND) mypy -full
# Run Mypy checks on all Python code using daemon mode.
dmypy: py_check_prereqs
dmypy: py_check_prepass
@$(PCOMMAND) dmypy
# Stop the mypy daemon
dmypy-stop: py_check_prereqs
dmypy-stop: py_check_prepass
@$(PCOMMAND) dmypy -stop
# Run Pyright checks on all Python code.
pyright: py_check_prereqs
pyright: py_check_prepass
@$(PCOMMAND) pyright
# Run PyCharm checks on all Python code.
pycharm: py_check_prereqs
pycharm: py_check_prepass
@$(PCOMMAND) pycharm
# Run PyCharm checks without caching (all files are checked).
pycharm-full: py_check_prereqs
pycharm-full: py_check_prepass
@$(PCOMMAND) pycharm -full
# Build prerequisites needed for python checks.
@ -867,12 +868,12 @@ pycharm-full: py_check_prereqs
# others (such as by the 'check-full' target) the parent target should
# explicitly built this beforehand to ensure it does not happen during the
# parallel part.
py_check_prereqs: dummymodules
py_check_prepass: dummymodules
# Tell make which of these targets don't represent files.
.PHONY: check check-full check2 check2-full cpplint cpplint-full pylint \
pylint-full mypy mypy-full dmypy dmypy-stop pycharm pycharm-full \
py_check_prereqs
py_check_prepass
################################################################################
@ -890,12 +891,12 @@ py_check_prereqs: dummymodules
TEST_TARGET ?= tests
# Run all tests. (live execution verification)
test: py_check_prereqs
test: py_check_prepass
@$(PCOMMANDBATCH) echo BLU Running all tests...
@$(PCOMMAND) tests_warm_start
@$(PCOMMAND) pytest -v $(TEST_TARGET)
test-verbose: py_check_prereqs
test-verbose: py_check_prepass
@$(PCOMMANDBATCH) echo BLU Running all tests...
@$(PCOMMAND) tests_warm_start
@$(PCOMMAND) pytest -o log_cli=true -o log_cli_level=debug \
@ -933,7 +934,7 @@ test-rpc:
preflight:
@$(MAKE) format
@$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint pylint mypy test
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -941,7 +942,7 @@ preflight:
preflight-full:
@$(MAKE) format-full
@$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -949,7 +950,7 @@ preflight-full:
preflight2:
@$(MAKE) format
@$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint pylint mypy test
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -957,7 +958,7 @@ preflight2:
preflight2-full:
@$(MAKE) format-full
@$(MAKE) update
@$(MAKE) -j$(CPUS) py_check_prereqs # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) py_check_prepass # Needs to be done explicitly first.
@$(MAKE) -j$(CPUS) cpplint-full pylint-full mypy-full test-full
@$(PCOMMANDBATCH) echo SGRN BLD PREFLIGHT SUCCESSFUL!
@ -997,7 +998,7 @@ windows-release: windows-release-build
build/windows/Release_Win32/BallisticaKitGeneric.exe
# Build a debug windows build (from WSL).
windows-debug-build: prereqs \
windows-debug-build: env \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1007,7 +1008,7 @@ windows-debug-build: prereqs \
$(MAKE) _windows-wsl-build
# Rebuild a debug windows build (from WSL).
windows-debug-rebuild: prereqs \
windows-debug-rebuild: env \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1017,7 +1018,7 @@ windows-debug-rebuild: prereqs \
$(MAKE) _windows-wsl-rebuild
# Build a release windows build (from WSL).
windows-release-build: prereqs \
windows-release-build: env \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1027,7 +1028,7 @@ windows-release-build: prereqs \
$(MAKE) _windows-wsl-build
# Rebuild a release windows build (from WSL).
windows-release-rebuild: prereqs \
windows-release-rebuild: env \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib \
build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb
@$(WSLW) $(PCOMMAND) ensure_prefab_platform windows_x86
@ -1037,13 +1038,13 @@ windows-release-rebuild: prereqs \
$(MAKE) _windows-wsl-rebuild
# Remove all non-git-managed files in windows subdir.
windows-clean: prereqs
windows-clean: env
@$(CHECK_CLEAN_SAFETY)
git clean -dfx ballisticakit-windows
rm -rf build/windows $(LAZYBUILDDIR)
# Show what would be cleaned.
windows-clean-list: prereqs
windows-clean-list: env
@$(CHECK_CLEAN_SAFETY)
git clean -dnx ballisticakit-windows
echo would also remove build/windows $(LAZYBUILDDIR)
@ -1196,11 +1197,15 @@ DMAKE = $(MAKE) MAKEFLAGS= MKFLAGS= MAKELEVEL=
# if using this on other platforms.
CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8)
PROJ_DIR = $(abspath $(CURDIR))
# IMPORTANT: Make sure anything using these values has built env first (so
# that pcommand exists).
VERSION = $(shell $(PCOMMAND) version version)
BUILD_NUMBER = $(shell $(PCOMMAND) version build)
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
BUILD_DIR = $(PROJ_DIR)/build
LAZYBUILDDIR = .cache/lazybuild
STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build
# Things to ignore when doing root level cleans. Note that we exclude build
# and just blow that away manually; it might contain git repos or other things
@ -1216,25 +1221,32 @@ TOOL_CFG_INST = $(PCOMMAND) tool_config_install
# Anything that affects tool-config generation.
TOOL_CFG_SRC = tools/efrotools/toolconfig.py config/projectconfig.json \
.venv/efro_venv_complete tools/pcommand
.venv/.efro_venv_complete tools/pcommand
# Anything that should trigger an environment-check when changed.
ENV_SRC = tools/batools/build.py .venv/efro_venv_complete tools/pcommand
ENV_SRC = tools/batools/build.py .venv/.efro_venv_complete tools/pcommand
# Generate a pcommand script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on prereqs.
# This is a prereq dependency so should not itself depend on env.
tools/pcommand: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/pcommand...
@PYTHONPATH=tools python3 -m \
efrotools.genwrapper pcommand batools.pcommandmain tools/pcommand
# Generate a cloudshell script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on prereqs.
# This is a prereq dependency so should not itself depend on env.
tools/cloudshell: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/cloudshell...
@PYTHONPATH=tools python3 -m \
efrotools.genwrapper cloudshell efrotoolsinternal.cloudshell tools/cloudshell
# Generate a bacloud script hard-coded to use our virtual environment.
# This is a prereq dependency so should not itself depend on env.
tools/bacloud: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
@echo Generating tools/bacloud...
@PYTHONPATH=tools python3 -m \
efrotools.genwrapper bacloud batools.bacloud tools/bacloud
.clang-format: config/toolconfigsrc/clang-format $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@
@ -1253,7 +1265,7 @@ tools/cloudshell: tools/efrotools/genwrapper.py tools/efrotools/pyver.py
.mypy.ini: config/toolconfigsrc/mypy.ini $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@
.pyrightconfig.json: config/toolconfigsrc/pyrightconfig.yaml $(TOOL_CFG_SRC)
.pyrightconfig.json: config/toolconfigsrc/pyrightconfig.toml $(TOOL_CFG_SRC)
@$(TOOL_CFG_INST) $< $@
# Set this to 1 to skip environment checks.
@ -1261,27 +1273,40 @@ SKIP_ENV_CHECKS ?= 0
VENV_PYTHON ?= python3.12
# Rebuild our virtual environment whenever reqs or Python version changes.
# This is a prereq dependency so should not itself depend on prereqs. Note
# that we rely on pcommand but can't use it in here until the end when the
# venv is up.
.venv/efro_venv_complete: tools/pcommand config/requirements.txt \
# Increment this to force all downstream venvs to fully rebuild. Useful after
# removing requirements since upgrading in place will never uninstall stuff.
VENV_STATE = 1
# Rebuild our virtual environment whenever reqs, Python version, or explicit
# state number changes. This is a dependency of env so it should not itself
# depend on env. Note that we list pcommand as a requirement but can't use it
# in here until the end when the venv is up. Also note that we try to update
# venvs in place when possible, but when Python version or venv-state changes
# we blow it away and start over to be safe.
.venv/.efro_venv_complete: tools/pcommand config/requirements.txt \
tools/efrotools/pyver.py
@echo Creating Project\'s Python Virtual Environment...
@rm -rf .venv
@[ -f .venv/bin/$(VENV_PYTHON) ] \
&& [ -f .venv/.efro_venv_state_$(VENV_STATE) ] \
&& echo Updating existing $(VENV_PYTHON) virtual environment in \'.venv\'... \
|| (echo Creating new $(VENV_PYTHON) virtual environment in \'.venv\'... \
&& rm -rf .venv)
$(VENV_PYTHON) -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -r config/requirements.txt
touch .venv/efro_venv_complete # Done last to avoid partly-built venvs.
@$(PCOMMAND) echo GRN Python Virtual Environment Created.
touch .venv/.efro_venv_state_$(VENV_STATE) \
.venv/.efro_venv_complete # Done last to enforce fully-built venvs.
@$(PCOMMAND) echo \
GRN Project virtual environment for BLD $(VENV_PYTHON) RST GRN \
at BLD .venv RST GRN is ready to use.
.cache/checkenv: $(ENV_SRC)
@if [ $(SKIP_ENV_CHECKS) -ne 1 ]; then \
$(PCOMMAND) checkenv && mkdir -p .cache && touch .cache/checkenv; \
fi
$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \
$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \
src/tools/pcommandbatch/cJSON.c
@$(MAKE) tools/pcommand
@$(PCOMMAND) build_pcommandbatch $^ $@
# CMake build-type lowercase
@ -1329,7 +1354,7 @@ ballisticakit-cmake/.clang-format: .clang-format
&& mv compile_commands.json .cache/compile_commands_db
@$(PCOMMANDBATCH) echo BLU Created compile commands db at $@
_windows-wsl-build: prereqs
_windows-wsl-build: env
@$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \
$(shell $(PCOMMAND) wsl_path_to_win --escape \
@ -1340,7 +1365,7 @@ _windows-wsl-build: prereqs
$(VISUAL_STUDIO_VERSION)
@$(PCOMMAND) echo BLU BLD Built build/windows/BallisticaKit$(WINPRJ).exe.
_windows-wsl-rebuild: prereqs
_windows-wsl-rebuild: env
@$(PCOMMAND) wsl_build_check_win_drive
$(WIN_MSBUILD_EXE_B) \
$(shell $(PCOMMAND) wsl_path_to_win --escape \

View File

@ -1205,7 +1205,6 @@
<w>objpath</w>
<w>objset</w>
<w>objsizes</w>
<w>objtoyaml</w>
<w>objtypes</w>
<w>obstack</w>
<w>obvs</w>
@ -2013,4 +2012,4 @@
<w>zrot</w>
</words>
</dictionary>
</component>
</component>

View File

@ -31,8 +31,6 @@
"astroid",
"pylint.lint",
"pytest",
"pytz",
"yaml",
"requests",
"typing_extensions",
"cpplint",
@ -47,7 +45,8 @@
"openstep_parser",
"daemon",
"jinja2",
"jinja2.Environment"
"jinja2.Environment",
"tomlkit"
],
"python_paths": [
"src/assets/ba_data/python",

View File

@ -1,8 +1,8 @@
ansiwrap==0.8.4
cpplint==1.6.1
dmgbuild==1.6.1
filelock==3.13.4
furo==2024.1.29
mypy==1.9.0
mypy==1.10.0
pbxproj==4.1.0
pdoc==14.4.0
pur==7.3.1
@ -12,13 +12,10 @@ pytest==8.1.1
python-daemon==3.0.1
python-lsp-black==2.0.0
python-lsp-server==1.11.0
pytz==2024.1
PyYAML==6.0.1
requests==2.31.0
Sphinx==7.3.7
tomlkit==0.12.4
types-certifi==2021.10.8.3
types-filelock==3.2.7
types-pytz==2024.1.0.20240417
types-PyYAML==6.0.12.20240311
types-requests==2.31.0.20240406
typing_extensions==4.11.0

View File

@ -198,7 +198,7 @@ ctx.filter_file_names = {
'LICENSE',
'cloudtool',
'bacloud',
'config_template.yaml',
'config_template.toml',
'.efrocachemap',
}

View File

@ -1,6 +1,6 @@
# Ballistica Tool Config Source
These configs can be installed via 'make prereqs' in the project root.
These configs can be installed via 'make env' in the project root.
(this should automatically happen as part of other targets such as 'make check')
Some of these are filtered to include an abs path to the project root or other

View File

@ -12,9 +12,6 @@ ignore_missing_imports = True
[mypy-pylint.*]
ignore_missing_imports = True
[mypy-ansiwrap.*]
ignore_missing_imports = True
[mypy-xml.*]
ignore_missing_imports = True

View File

@ -0,0 +1,16 @@
# Pyright's actual config is a json file but we're using toml here so we
# can include lovely comments (yaml is a superset of json) and then we
# bake it down into a json file.
# For now I'm listing explicit things here. Once we get everything
# passing we can autogenerate the include list like we do for other
# checkers.
include = [ 'tools' ]
# Ideally we should get to 'strict' for everying if we want to consider
# leaning on this as much as we do mypy.
typeCheckingMode = 'basic'
reportMissingTypeStubs = true
stubPath = 'src/stubs'
pythonPlatform = 'Linux'

View File

@ -1,19 +0,0 @@
# Pyright's actual config is a json file but we're using yaml here so we can
# include lovely comments (yaml is a superset of json) and then we bake it down
# into a json file.
{
# For now I'm listing explicit things here. Once we get everything passing we
# can autogenerate the include list like we do for other checkers.
"include": [
"tools"
],
# Ideally we should get to 'strict' for everying if we want to consider
# leaning on this as much as we do mypy. But
"typeCheckingMode": "basic",
"reportMissingTypeStubs": true,
"stubPath": "src/stubs",
"pythonPlatform": "Linux"
}

View File

@ -945,8 +945,6 @@
"ba_data/meshes/zoeUpperArm.bob",
"ba_data/meshes/zoeUpperLeg.bob",
"ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/_yaml/__init__.py",
"ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/certifi/__init__.py",
"ba_data/python-site-packages/certifi/__main__.py",
"ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc",
@ -955,40 +953,6 @@
"ba_data/python-site-packages/certifi/cacert.pem",
"ba_data/python-site-packages/certifi/core.py",
"ba_data/python-site-packages/typing_extensions.py",
"ba_data/python-site-packages/yaml/__init__.py",
"ba_data/python-site-packages/yaml/__pycache__/__init__.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/composer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/constructor.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/cyaml.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/dumper.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/emitter.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/error.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/events.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/loader.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/nodes.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/parser.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/reader.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/representer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-312.opt-1.pyc",
"ba_data/python-site-packages/yaml/composer.py",
"ba_data/python-site-packages/yaml/constructor.py",
"ba_data/python-site-packages/yaml/cyaml.py",
"ba_data/python-site-packages/yaml/dumper.py",
"ba_data/python-site-packages/yaml/emitter.py",
"ba_data/python-site-packages/yaml/error.py",
"ba_data/python-site-packages/yaml/events.py",
"ba_data/python-site-packages/yaml/loader.py",
"ba_data/python-site-packages/yaml/nodes.py",
"ba_data/python-site-packages/yaml/parser.py",
"ba_data/python-site-packages/yaml/reader.py",
"ba_data/python-site-packages/yaml/representer.py",
"ba_data/python-site-packages/yaml/resolver.py",
"ba_data/python-site-packages/yaml/scanner.py",
"ba_data/python-site-packages/yaml/serializer.py",
"ba_data/python-site-packages/yaml/tokens.py",
"ba_data/textures/achievementBoxer.dds",
"ba_data/textures/achievementBoxer.ktx",
"ba_data/textures/achievementBoxer.pvr",

View File

@ -28,12 +28,12 @@ PCOMMAND = $(TOOLS_DIR)/pcommand
# pcommand. See tools/efrotools/pcommandbatch.py for more info on when to use
# which.
PCOMMANDBATCHBIN = $(PROJ_DIR)/.cache/pcommandbatch/pcommandbatch
ifeq ($(BA_PCOMMANDBATCH_DISABLE),1)
PCOMMANDBATCH = $(TOOLS_DIR)/pcommand
PCOMMANDBATCHFROMROOT = tools/pcommand
else
ifeq ($(BA_PCOMMANDBATCH_ENABLE),0)
PCOMMANDBATCH = $(PCOMMANDBATCHBIN)
PCOMMANDBATCHFROMROOT = .cache/pcommandbatch/pcommandbatch
else
PCOMMANDBATCH = $(TOOLS_DIR)/pcommand
PCOMMANDBATCHFROMROOT = tools/pcommand
endif
# High level targets: generally these are what should be used here.
@ -2691,53 +2691,17 @@ $(foreach element,$(SCRIPT_TARGETS_PYC_PRIVATE_ANDROID),\
$(eval $(call make-opt-pyc-target,$(element))))
SCRIPT_TARGETS_PY_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/_yaml/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__main__.py \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/core.py \
$(BUILD_DIR)/ba_data/python-site-packages/typing_extensions.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__init__.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/composer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/constructor.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/cyaml.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/dumper.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/emitter.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/error.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/events.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/loader.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/nodes.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/parser.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/reader.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/representer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/resolver.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/scanner.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/serializer.py \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/tokens.py \
$(BUILD_DIR)/sphinx/static/conf.py
SCRIPT_TARGETS_PYC_PRIVATE_COMMON = \
$(BUILD_DIR)/ba_data/python-site-packages/_yaml/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/__main__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/certifi/__pycache__/core.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/__pycache__/typing_extensions.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/__init__.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/composer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/constructor.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/cyaml.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/dumper.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/emitter.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/error.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/events.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/loader.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/nodes.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/parser.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/reader.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/representer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/resolver.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/scanner.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/serializer.cpython-312.opt-1.pyc \
$(BUILD_DIR)/ba_data/python-site-packages/yaml/__pycache__/tokens.cpython-312.opt-1.pyc \
$(BUILD_DIR)/sphinx/static/__pycache__/conf.cpython-312.opt-1.pyc
# Rule to copy src asset scripts to dst.

View File

@ -9,7 +9,8 @@ import logging
from enum import Enum
from typing import TYPE_CHECKING, TypeVar, override
from concurrent.futures import ThreadPoolExecutor
from functools import cached_property
from threading import RLock
from efro.call import tpartial
@ -45,6 +46,8 @@ if TYPE_CHECKING:
T = TypeVar('T')
Tsub = TypeVar('Tsub', bound='AppSubsystem')
class App:
"""A class for high level app functionality and state.
@ -219,6 +222,13 @@ class App:
]
self._pool_thread_count = 0
# We hold a lock while lazy-loading our subsystem properties so
# we don't spin up any subsystem more than once, but the lock is
# recursive so that the subsystems can instantiate other
# subsystems.
self._subsystem_property_lock = RLock()
self._subsystem_property_data: dict[str, AppSubsystem | bool] = {}
def postinit(self) -> None:
"""Called after we've been inited and assigned to babase.app.
@ -331,14 +341,64 @@ class App:
def mode_selector(self, selector: babase.AppModeSelector) -> None:
self._mode_selector = selector
def _get_subsystem_property(
self, ssname: str, create_call: Callable[[], AppSubsystem | None]
) -> AppSubsystem | None:
# Quick-out: if a subsystem object is present, just return it;
# no locking necessary.
val = self._subsystem_property_data.get(ssname)
if val is not None:
if val is False:
# False means subsystem is confirmed as not present.
return None
if val is not True:
# A subsystem has been set. Return it.
return val
# Anything else (no val present or val True) requires locking.
with self._subsystem_property_lock:
val = self._subsystem_property_data.get(ssname)
if val is not None:
if val is False:
# False means confirmed as not present.
return None
if val is True:
# True means this property is already being loaded;
# not good.
raise RuntimeError(
f'Recursive subsystem load detected for {ssname}'
)
# Must be an instantiated subsystem. Noice.
return val
# Ok, there's nothing here for it. Instantiate and set it
# while we hold the lock. Set a placeholder value of True
# first so we know if something tries to recursively
# instantiate us while we're instantiating.
self._subsystem_property_data[ssname] = True
# Do our one attempt to create the singleton.
val = create_call()
self._subsystem_property_data[ssname] = (
False if val is None else val
)
return val
# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__
# This section generated by batools.appmodule; do not edit.
@cached_property
@property
def classic(self) -> ClassicSubsystem | None:
"""Our classic subsystem (if available)."""
# pylint: disable=cyclic-import
return self._get_subsystem_property(
'classic', self._create_classic_subsystem
) # type: ignore
@staticmethod
def _create_classic_subsystem() -> ClassicSubsystem | None:
# pylint: disable=cyclic-import
try:
from baclassic import ClassicSubsystem
@ -349,11 +409,16 @@ class App:
logging.exception('Error importing baclassic.')
return None
@cached_property
@property
def plus(self) -> PlusSubsystem | None:
"""Our plus subsystem (if available)."""
# pylint: disable=cyclic-import
return self._get_subsystem_property(
'plus', self._create_plus_subsystem
) # type: ignore
@staticmethod
def _create_plus_subsystem() -> PlusSubsystem | None:
# pylint: disable=cyclic-import
try:
from baplus import PlusSubsystem
@ -364,9 +429,15 @@ class App:
logging.exception('Error importing baplus.')
return None
@cached_property
@property
def ui_v1(self) -> UIV1Subsystem:
"""Our ui_v1 subsystem (always available)."""
return self._get_subsystem_property(
'ui_v1', self._create_ui_v1_subsystem
) # type: ignore
@staticmethod
def _create_ui_v1_subsystem() -> UIV1Subsystem:
# pylint: disable=cyclic-import
from bauiv1 import UIV1Subsystem

View File

@ -7,6 +7,8 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from efro.util import utc_now
import babase
import bascenev1
@ -522,10 +524,10 @@ class StoreSubsystem:
if item in sales_raw:
if not plus.get_purchased(item):
to_end = (
datetime.datetime.utcfromtimestamp(
sales_raw[item]['e']
datetime.datetime.fromtimestamp(
sales_raw[item]['e'], datetime.UTC
)
- datetime.datetime.utcnow()
- utc_now()
).total_seconds()
if to_end > 0:
sale_times.append(int(to_end * 1000))

View File

@ -52,8 +52,8 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21804
TARGET_BALLISTICA_VERSION = '1.7.34'
TARGET_BALLISTICA_BUILD = 21824
TARGET_BALLISTICA_VERSION = '1.7.35'
@dataclass

View File

@ -6,6 +6,8 @@ from __future__ import annotations
from typing import TYPE_CHECKING
from efro.util import utc_now
import bauiv1 as bui
if TYPE_CHECKING:
@ -541,24 +543,24 @@ class GetCurrencyWindow(bui.Window):
plus = bui.app.plus
assert plus is not None
# if we somehow get signed out, just die..
# If we somehow get signed out, just die.
if plus.get_v1_account_state() != 'signed_in':
self._back()
return
self._ticket_count = plus.get_v1_account_ticket_count()
# update our incentivized ad button depending on whether ads are
# available
# Update our incentivized ad button depending on whether ads are
# available.
if self._ad_button is not None:
next_reward_ad_time = plus.get_v1_account_misc_read_val_2(
'nextRewardAdTime', None
)
if next_reward_ad_time is not None:
next_reward_ad_time = datetime.datetime.utcfromtimestamp(
next_reward_ad_time
next_reward_ad_time = datetime.datetime.fromtimestamp(
next_reward_ad_time, datetime.UTC
)
now = datetime.datetime.utcnow()
now = utc_now()
if plus.have_incentivized_ad() and (
next_reward_ad_time is None or next_reward_ad_time <= now
):
@ -586,8 +588,8 @@ class GetCurrencyWindow(bui.Window):
sval = ''
bui.textwidget(edit=self._ad_time_text, text=sval)
# if this is our first update, assign immediately; otherwise kick
# off a smooth transition if the value has changed
# If this is our first update, assign immediately; otherwise kick
# off a smooth transition if the value has changed.
if self._smooth_ticket_count is None:
self._smooth_ticket_count = float(self._ticket_count)
self._smooth_update() # will set the text widget
@ -614,8 +616,8 @@ class GetCurrencyWindow(bui.Window):
plus = bui.app.plus
assert plus is not None
# if we're on a platform without purchases, inform the user they
# can link their accounts and buy stuff elsewhere
# If we're on a platform without purchases, inform the user they
# can link their accounts and buy stuff elsewhere.
app = bui.app
assert app.classic is not None
if (
@ -652,8 +654,10 @@ class GetCurrencyWindow(bui.Window):
return
appinvite.handle_app_invites_press()
return
# here we ping the server to ask if it's valid for us to
# purchase this.. (better to fail now than after we've paid locally)
# Here we ping the server to ask if it's valid for us to
# purchase this.. (better to fail now than after we've paid
# locally).
app = bui.app
assert app.classic is not None
bui.app.classic.master_server_v1_get(
@ -694,7 +698,7 @@ class GetCurrencyWindow(bui.Window):
color=(1, 0, 0),
)
# actually start the purchase locally..
# Actually start the purchase locally.
def _do_purchase(self, item: str) -> None:
plus = bui.app.plus
assert plus is not None
@ -702,15 +706,15 @@ class GetCurrencyWindow(bui.Window):
if item == 'ad':
import datetime
# if ads are disabled until some time, error..
# If ads are disabled until some time, error.
next_reward_ad_time = plus.get_v1_account_misc_read_val_2(
'nextRewardAdTime', None
)
if next_reward_ad_time is not None:
next_reward_ad_time = datetime.datetime.utcfromtimestamp(
next_reward_ad_time
next_reward_ad_time = datetime.datetime.fromtimestamp(
next_reward_ad_time, datetime.UTC
)
now = datetime.datetime.utcnow()
now = utc_now()
if (
next_reward_ad_time is not None and next_reward_ad_time > now
) or self._ad_button_greyed:
@ -730,7 +734,7 @@ class GetCurrencyWindow(bui.Window):
def _back(self) -> None:
from bauiv1lib.store import browser
# no-op if our underlying widget is dead or on its way out.
# No-op if our underlying widget is dead or on its way out.
if not self._root_widget or self._root_widget.transitioning_out:
return

View File

@ -15,6 +15,7 @@ from enum import Enum
from threading import Thread
from typing import TYPE_CHECKING
from efro.util import utc_now
from efro.error import CommunicationError
import bacommon.cloud
import bauiv1 as bui
@ -681,8 +682,10 @@ class StoreBrowserWindow(bui.Window):
# Look at the current set of sales; filter any with time remaining.
for sale_item, sale_info in list(sales_raw.items()):
to_end = (
datetime.datetime.utcfromtimestamp(sale_info['e'])
- datetime.datetime.utcnow()
datetime.datetime.fromtimestamp(
sale_info['e'], datetime.UTC
)
- utc_now()
).total_seconds()
if to_end > 0:
sales[sale_item] = {

View File

@ -6,6 +6,8 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING
from efro.util import utc_now
import bauiv1 as bui
if TYPE_CHECKING:
@ -278,8 +280,10 @@ class StoreButton:
for sale_item, sale_info in list(sales_raw.items()):
if not plus.get_purchased(sale_item):
to_end = (
datetime.datetime.utcfromtimestamp(sale_info['e'])
- datetime.datetime.utcnow()
datetime.datetime.fromtimestamp(
sale_info['e'], datetime.UTC
)
- utc_now()
).total_seconds()
if to_end > 0:
sale_times.append(to_end)

View File

@ -2,8 +2,8 @@ To run this, simply cd into this directory and run ./ballisticakit_server
(on mac or linux) or launch_ballisticakit_server.bat (on windows).
You'll need to open a UDP port (43210 by default) so that the world can
communicate with your server.
You can configure your server by editing the config.yaml file.
(if you only see config_template.yaml, you can copy/rename that to config.yaml)
You can configure your server by editing the config.toml file.
(if you only see config_template.toml, you can copy/rename that to config.toml)
Platform-Specific Notes:

View File

@ -1,15 +1,17 @@
#!/usr/bin/env python3.12
# Released under the MIT License. See LICENSE for details.
#
# pylint: disable=too-many-lines
"""BallisticaKit server manager."""
from __future__ import annotations
import json
import os
import signal
import subprocess
import sys
import time
import json
import signal
import tomllib
import subprocess
from pathlib import Path
from threading import Lock, Thread, current_thread
from typing import TYPE_CHECKING
@ -39,6 +41,12 @@ VERSION_STR = '1.3.2'
#
# - Updated to use Python 3.12.
#
# - Server config file is now in toml format instead of yaml.
#
# - Server config can now be set to a .json file OR a .toml file.
# By default it will look for 'config.json' and then 'config.toml'
# in the same dir as this script.
#
# 1.3.1
#
# - Windows binary is now named 'BallisticaKitHeadless.exe'.
@ -101,8 +109,7 @@ class ServerManagerApp:
IMMEDIATE_SHUTDOWN_TIME_LIMIT = 5.0
def __init__(self) -> None:
self._config_path = 'config.yaml'
self._user_provided_config_path = False
self._user_provided_config_path: str | None = None
self._config = ServerConfig()
self._ba_root_path = os.path.abspath('dist/ba_root')
self._interactive = sys.stdin.isatty()
@ -125,13 +132,14 @@ class ServerManagerApp:
self._subprocess_sent_unclean_exit = False
self._subprocess_thread: Thread | None = None
self._subprocess_exited_cleanly: bool | None = None
self._did_multi_config_warning = False
# This may override the above defaults.
self._parse_command_line_args()
# Do an initial config-load. If the config is invalid at this
# point we can cleanly die (we're more lenient later on
# reloads).
# point we can cleanly die; we're more resilient later on reload
# attempts.
self.load_config(strict=True, print_confirmation=False)
@property
@ -407,8 +415,7 @@ class ServerManagerApp:
raise CleanError(f"Supplied path does not exist: '{path}'.")
# We need an abs path because we may be in a different
# cwd currently than we will be during the run.
self._config_path = os.path.abspath(path)
self._user_provided_config_path = True
self._user_provided_config_path = os.path.abspath(path)
i += 2
elif arg == '--root':
if i + 1 >= argc:
@ -476,11 +483,9 @@ class ServerManagerApp:
+ cls._par(
'Set the config file read by the server script. The config'
' file contains most options for what kind of game to host.'
' It should be in yaml format. Note that yaml is backwards'
' compatible with json so you can just write json if you'
' want to. If not specified, the script will look for a'
' file named \'config.yaml\' in the same directory as the'
' script.'
' It should be in toml or json format. If not specified,'
' the script will look for a file named \'config.toml\' or'
' \'config.json\' in the same directory as the script.'
)
+ '\n'
f'{Clr.BLD}--root [path]{Clr.RST}\n'
@ -570,21 +575,51 @@ class ServerManagerApp:
return
time.sleep(1)
def _get_config_path(self) -> str:
if self._user_provided_config_path is not None:
return self._user_provided_config_path
# Otherwise look for config.toml or config.json in the same dir
# as our script. Need to work in abs paths since we may chdir when
# we start running.
toml_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'config.toml')
)
toml_exists = os.path.exists(toml_path)
json_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), 'config.json')
)
json_exists = os.path.exists(json_path)
# Warn if both configs are present.
if toml_exists and json_exists and not self._did_multi_config_warning:
self._did_multi_config_warning = True
print(
f'{Clr.YLW}Both config.toml and config.json'
f' found; will use json.{Clr.RST}',
flush=True,
)
if json_exists:
return json_path
return toml_path
def _load_config_from_file(self, print_confirmation: bool) -> ServerConfig:
out: ServerConfig | None = None
if not os.path.exists(self._config_path):
config_path = self._get_config_path()
if not os.path.exists(config_path):
# Special case:
#
# If the user didn't specify a particular config file, allow
# gracefully falling back to defaults if the default one is
# missing.
# If the user didn't provide a config path AND the default
# config path does not exist, fall back to defaults.
if not self._user_provided_config_path:
if print_confirmation:
print(
f'{Clr.YLW}Default config file not found'
f' (\'{self._config_path}\'); using default'
f' settings.{Clr.RST}',
f' (\'{config_path}\'); using default'
f' config.{Clr.RST}',
flush=True,
)
self._config_mtime = None
@ -592,25 +627,25 @@ class ServerManagerApp:
return ServerConfig()
# Don't be so lenient if the user pointed us at one though.
raise RuntimeError(f"Config file not found: '{self._config_path}'.")
raise RuntimeError(f"Config file not found: '{config_path}'.")
import yaml
with open(config_path, encoding='utf-8') as infile:
if config_path.endswith('.toml'):
user_config_raw = tomllib.loads(infile.read())
elif config_path.endswith('.json'):
user_config_raw = json.loads(infile.read())
else:
raise CleanError(
f"Invalid config file path '{config_path}';"
f" path must end with '.toml' or '.json'."
)
with open(self._config_path, encoding='utf-8') as infile:
user_config_raw = yaml.safe_load(infile.read())
# An empty config file will yield None, and that's ok.
if user_config_raw is not None:
out = dataclass_from_dict(ServerConfig, user_config_raw)
out = dataclass_from_dict(ServerConfig, user_config_raw)
# Update our known mod-time since we know it exists.
self._config_mtime = Path(self._config_path).stat().st_mtime
self._config_mtime = Path(config_path).stat().st_mtime
self._last_config_mtime_check_time = time.time()
# Go with defaults if we weren't able to load anything.
if out is None:
out = ServerConfig()
if print_confirmation:
print(
f'{Clr.CYN}Valid server config file loaded.{Clr.RST}',
@ -885,8 +920,9 @@ class ServerManagerApp:
):
self._last_config_mtime_check_time = now
mtime: float | None
if os.path.isfile(self._config_path):
mtime = Path(self._config_path).stat().st_mtime
config_path = self._get_config_path()
if os.path.isfile(config_path):
mtime = Path(config_path).stat().st_mtime
else:
mtime = None
if mtime != self._config_mtime:

View File

@ -1,5 +1,5 @@
# To configure your server, create a config.yaml file in the same directory
# as the ballisticakit_server script. The config_template.yaml file can be
# To configure your server, create a config.toml file in the same directory
# as the ballisticakit_server script. The config_template.toml file can be
# copied or renamed as a convenient starting point.
# Uncomment any of these values to override defaults.

View File

@ -39,8 +39,8 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21804;
const char* kEngineVersion = "1.7.34";
const int kEngineBuildNumber = 21824;
const char* kEngineVersion = "1.7.35";
const int kEngineApiVersion = 8;
#if BA_MONOLITHIC_BUILD

View File

@ -20,7 +20,7 @@ from typing import (
)
import pytest
from efro.util import utc_now
from efro.util import utc_now, utc_now_naive
from efro.dataclassio import (
dataclass_validate,
dataclass_from_dict,
@ -69,8 +69,6 @@ class _NestedClass:
dval: dict[int, str] = field(default_factory=dict)
# We use utc_now() for a test which is deprecated.
@pytest.mark.filterwarnings('ignore::DeprecationWarning')
def test_assign() -> None:
"""Testing various assignments."""
@ -292,8 +290,8 @@ def test_assign() -> None:
with pytest.raises(ValueError):
dataclass_to_dict(_TestClass(datetimeval=datetime.datetime.now()))
with pytest.raises(ValueError):
# This doesn't actually set timezone on the datetime obj.
dataclass_to_dict(_TestClass(datetimeval=datetime.datetime.utcnow()))
# This doesn't have a timezone on the datetime obj.
dataclass_to_dict(_TestClass(datetimeval=utc_now_naive()))
def test_coerce() -> None:

View File

@ -1,23 +0,0 @@
#!/usr/bin/env python3.12
# Released under the MIT License. See LICENSE for details.
#
"""A tool for interacting with ballistica's cloud services.
This facilitates workflows such as creating asset-packages, etc.
"""
from __future__ import annotations
import sys
from batools.bacloud import App
from efro.error import CleanError
try:
App().run()
except KeyboardInterrupt:
# Let's do a clean fail on keyboard interrupt.
# Can make this optional if a backtrace is ever useful.
sys.exit(1)
except CleanError as clean_exc:
clean_exc.pretty_print()
sys.exit(1)

View File

@ -69,11 +69,10 @@ def generate_app_module(
contents = ''
for fsetname in sorted(all_fset_names):
# for _fsname, fset in sorted(fsets.items()):
if fsetname in missing_soft_fset_names:
contents += (
f'\n'
f'@cached_property\n'
f'@property\n'
f'def {fsetname}(self) -> Any | None:\n'
f' """Our {fsetname} subsystem (not available'
f' in this project)."""\n'
@ -95,11 +94,18 @@ def generate_app_module(
if fset.allow_as_soft_requirement:
contents += (
f'\n'
f'@cached_property\n'
f'@property\n'
f'def {fset.name}(self) -> {classname} | None:\n'
f' """Our {fset.name} subsystem (if available)."""\n'
f' # pylint: disable=cyclic-import\n'
f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname} | None:\n'
f' # pylint: disable=cyclic-import\n'
f' try:\n'
f' from {modname} import {classname}\n'
f'\n'
@ -114,10 +120,18 @@ def generate_app_module(
else:
contents += (
f'\n'
f'@cached_property\n'
'@property\n'
f'def {fset.name}(self) -> {classname}:\n'
f' """Our {fset.name} subsystem'
' (always available)."""\n'
f' return self._get_subsystem_property(\n'
f" '{fset.name}', "
f'self._create_{fset.name}_subsystem\n'
f' ) # type: ignore\n'
f'\n'
f'@staticmethod\n'
f'def _create_{fset.name}_subsystem()'
f' -> {classname}:\n'
f' # pylint: disable=cyclic-import\n'
f'\n'
f' from {modname} import {classname}\n'

View File

@ -50,13 +50,31 @@ class StateData:
def get_tz_offset_seconds() -> float:
"""Return the offset between utc and local time in seconds."""
tval = time.time()
# Compare naive current and utc times to get our offset from utc.
utc_offset = (
datetime.datetime.fromtimestamp(tval)
- datetime.datetime.utcfromtimestamp(tval)
- datetime.datetime.fromtimestamp(tval, datetime.UTC).replace(
tzinfo=None
)
).total_seconds()
return utc_offset
def run_bacloud_main() -> None:
"""Do the thing."""
try:
App().run()
except KeyboardInterrupt:
# Let's do a clean fail on keyboard interrupt.
# Can make this optional if a backtrace is ever useful.
sys.exit(1)
except CleanError as clean_exc:
clean_exc.pretty_print()
sys.exit(1)
class App:
"""Context for a run of the tool."""
@ -76,17 +94,17 @@ class App:
):
raise CleanError('Unable to locate project directory.')
# Also run project prereqs checks so we can hopefully inform the user
# Also run project env checks so we can hopefully inform the user
# of missing Python modules/etc. instead of just failing cryptically.
try:
subprocess.run(
['make', '--quiet', 'prereqs'],
['make', '--quiet', 'env'],
check=True,
cwd=self._project_root,
)
except subprocess.CalledProcessError as exc:
raise CleanError(
'"make prereqs" check failed. '
'"make env" check failed. '
'Install missing requirements and try again.'
) from exc

View File

@ -446,92 +446,85 @@ def _get_server_config_raw_contents(projroot: str) -> str:
return textwrap.dedent('\n'.join(lines[firstline : lastline + 1]))
def _get_server_config_template_yaml(projroot: str) -> str:
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
import yaml
def _get_server_config_template_toml(projroot: str) -> str:
from tomlkit import document, dumps
from bacommon.servermanager import ServerConfig
cfg = ServerConfig()
# Override some defaults with values we want to display commented
# out instead.
cfg.playlist_code = 12345
cfg.stats_url = 'https://mystatssite.com/showstats?player=${ACCOUNT}'
cfg.clean_exit_minutes = 60
cfg.unclean_exit_minutes = 90
cfg.idle_exit_minutes = 20
cfg.admins = ['pb-yOuRAccOuNtIdHErE', 'pb-aNdMayBeAnotherHeRE']
cfg.protocol_version = 35
cfg.session_max_players_override = 8
cfg.playlist_inline = []
cfg.team_names = ('Red', 'Blue')
cfg.team_colors = ((0.1, 0.25, 1.0), (1.0, 0.25, 0.2))
lines_in = _get_server_config_raw_contents(projroot).splitlines()
# Convert to double quotes only (we'll convert back at the end).
assert all(('"' not in l) for l in lines_in)
lines_in = [l.replace("'", '"') for l in lines_in]
lines_out: list[str] = []
ignore_vars = {'stress_test_players'}
for line in lines_in:
if any(line.startswith(f'{var}:') for var in ignore_vars):
continue
if line.startswith(' '):
# Ignore indented lines (our few multi-line special cases).
continue
if line.startswith(']') or line.startswith(')'):
# Ignore closing lines (our few multi-line special cases).
continue
# Replace attr declarations with commented out toml values.
if line != '' and not line.startswith('#') and ':' in line:
before_colon, _after_colon = line.split(':', 1)
vname = before_colon.strip()
if vname in ignore_vars:
continue
vval: Any = getattr(cfg, vname)
if line.startswith('team_names:'):
lines_out += [
'#team_names:',
'#- Blue',
'#- Red',
]
continue
doc = document()
# Toml doesn't support None/null
if vval is None:
raise RuntimeError(
f"ServerManager value '{vname}' has value None."
f' This is not allowed in toml;'
f' please provide a dummy value.'
)
assert vval is not None
doc[vname] = vval
lines_out += ['#' + l for l in dumps(doc).strip().splitlines()]
if line.startswith('team_colors:'):
lines_out += [
'#team_colors:',
'#- [0.1, 0.25, 1.0]',
'#- [1.0, 0.25, 0.2]',
]
continue
# Preserve blank lines, but only one in a row.
elif line == '':
if not lines_out or lines_out[-1] != '':
lines_out.append(line)
if line.startswith('playlist_inline:'):
lines_out += ['#playlist_inline: []']
continue
if line != '' and not line.startswith('#'):
before_equal_sign, vval_raw = line.split('=', 1)
before_equal_sign = before_equal_sign.strip()
vval_raw = vval_raw.strip()
vname = before_equal_sign.split()[0]
assert vname.endswith(':'), f"'{vname}' does not end with ':'"
vname = vname[:-1]
vval: Any
if vval_raw == 'field(default_factory=list)':
vval = []
else:
vval = eval(vval_raw) # pylint: disable=eval-used
# Filter/override a few things.
if vname == 'playlist_code':
# User wouldn't want to pass the default of None here.
vval = 12345
elif vname == 'clean_exit_minutes':
vval = 60
elif vname == 'unclean_exit_minutes':
vval = 90
elif vname == 'idle_exit_minutes':
vval = 20
elif vname == 'stats_url':
vval = 'https://mystatssite.com/showstats?player=${ACCOUNT}'
elif vname == 'admins':
vval = ['pb-yOuRAccOuNtIdHErE', 'pb-aNdMayBeAnotherHeRE']
elif vname == 'protocol_version':
vval = 35
lines_out += [
'#' + l for l in yaml.dump({vname: vval}).strip().splitlines()
]
else:
# Convert comments referring to python bools to yaml bools.
# Preserve comment lines.
elif line.startswith('#'):
# Convert comments referring to python bools to toml bools.
line = line.replace('True', 'true').replace('False', 'false')
if '(internal)' not in line:
lines_out.append(line)
return '\n'.join(lines_out)
out = '\n'.join(lines_out)
# Convert back to single quotes only.
assert "'" not in out
out = out.replace('"', "'")
return out
def filter_server_config(projroot: str, infilepath: str) -> str:
def filter_server_config_toml(projroot: str, infilepath: str) -> str:
"""Add commented-out config options to a server config."""
with open(infilepath, encoding='utf-8') as infile:
cfg = infile.read()
return cfg.replace(
'# __CONFIG_TEMPLATE_VALUES__',
_get_server_config_template_yaml(projroot),
_get_server_config_template_toml(projroot),
)

View File

@ -1050,7 +1050,8 @@ class SpinoffContext:
# The proper way might be to ask the parent repo for its full list of
# script files but that would add more expense.
if (
src_path.endswith('.py') or src_path in {'tools/cloudshell'}
src_path.endswith('.py')
# or src_path in {'tools/cloudshell'}
) and out != text:
self._ensure_parent_repo_tool_configs_exist()
out = format_python_str(projroot=self._src_root, code=out)
@ -1071,7 +1072,7 @@ class SpinoffContext:
# Interestingly, seems we need to use shell command cd here
# instead of just passing cwd arg.
subprocess.run(
f'cd {self._src_root} && make prereqs',
f'cd {self._src_root} && make env',
shell=True,
check=True,
capture_output=True,

View File

@ -669,8 +669,8 @@ class AssetStager:
projroot=self.projroot,
mode=modeval,
infilename=f'{self.projroot}/src/assets/server_package/'
'config_template.yaml',
outfilename=os.path.join(self.serverdst, 'config_template.yaml'),
'config_template.toml',
outfilename=os.path.join(self.serverdst, 'config_template.toml'),
)
if self.win_type is not None:
fname = 'launch_ballisticakit_server.bat'
@ -763,11 +763,11 @@ def _stage_server_file(
os.makedirs(os.path.dirname(outfilename), exist_ok=True)
basename = os.path.basename(infilename)
if basename == 'config_template.yaml':
if basename == 'config_template.toml':
# Inject all available config values into the config file.
_write_if_changed(
outfilename,
batools.build.filter_server_config(str(projroot), infilename),
batools.build.filter_server_config_toml(str(projroot), infilename),
)
elif basename == 'ballisticakit_server.py':

View File

@ -12,16 +12,6 @@ import functools
from enum import Enum
from typing import TYPE_CHECKING, cast, TypeVar, Generic
_pytz_utc: Any
# We don't *require* pytz, but we want to support it for tzinfos if available.
try:
import pytz
_pytz_utc = pytz.utc
except ModuleNotFoundError:
_pytz_utc = None # pylint: disable=invalid-name
if TYPE_CHECKING:
import asyncio
from efro.call import Call as Call # 'as Call' so we re-export.
@ -112,29 +102,35 @@ def enum_by_value(cls: type[EnumT], value: Any) -> EnumT:
def check_utc(value: datetime.datetime) -> None:
"""Ensure a datetime value is timezone-aware utc."""
if value.tzinfo is not datetime.timezone.utc and (
_pytz_utc is None or value.tzinfo is not _pytz_utc
):
if value.tzinfo is not datetime.UTC:
raise ValueError(
'datetime value does not have timezone set as'
' datetime.timezone.utc'
'datetime value does not have timezone set as datetime.UTC'
)
def utc_now() -> datetime.datetime:
"""Get offset-aware current utc time.
"""Get timezone-aware current utc time.
This should be used for all datetimes getting sent over the network,
used with the entity system, etc.
(datetime.utcnow() gives a utc time value, but it is not timezone-aware
which makes it less safe to use)
Just a shortcut for datetime.datetime.now(datetime.UTC).
Avoid datetime.datetime.utcnow() which is deprecated and gives naive
times.
"""
return datetime.datetime.now(datetime.timezone.utc)
return datetime.datetime.now(datetime.UTC)
def utc_now_naive() -> datetime.datetime:
"""Get naive utc time.
This can be used to replace datetime.utcnow(), which is now deprecated.
Most all code should migrate to use timezone-aware times instead of
this.
"""
return datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
def utc_today() -> datetime.datetime:
"""Get offset-aware midnight in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc)
now = datetime.datetime.now(datetime.UTC)
return datetime.datetime(
year=now.year, month=now.month, day=now.day, tzinfo=now.tzinfo
)
@ -142,7 +138,7 @@ def utc_today() -> datetime.datetime:
def utc_this_hour() -> datetime.datetime:
"""Get offset-aware beginning of the current hour in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc)
now = datetime.datetime.now(datetime.UTC)
return datetime.datetime(
year=now.year,
month=now.month,
@ -154,7 +150,7 @@ def utc_this_hour() -> datetime.datetime:
def utc_this_minute() -> datetime.datetime:
"""Get offset-aware beginning of current minute in the utc time zone."""
now = datetime.datetime.now(datetime.timezone.utc)
now = datetime.datetime.now(datetime.UTC)
return datetime.datetime(
year=now.year,
month=now.month,

View File

@ -34,41 +34,31 @@ def format_cpp_str(
Note that some cpp formatting keys off the filename, so a fake one can
be optionally provided.
"""
# Note: previously was explicitly passing the config path from
# toolconfigsrc so we didn't require running from the project root
# dir, but this doesn't work on older clang-format versions. So now
# just parsing and passing the values itself which should do the
# same thing. Once most people have newer clang-format we can go
# back to just passing the path.
use_built_config = True
cfconfig = os.path.join(projroot, '.clang-format')
if not os.path.isfile(cfconfig):
raise CleanError(
f".clang-format file not found in '{projroot}';"
" do 'make prereqs' to generate it."
" do 'make env' to generate it."
)
with tempfile.TemporaryDirectory() as tempdir:
filename = os.path.join(tempdir, filename)
with open(filename, 'w', encoding='utf-8') as outfile:
tfilename = os.path.join(tempdir, filename)
with open(tfilename, 'w', encoding='utf-8') as outfile:
outfile.write(text)
if use_built_config:
import yaml
import json
# clang-format uses yaml but seems passing our raw yaml
# config contents doesn't work; converting to json seems to
# work though.
with open(cfconfig, encoding='utf-8') as infile:
cfconfigdata = json.dumps(yaml.safe_load(infile.read()))
style_arg = f'--style={cfconfigdata}'
else:
style_arg = f'--style=file:{cfconfig}'
subprocess.run(['clang-format', style_arg, '-i', filename], check=True)
with open(filename, encoding='utf-8') as infile:
# Note: clang-format allows '--style=file:<path>' in version 14
# or newer, but older versions are still common, so the easiest
# way to work everywhere is to just copy our config file into
# the temp dir.
with open(cfconfig, 'rb') as infileb:
with open(os.path.join(tempdir, '.clang-format'), 'wb') as outfileb:
outfileb.write(infileb.read())
subprocess.run(
['clang-format', '--style=file', '-i', tfilename], check=True
)
with open(tfilename, encoding='utf-8') as infile:
return infile.read()
@ -91,7 +81,7 @@ def format_project_cpp_files(projroot: Path, full: bool) -> None:
if not os.path.isfile(cfconfig):
raise CleanError(
f".clang-format file not found in '{os.getcwd()}';"
" do 'make prereqs' to generate it."
" do 'make env' to generate it."
)
# Exclude generated files or else we could mess up dependencies
@ -105,8 +95,6 @@ def format_project_cpp_files(projroot: Path, full: bool) -> None:
def format_file(filename: str) -> dict[str, Any]:
start_time = time.monotonic()
# Note: seems os.system does not unlock the gil;
# make sure to use subprocess.
result = subprocess.call(['clang-format', '-i', filename])
if result != 0:
raise RuntimeError(f'Formatting failed for {filename}')

View File

@ -47,7 +47,7 @@ if __name__ == '__main__':
f'# {legalnotice}\n'
f'# This file is autogenerated; do not edit.\n'
f'#\n'
f'"""Simple wrapper so {toolname} uses our internal virtual'
f'"""Simple wrapper so {toolname} uses the project virtual'
f' environment."""\n'
f'from {toolmodule} import run_{toolname}_main\n'
f'\n'

View File

@ -78,7 +78,8 @@ def pcommand_main(globs: dict[str, Any]) -> None:
):
raise RuntimeError(
'Unexpected Python environment;'
' we expect to be running using .venv/bin/pythonX.Y'
f' we expect to be running under something like'
f" .venv/bin/pythonX.Y; found '{abs_exe_path}'."
)
cur_paths_str = os.environ.get('PATH')

View File

@ -74,7 +74,7 @@ def requirements_upgrade() -> None:
subprocess.run([sys.executable, '-m', 'pur', '-r', fname], check=True)
# Sort lines.
with open(reqpath, encoding='utf-8') as infile:
with open(fname, encoding='utf-8') as infile:
reqs2 = infile.read().strip()
reqs_new = (
'\n'.join(sorted(reqs2.splitlines(), key=lambda l: l.lower()))

View File

@ -271,8 +271,7 @@ def build_apple(arch: str, debug: bool = False) -> None:
'\t# Apply target Python patches\n'
f'\tcd $$(PYTHON_SRCDIR-$({tword})) && '
'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n'
f'\t/opt/homebrew/opt/python@3.12/bin/python3.12'
' ../../tools/pcommand python_apple_patch'
f'\t../../tools/pcommand python_apple_patch'
f' $$(PYTHON_SRCDIR-$({tword}))\n'
),
count=1,
@ -1291,22 +1290,6 @@ def gather(do_android: bool, do_apple: bool) -> None:
],
libs=_apple_libs('tvos_simulator'),
),
BuildDef(
name='android_arm',
group=groups['android'],
config_headers={
CompileArch.ANDROID_ARM: bases['android_arm']
+ f'/usr/include/{alibname}/pyconfig.h'
},
sys_config_scripts=[
bases['android_arm']
+ f'/usr/lib/python{PY_VER_ANDROID}/'
# f'_sysconfigdata_{debug_d}_linux_arm-linux-androideabi.py'
f'_sysconfigdata_{debug_d}_linux_.py'
],
libs=_android_libs('android_arm'),
libinst='android_armeabi-v7a',
),
BuildDef(
name='android_arm64',
group=groups['android'],
@ -1324,20 +1307,20 @@ def gather(do_android: bool, do_apple: bool) -> None:
libinst='android_arm64-v8a',
),
BuildDef(
name='android_x86',
name='android_arm',
group=groups['android'],
config_headers={
CompileArch.ANDROID_X86: bases['android_x86']
CompileArch.ANDROID_ARM: bases['android_arm']
+ f'/usr/include/{alibname}/pyconfig.h'
},
sys_config_scripts=[
bases['android_x86'] + f'/usr/lib/python{PY_VER_ANDROID}/'
f'_sysconfigdata_{debug_d}'
# f'_linux_i686-linux-android.py'
f'_linux_.py'
bases['android_arm']
+ f'/usr/lib/python{PY_VER_ANDROID}/'
# f'_sysconfigdata_{debug_d}_linux_arm-linux-androideabi.py'
f'_sysconfigdata_{debug_d}_linux_.py'
],
libs=_android_libs('android_x86'),
libinst='android_x86',
libs=_android_libs('android_arm'),
libinst='android_armeabi-v7a',
),
BuildDef(
name='android_x86_64',
@ -1356,6 +1339,22 @@ def gather(do_android: bool, do_apple: bool) -> None:
libs=_android_libs('android_x86_64'),
libinst='android_x86_64',
),
BuildDef(
name='android_x86',
group=groups['android'],
config_headers={
CompileArch.ANDROID_X86: bases['android_x86']
+ f'/usr/include/{alibname}/pyconfig.h'
},
sys_config_scripts=[
bases['android_x86'] + f'/usr/lib/python{PY_VER_ANDROID}/'
f'_sysconfigdata_{debug_d}'
# f'_linux_i686-linux-android.py'
f'_linux_.py'
],
libs=_android_libs('android_x86'),
libinst='android_x86',
),
]
# if do_apple:
@ -1561,9 +1560,20 @@ def gather(do_android: bool, do_apple: bool) -> None:
scriptdst = os.path.join(
pylib_dst, os.path.basename(script)
)
# Note to self: Python 3.12 seemed to change
# something where the sys_config_scripts for
# each of the architectures has the same name
# whereas it did not before. We could patch this
# by hand to split them out again, but for now
# just going to hope it gets fixed in 3.13 (when
# Android Python becomes an officially supported
# target; yay!). Hopefully nobody is using stuff
# from sysconfig anyway. But if they are, I
# rearranged the order so x86 is the actual one
# which will hopefully make errors obvious.
if os.path.exists(scriptdst):
print(
'WARNING TEMPORARILY ALLOWING'
'WARNING: TEMPORARILY ALLOWING'
' REPEAT SYS CONFIG SCRIPTS'
)
# raise RuntimeError(

View File

@ -23,15 +23,15 @@ def install_tool_config(projroot: Path, src: Path, dst: Path) -> None:
"""Install a config."""
print(f'Creating tool config: {Clr.BLD}{dst}{Clr.RST}')
# Special case: if we've got a src .yaml and a dst .json, convert.
# Special case: if we've got a src .toml and a dst .json, convert.
# This can be handy to add annotations/etc. in the src which isn't
# possible with json.
if src.suffix == '.yaml' and dst.suffix == '.json':
import yaml
if src.suffix == '.toml' and dst.suffix == '.json':
import tomllib
import json
with src.open(encoding='utf-8') as infile:
contents = yaml.safe_load(infile.read())
contents = tomllib.loads(infile.read())
cfg = json.dumps(contents, indent=2, sort_keys=True)
# In normal cases we just push the source file straight through.

View File

@ -46,7 +46,7 @@ if __name__ == '__main__':
env['BA_SPINOFF_DST_ROOT'] = dst_proj_root
# Make sure the src project is properly bootstrapped.
subprocess.run(['make', 'prereqs'], check=True, cwd=src_proj_root)
subprocess.run(['make', 'env'], check=True, cwd=src_proj_root)
# Finally, run for realz (from src proj dir).
result = subprocess.run(cmd, check=False, env=env, cwd=src_proj_root)