added bascenev1.get_connection_to_host_info_2()

This commit is contained in:
Eric 2023-12-13 22:18:42 -08:00
parent c6f0ecf17e
commit 5cf8065c40
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
54 changed files with 542 additions and 378 deletions

100
.efrocachemap generated
View File

@ -421,18 +421,18 @@
"build/assets/ba_data/audio/zoeOw.ogg": "74befe45a8417e95b6a2233c51992a26",
"build/assets/ba_data/audio/zoePickup01.ogg": "48ab8cddfcde36a750856f3f81dd20c8",
"build/assets/ba_data/audio/zoeScream01.ogg": "2b468aedfa8741090247f04eb9e6df55",
"build/assets/ba_data/data/langdata.json": "c6f94f9c1dc833c537d16672d9018b94",
"build/assets/ba_data/data/langdata.json": "4a35cc51d1021fa7e525123bcf99043c",
"build/assets/ba_data/data/languages/arabic.json": "00ba700de6c672a56658a6bd1ad27523",
"build/assets/ba_data/data/languages/belarussian.json": "7fe38341815ca6ff4d95224196e7a67e",
"build/assets/ba_data/data/languages/chinese.json": "5761468d25f2bd4e79921826cebd572b",
"build/assets/ba_data/data/languages/chinesetraditional.json": "f858da49be0a5374157c627857751078",
"build/assets/ba_data/data/languages/croatian.json": "766532c67af5bd0144c2d63cab0516fa",
"build/assets/ba_data/data/languages/czech.json": "93c5fe0d884d95435da6c675f64e30e0",
"build/assets/ba_data/data/languages/czech.json": "cd21ad8c6b8e9ed700284cf1e1aecbf8",
"build/assets/ba_data/data/languages/danish.json": "3fd69080783d5c9dcc0af737f02b6f1e",
"build/assets/ba_data/data/languages/dutch.json": "22b44a33bf81142ba2befad14eb5746e",
"build/assets/ba_data/data/languages/english.json": "bd43b77b1ccca059573acbde148b4767",
"build/assets/ba_data/data/languages/esperanto.json": "0e397cfa5f3fb8cef5f4a64f21cda880",
"build/assets/ba_data/data/languages/filipino.json": "afbda3adf14555e1567ee63c32e340e7",
"build/assets/ba_data/data/languages/filipino.json": "0f5ad7c06db70027b116dfd9324bdf67",
"build/assets/ba_data/data/languages/french.json": "49ff6d211537b8003b8241438dca661d",
"build/assets/ba_data/data/languages/german.json": "450fa41ae264f29a5d1af22143d0d0ad",
"build/assets/ba_data/data/languages/gibberish.json": "9aae526303a22372fe9b4cf1781520ef",
@ -445,12 +445,12 @@
"build/assets/ba_data/data/languages/malay.json": "832562ce997fc70704b9234c95fb2e38",
"build/assets/ba_data/data/languages/persian.json": "d742f4a6d3c3555031102b21abdcbb5b",
"build/assets/ba_data/data/languages/polish.json": "b9a58b70ed5e99d8b7fa2392b2eb0cda",
"build/assets/ba_data/data/languages/portuguese.json": "556af4e8170356ad239412e1743e20d5",
"build/assets/ba_data/data/languages/portuguese.json": "e3adc6c04486d21e84019a0b03ce11b1",
"build/assets/ba_data/data/languages/romanian.json": "aeebdd54f65939c2facc6ac50c117826",
"build/assets/ba_data/data/languages/russian.json": "e120993371f52edd2d99f2236188933c",
"build/assets/ba_data/data/languages/serbian.json": "d7452dd72ac0e51680cb39b5ebaa1c69",
"build/assets/ba_data/data/languages/slovak.json": "27962d53dc3f7dd4e877cd40faafeeef",
"build/assets/ba_data/data/languages/spanish.json": "80ea58bd3295a0252b7fdac9154aa22f",
"build/assets/ba_data/data/languages/spanish.json": "1d14210b4eefb48130608bd0495b7900",
"build/assets/ba_data/data/languages/swedish.json": "5142a96597d17d8344be96a603da64ac",
"build/assets/ba_data/data/languages/tamil.json": "b4de1a2851afe4869c82e9acd94cd89c",
"build/assets/ba_data/data/languages/thai.json": "77755219bbf5fb7eea0d6b226684f403",
@ -4060,50 +4060,50 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "8561660678904509458b80bb4b62d8ea",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "f2e7de4723ce8fb6984a5bbd9ac93aa6",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "af1ade2cc275dacc7e1793383d766f3d",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bb806faa941b6c3c7834383264cf8571",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "648bfaca6487ff13cd27a31e317878f0",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "38501876d5009ecaa936994ec6fbb3a2",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f7d354aded26684974b4d0fbb8725762",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "f6ceb8135fe4fb9aa7fc13fb1b835077",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "402cb0d5a0abecfa9e578f3801b15e59",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "4eae3e6ade00be0224839bfc16351d2c",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "c6dd9b6cf876db50aa8d0cc0cc80efa4",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "79d19536ed7de918c947c5095286b8ce",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "409140e2c39941dbc66088417399d5ea",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "1a25fd7e3c5b94a294ce769083b71751",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "7bfbb50681473702f286a50e56277b93",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "37ce7d3b865c0b58161c2d4ccdb54256",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "728dfc083916d7199dee1e75ad12e9fc",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "fbf59de05d7e121d9c5dd164939228dc",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "1eb456e1b1c4d215912809950d938c1a",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "65f507699fed78fcfa12e3e63af2bf8b",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "4f5d3cafbea651078c1721684b61033a",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "7436c575aee1f9d112d41f18e2ae6b22",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "4f5d3cafbea651078c1721684b61033a",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "7436c575aee1f9d112d41f18e2ae6b22",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "3ffcb35eb71566fefb7d9ad2589b37b4",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "ce9de33efccb9aa1e301fe4f11e6b1c1",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "3ffcb35eb71566fefb7d9ad2589b37b4",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "ce9de33efccb9aa1e301fe4f11e6b1c1",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "9d674b5e8a8357b9462a65359611ea45",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "e6d1c0b9bf27c34968e512c5db8e7de5",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "9d674b5e8a8357b9462a65359611ea45",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "e6d1c0b9bf27c34968e512c5db8e7de5",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "910b5e39fe4ba5bb849505c578efe3ec",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "2d9e14f7cfe50b1dc51e5e9eae05b5fd",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "b83a67eeaed0fc99bf995767a8150e5d",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "2d9e14f7cfe50b1dc51e5e9eae05b5fd",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "f6a855e83d7816e73d9859ff9e508190",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "6cd203dce2718e0eded672c83c51506a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "a1f81d6527bba562c3626e520ab8aa2d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "8b6a8b19f73b67413612185aa2d9ca5d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "2534af31cf9f8a86ddb7c92b0184f4b2",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "0cf7fb12f97a3f8176462ec5d1ddb992",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "4afbbfa78e25e932d9392a1bd6bacc52",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "a0ba1ed33b7a83543b51f24a96941dfa",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6135aeb242afaf9d1114810a67c89cec",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "bbbbb14d42ed6eb0c5eb56867b7fb870",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "cd28f9cc4652736a31c677fc4e5dbaf1",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "239c608cc52c0320210e56ad6abe57a5",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "e76d67cacf1393d33796d6b6b1bf1413",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "a7eaa8dc4d859ef7a735483b04ccec4a",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "7a2eef42da34a35ddcc2fd7c66843b1b",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "694599ac6a967b2ed383b27bf8093e5b",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "c91cbab6a07affa22e0612210f8b807c",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "d460f7a3909f92d5dbf752e4521a9fbc",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "0a0abfe75bc987e7b65a3cfa106e8353",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "8f21405b29f2b2ab01323d711492cca0",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "96dc73e819f41f99a1b2dbb45f79d551",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "c79ac51cd2deabb1c2d0acddeaf81c30",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "f06ec14e8c3106be9df91af7da621dc9",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "f389f9a7b1afc81f76787722340cfa9c",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "c7dab78aac11cb1430d8456d5d48107a",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "67e29852dfee2e63e179cfebf608ef26",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "9778f8faf91c9993fbf3015bd4554a87",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "73477bd15b9e3834314fd878c9e108d4",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "fb9b8443c1b4cccad749df7d6328220f",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "384fb7fd55ad5a6cdbb662da1ec402ab",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "fb9b8443c1b4cccad749df7d6328220f",
"build/prefab/lib/linux_arm64_server/release/libballisticaplus.a": "384fb7fd55ad5a6cdbb662da1ec402ab",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticaplus.a": "bc7d0811bcd87156ebf5292a38a1c350",
"build/prefab/lib/linux_x86_64_gui/release/libballisticaplus.a": "bb32f45054b6999300bf8b41d6a4b402",
"build/prefab/lib/linux_x86_64_server/debug/libballisticaplus.a": "bc7d0811bcd87156ebf5292a38a1c350",
"build/prefab/lib/linux_x86_64_server/release/libballisticaplus.a": "bb32f45054b6999300bf8b41d6a4b402",
"build/prefab/lib/mac_arm64_gui/debug/libballisticaplus.a": "8d9a1505bf397f4902baabed7c1cf438",
"build/prefab/lib/mac_arm64_gui/release/libballisticaplus.a": "f4d9c115e22dd81e36d1c5baeac8d848",
"build/prefab/lib/mac_arm64_server/debug/libballisticaplus.a": "8d9a1505bf397f4902baabed7c1cf438",
"build/prefab/lib/mac_arm64_server/release/libballisticaplus.a": "f4d9c115e22dd81e36d1c5baeac8d848",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticaplus.a": "fb72c92ec6ec0e1c8f4ced32abd86505",
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "131aab20cfe77fe89c3f452a855f1e68",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "ee10cdc9f9a861e2be0f1a208c0ca0fe",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "131aab20cfe77fe89c3f452a855f1e68",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "678fabc6dfd6f401ee8942d088ee9181",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "e092d2aed8464a61a623d79ca25308d8",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6b658f49be396ad645c5e57464739a3b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "9d79a56403a6d806ff131a7de664dfa7",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "e831a26d2c28e862d51e24393d158c99",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "46fe1c89bcc75c781729ec9e5491c610",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "9c6278d7df3ce4db2ffe7794a0fd35b7",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "110c35a17b462864075800756b5e541a",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",
@ -4112,7 +4112,7 @@
"src/ballistica/core/mgen/pyembed/binding_core.inc": "9d0a3c9636138e35284923e0c8311c69",
"src/ballistica/core/mgen/pyembed/env.inc": "8be46e5818f360d10b7b0224a9e91d07",
"src/ballistica/core/mgen/python_modules_monolithic.h": "fb967ed1c7db0c77d8deb4f00a7103c5",
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "d80f970053099b3044204bfe29ddefce",
"src/ballistica/scene_v1/mgen/pyembed/binding_scene_v1.inc": "c25b263f2a31fb5ebe057db07d144879",
"src/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc": "44a45492db057bf7f7158c3b0fa11f0f",
"src/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc": "f5f054050d2b2fcd3763a4833fb32269"
}

View File

@ -21,7 +21,6 @@
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-android" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-cmake" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-ios.xcodeproj" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-mac.xcodeproj" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-windows-oculus" />
<excludeFolder url="file://$MODULE_DIR$/ballisticakit-xcode" />

View File

@ -1,5 +1,7 @@
### 1.7.31 (build 21700, api 8, 2023-12-09)
### 1.7.31 (build 21707, api 8, 2023-12-13)
- added `bascenev1.get_connection_to_host_info_2()` which is an improved
type-safe version of `bascenev1.get_connection_to_host_info()`.
### 1.7.30 (build 21697, api 8, 2023-12-08)
- Continued work on the big 1.7.28 update.
- Got the Android version back up and running. There's been lots of cleanup and

View File

@ -14,7 +14,6 @@
<file path="$PROJECT_DIR$/../ballisticakit-android" />
<file path="$PROJECT_DIR$/.idea" />
<file path="$PROJECT_DIR$/../ballisticakit-ios.xcodeproj" />
<file path="$PROJECT_DIR$/../ballisticakit-mac.xcodeproj" />
<file path="$PROJECT_DIR$/../ballisticakit-windows" />
<file path="$PROJECT_DIR$/../ballisticakit-xcode" />
<file path="$PROJECT_DIR$/../build" />

View File

@ -152,7 +152,6 @@ ctx.filter_dirs = {
'ballisticakit-cmake',
'ballisticakit-xcode/BallisticaKit.xcodeproj',
'ballisticakit-ios.xcodeproj',
'ballisticakit-mac.xcodeproj',
'config',
'src/assets/pdoc',
}

View File

@ -20,7 +20,6 @@
"ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_keyboard.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc",
@ -50,7 +49,6 @@
"ba_data/python/babase/_error.py",
"ba_data/python/babase/_general.py",
"ba_data/python/babase/_hooks.py",
"ba_data/python/babase/_keyboard.py",
"ba_data/python/babase/_language.py",
"ba_data/python/babase/_login.py",
"ba_data/python/babase/_math.py",
@ -152,6 +150,7 @@
"ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_net.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc",
"ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc",
@ -186,6 +185,7 @@
"ba_data/python/bascenev1/_messages.py",
"ba_data/python/bascenev1/_multiteamsession.py",
"ba_data/python/bascenev1/_music.py",
"ba_data/python/bascenev1/_net.py",
"ba_data/python/bascenev1/_nodeactor.py",
"ba_data/python/bascenev1/_player.py",
"ba_data/python/bascenev1/_playlist.py",
@ -352,10 +352,12 @@
"ba_data/python/bauiv1/__init__.py",
"ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/__pycache__/_keyboard.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc",
"ba_data/python/bauiv1/_hooks.py",
"ba_data/python/bauiv1/_keyboard.py",
"ba_data/python/bauiv1/_subsystem.py",
"ba_data/python/bauiv1/_uitypes.py",
"ba_data/python/bauiv1/onscreenkeyboard.py",

View File

@ -178,7 +178,6 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/_error.py \
$(BUILD_DIR)/ba_data/python/babase/_general.py \
$(BUILD_DIR)/ba_data/python/babase/_hooks.py \
$(BUILD_DIR)/ba_data/python/babase/_keyboard.py \
$(BUILD_DIR)/ba_data/python/babase/_language.py \
$(BUILD_DIR)/ba_data/python/babase/_login.py \
$(BUILD_DIR)/ba_data/python/babase/_math.py \
@ -237,6 +236,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/bascenev1/_messages.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_multiteamsession.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_music.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_net.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_nodeactor.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_player.py \
$(BUILD_DIR)/ba_data/python/bascenev1/_playlist.py \
@ -326,6 +326,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/batemplatefs/_subsystem.py \
$(BUILD_DIR)/ba_data/python/bauiv1/__init__.py \
$(BUILD_DIR)/ba_data/python/bauiv1/_hooks.py \
$(BUILD_DIR)/ba_data/python/bauiv1/_keyboard.py \
$(BUILD_DIR)/ba_data/python/bauiv1/_subsystem.py \
$(BUILD_DIR)/ba_data/python/bauiv1/_uitypes.py \
$(BUILD_DIR)/ba_data/python/bauiv1/onscreenkeyboard.py \
@ -452,7 +453,6 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_keyboard.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_language.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_login.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_math.cpython-311.opt-1.pyc \
@ -511,6 +511,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_messages.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_multiteamsession.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_music.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_net.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_nodeactor.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_player.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bascenev1/__pycache__/_playlist.cpython-311.opt-1.pyc \
@ -600,6 +601,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(BUILD_DIR)/ba_data/python/batemplatefs/__pycache__/_subsystem.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/__init__.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_hooks.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_keyboard.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_subsystem.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/_uitypes.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/bauiv1/__pycache__/onscreenkeyboard.cpython-311.opt-1.pyc \

View File

@ -154,7 +154,6 @@ from babase._general import (
getclass,
get_type_name,
)
from babase._keyboard import Keyboard
from babase._language import Lstr, LanguageSubsystem
from babase._login import LoginAdapter, LoginInfo
@ -261,7 +260,6 @@ __all__ = [
'is_point_in_box',
'is_running_on_fire_tv',
'is_xcode_build',
'Keyboard',
'LanguageSubsystem',
'lock_all_input',
'LoginAdapter',

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
from babase._login import LoginAdapter, LoginInfo
DEBUG_LOG = _babase.temp_testing()
DEBUG_LOG = False
class AccountV2Subsystem:

View File

@ -31,6 +31,7 @@ class AppMode:
AppExperience associated with the AppMode must be supported by
the current app and runtime environment.
"""
# FIXME: check AppExperience.
return cls._supports_intent(intent)
@classmethod

View File

@ -325,7 +325,7 @@ def dump_app_state(
)
def log_dumped_app_state() -> None:
def log_dumped_app_state(from_previous_run: bool = False) -> None:
"""If an app-state dump exists, log it and clear it. No-op otherwise."""
try:
@ -352,8 +352,13 @@ def log_dumped_app_state() -> None:
metadata = dataclass_from_json(DumpedAppStateMetadata, appstatedata)
header = (
'Found app state dump from previous app run'
if from_previous_run
else 'App state dump'
)
out += (
f'App state dump:\nReason: {metadata.reason}\n'
f'{header}:\nReason: {metadata.reason}\n'
f'Time: {metadata.app_time:.2f}'
)
tbpath = os.path.join(
@ -383,7 +388,7 @@ class AppHealthMonitor(AppSubsystem):
def on_app_loading(self) -> None:
# If any traceback dumps happened last run, log and clear them.
log_dumped_app_state()
log_dumped_app_state(from_previous_run=True)
def _app_monitor_thread_main(self) -> None:
_babase.set_thread_name('ballistica app-monitor')

View File

@ -17,7 +17,7 @@ if TYPE_CHECKING:
from typing import Callable
DEBUG_LOG = _babase.temp_testing()
DEBUG_LOG = False
@dataclass

View File

@ -24,6 +24,8 @@ if TYPE_CHECKING:
# instead of these or to make the meta system aware of arbitrary classes.
EXPORT_CLASS_NAME_SHORTCUTS: dict[str, str] = {
'plugin': 'babase.Plugin',
# DEPRECATED as of 12/2023. Currently am warning if finding these
# but should take this out eventually.
'keyboard': 'babase.Keyboard',
}
@ -414,30 +416,27 @@ class DirectoryScan:
if export_class_name is not None:
classname = modulename + '.' + export_class_name
# Since we'll soon have multiple versions of 'game'
# classes we need to migrate people to using base
# class names for them.
if exporttypestr == 'game':
# Migrating away from the 'keyboard' name shortcut
# since it's specific to bauiv1; warn if we find it.
if exporttypestr == 'keyboard':
logging.warning(
"metascan: %s:%d: '# ba_meta export"
" game' tag should be replaced by '# ba_meta"
" export bascenev1.GameActivity'.",
" keyboard' tag should be replaced by '# ba_meta"
" export bauiv1.Keyboard'.",
subpath,
lindex + 1,
)
self.results.announce_errors_occurred = True
else:
# If export type is one of our shortcuts, sub in the
# actual class path. Otherwise assume its a classpath
# itself.
exporttype = EXPORT_CLASS_NAME_SHORTCUTS.get(
exporttypestr
)
if exporttype is None:
exporttype = exporttypestr
self.results.exports.setdefault(exporttype, []).append(
classname
)
# If export type is one of our shortcuts, sub in the
# actual class path. Otherwise assume its a classpath
# itself.
exporttype = EXPORT_CLASS_NAME_SHORTCUTS.get(exporttypestr)
if exporttype is None:
exporttype = exporttypestr
self.results.exports.setdefault(exporttype, []).append(
classname
)
def _get_export_class_name(
self, subpath: Path, lines: list[str], lindex: int

View File

@ -97,7 +97,7 @@ class AdsSubsystem:
show = True
# No ads without net-connections, etc.
if not bauiv1.can_show_ad():
if not plus.can_show_ad():
show = False
if classic.accounts.have_pro():
show = False # Pro disables interstitials.
@ -135,7 +135,7 @@ class AdsSubsystem:
# ad-show-threshold and see if we should *actually* show
# (we reach our threshold faster the longer we've been
# playing).
base = 'ads' if bauiv1.has_video_ads() else 'ads2'
base = 'ads' if plus.has_video_ads() else 'ads2'
min_lc = plus.get_v1_account_misc_read_val(base + '.minLC', 0.0)
max_lc = plus.get_v1_account_misc_read_val(base + '.maxLC', 5.0)
min_lc_scale = plus.get_v1_account_misc_read_val(

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21700
TARGET_BALLISTICA_BUILD = 21707
TARGET_BALLISTICA_VERSION = '1.7.31'

View File

@ -249,3 +249,18 @@ class PlusSubsystem(AppSubsystem):
) -> None:
"""(internal)"""
return _baplus.tournament_query(callback, args)
@staticmethod
def have_incentivized_ad() -> bool:
"""Is an incentivized ad available?"""
return _baplus.have_incentivized_ad()
@staticmethod
def has_video_ads() -> bool:
"""Are video ads available?"""
return _baplus.has_video_ads()
@staticmethod
def can_show_ad() -> bool:
"""Can we show an ad?"""
return _baplus.can_show_ad()

View File

@ -78,6 +78,7 @@ from _bascenev1 import (
end_host_scanning,
get_chat_messages,
get_connection_to_host_info,
get_connection_to_host_info_2,
get_foreground_host_activity,
get_foreground_host_session,
get_game_port,
@ -202,6 +203,7 @@ from bascenev1._multiteamsession import (
DEFAULT_TEAM_NAMES,
)
from bascenev1._music import MusicType, setmusic
from bascenev1._net import HostInfo
from bascenev1._nodeactor import NodeActor
from bascenev1._powerup import get_default_powerup_distribution
from bascenev1._profile import (
@ -303,6 +305,7 @@ __all__ = [
'GameTip',
'get_chat_messages',
'get_connection_to_host_info',
'get_connection_to_host_info_2',
'get_default_free_for_all_playlist',
'get_default_teams_playlist',
'get_default_powerup_distribution',
@ -338,6 +341,7 @@ __all__ = [
'have_connected_clients',
'have_touchscreen_input',
'HitMessage',
'HostInfo',
'host_scan_cycle',
'ImpactDamageMessage',
'increment_analytics_count',

View File

@ -0,0 +1,24 @@
# Released under the MIT License. See LICENSE for details.
#
"""Functionality related to net play."""
from __future__ import annotations
from typing import TYPE_CHECKING
from dataclasses import dataclass
if TYPE_CHECKING:
pass
@dataclass
class HostInfo:
"""Info about a host."""
name: str
build_number: int
# Note this can be None for non-ip hosts such as bluetooth.
address: str | None
# Note this can be None for non-ip hosts such as bluetooth.
port: int | None

View File

@ -62,7 +62,6 @@ from babase import (
is_browser_likely_available,
is_running_on_fire_tv,
is_xcode_build,
Keyboard,
lock_all_input,
LoginAdapter,
LoginInfo,
@ -94,7 +93,6 @@ from babase import (
from _bauiv1 import (
buttonwidget,
can_show_ad,
checkboxwidget,
columnwidget,
containerwidget,
@ -103,8 +101,6 @@ from _bauiv1 import (
getmesh,
getsound,
gettexture,
has_video_ads,
have_incentivized_ad,
hscrollwidget,
imagewidget,
is_party_icon_visible,
@ -125,6 +121,7 @@ from _bauiv1 import (
Widget,
widget,
)
from bauiv1._keyboard import Keyboard
from bauiv1._uitypes import Window, uicleanupcheck
from bauiv1._subsystem import UIV1Subsystem
@ -144,7 +141,6 @@ __all__ = [
'AppTimer',
'buttonwidget',
'Call',
'can_show_ad',
'fullscreen_control_available',
'fullscreen_control_get',
'fullscreen_control_key_shortcut',
@ -178,8 +174,6 @@ __all__ = [
'getmesh',
'getsound',
'gettexture',
'has_video_ads',
'have_incentivized_ad',
'have_permission',
'hscrollwidget',
'imagewidget',

View File

@ -12,6 +12,7 @@ from typing import TYPE_CHECKING
import babase
import _bauiv1
from bauiv1._keyboard import Keyboard
from bauiv1._uitypes import Window
if TYPE_CHECKING:
@ -252,9 +253,7 @@ class OnScreenKeyboardWindow(Window):
# Show change instructions only if we have more than one
# keyboard option.
keyboards = (
babase.app.meta.scanresults.exports_of_class(
babase.Keyboard
)
babase.app.meta.scanresults.exports_of_class(Keyboard)
if babase.app.meta.scanresults is not None
else []
)
@ -286,10 +285,10 @@ class OnScreenKeyboardWindow(Window):
def _get_keyboard(self) -> bui.Keyboard:
assert babase.app.meta.scanresults is not None
classname = babase.app.meta.scanresults.exports_of_class(
babase.Keyboard
)[self._keyboard_index]
kbclass = babase.getclass(classname, babase.Keyboard)
classname = babase.app.meta.scanresults.exports_of_class(Keyboard)[
self._keyboard_index
]
kbclass = babase.getclass(classname, Keyboard)
return kbclass()
def _refresh(self) -> None:
@ -384,9 +383,7 @@ class OnScreenKeyboardWindow(Window):
def _next_keyboard(self) -> None:
assert babase.app.meta.scanresults is not None
kbexports = babase.app.meta.scanresults.exports_of_class(
babase.Keyboard
)
kbexports = babase.app.meta.scanresults.exports_of_class(Keyboard)
self._keyboard_index = (self._keyboard_index + 1) % len(kbexports)
self._load_keyboard()

View File

@ -415,7 +415,7 @@ class CoopBrowserWindow(bui.Window):
)
# Decrement time on our tournament buttons.
ads_enabled = bui.have_incentivized_ad()
ads_enabled = plus.have_incentivized_ad()
for tbtn in self._tournament_buttons:
tbtn.time_remaining = max(0, tbtn.time_remaining - 1)
if tbtn.time_remaining_value_text is not None:
@ -430,7 +430,7 @@ class CoopBrowserWindow(bui.Window):
)
# Also adjust the ad icon visibility.
if tbtn.allow_ads and bui.has_video_ads():
if tbtn.allow_ads and plus.has_video_ads():
bui.imagewidget(
edit=tbtn.entry_fee_ad_image,
opacity=1.0 if ads_enabled else 0.25,

View File

@ -638,8 +638,8 @@ class TournamentButton:
# Now, if this fee allows ads and we support video ads, show
# the 'or ad' version.
if allow_ads and bui.has_video_ads():
ads_enabled = bui.have_incentivized_ad()
if allow_ads and plus.has_video_ads():
ads_enabled = plus.have_incentivized_ad()
bui.imagewidget(
edit=self.entry_fee_ad_image,
opacity=1.0 if ads_enabled else 0.25,

View File

@ -334,7 +334,7 @@ class GetCurrencyWindow(bui.Window):
tex_scale=1.2,
) # 19.99-ish
self._enable_ad_button = bui.has_video_ads()
self._enable_ad_button = plus.has_video_ads()
h = self._width * 0.5 + 110.0
v = self._height - b_size[1] - 115.0
@ -561,7 +561,7 @@ class GetCurrencyWindow(bui.Window):
next_reward_ad_time
)
now = datetime.datetime.utcnow()
if bui.have_incentivized_ad() and (
if plus.have_incentivized_ad() and (
next_reward_ad_time is None or next_reward_ad_time <= now
):
self._ad_button_greyed = False

View File

@ -9,7 +9,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
import babase
import bauiv1 as bui
if TYPE_CHECKING:
from typing import Iterable
@ -33,15 +33,15 @@ def split(chars: Iterable[str], maxlen: int) -> list[list[str]]:
def generate_emojis(maxlen: int) -> list[list[str]]:
"""Generates a lot of UTF8 emojis prepared for babase.Keyboard pages"""
"""Generates a lot of UTF8 emojis prepared for bui.Keyboard pages"""
all_emojis = split([chr(i) for i in range(0x1F601, 0x1F650)], maxlen)
all_emojis += split([chr(i) for i in range(0x2702, 0x27B1)], maxlen)
all_emojis += split([chr(i) for i in range(0x1F680, 0x1F6C1)], maxlen)
return all_emojis
# ba_meta export keyboard
class EnglishKeyboard(babase.Keyboard):
# ba_meta export bauiv1.Keyboard
class EnglishKeyboard(bui.Keyboard):
"""Default English keyboard."""
name = 'English'

View File

@ -92,9 +92,10 @@ class PartyWindow(bui.Window):
iconscale=1.2,
)
info = bs.get_connection_to_host_info()
if info.get('name', '') != '':
title = bui.Lstr(value=info['name'])
info = bs.get_connection_to_host_info_2()
if info is not None and info.name != '':
title = bui.Lstr(value=info.name)
else:
title = bui.Lstr(resource=self._r + '.titleText')
@ -481,7 +482,8 @@ class PartyWindow(bui.Window):
kick_str = bui.Lstr(resource='kickText')
else:
# kick-votes appeared in build 14248
if bs.get_connection_to_host_info().get('build_number', 0) < 14248:
info = bs.get_connection_to_host_info_2()
if info is None or info.build_number < 14248:
return
kick_str = bui.Lstr(resource='kickVoteText')
assert bui.app.classic is not None

View File

@ -34,6 +34,7 @@ class TournamentEntryWindow(PopupWindow):
# pylint: disable=too-many-statements
assert bui.app.classic is not None
assert bui.app.plus
bui.set_analytics_screen('Tournament Entry Window')
self._tournament_id = tournament_id
@ -100,7 +101,7 @@ class TournamentEntryWindow(PopupWindow):
self._launched = False
# Show the ad button only if we support ads *and* it has a level 1 fee.
self._do_ad_btn = bui.has_video_ads() and self._allow_ads
self._do_ad_btn = bui.app.plus.has_video_ads() and self._allow_ads
x_offs = 0 if self._do_ad_btn else 85
@ -477,7 +478,7 @@ class TournamentEntryWindow(PopupWindow):
)
if self._do_ad_btn:
enabled = bui.have_incentivized_ad()
enabled = plus.have_incentivized_ad()
have_ad_tries_remaining = (
self._tournament_info['adTriesRemaining'] is not None
and self._tournament_info['adTriesRemaining'] > 0

View File

@ -195,6 +195,12 @@ void BaseFeatureSet::OnAssetsAvailable() {
}
void BaseFeatureSet::StartApp() {
// {
// // TEST - recreate the ID python dumps in its thread tracebacks.
// auto val = PyThread_get_thread_ident();
// printf("MAIN THREAD IS %#018lx\n", val);
// }
BA_PRECONDITION(g_core->InMainThread());
BA_PRECONDITION(g_base);

View File

@ -50,7 +50,7 @@ void Networking::SendTo(const std::vector<uint8_t>& buffer,
if (sd != -1) {
sendto(sd, (const char*)&buffer[0],
static_cast_check_fit<socket_send_length_t>(buffer.size()), 0,
addr.GetSockAddr(), addr.GetSockAddrLen());
addr.AsSockAddr(), addr.GetSockAddrLen());
}
}

View File

@ -58,8 +58,8 @@ auto BasePlatform::GetPublicDeviceUUID() -> std::string {
// We used to plug version in directly here, but that caused uuids to
// shuffle too rapidly during periods of rapid development. This
// keeps it more constant.
// __last_rand_uuid_component_shuffle_date__ 2023 6 15
auto rand_uuid_component{"JVRWZ82D4WMBO110OA0IFJV7JKMQV8W3"};
// __last_rand_uuid_component_shuffle_date__ 2023 12 13
auto rand_uuid_component{"7YM96RZHN6ZCPZGTQONULZO1JU5NMMC7"};
inputs.emplace_back(rand_uuid_component);
auto gil{Python::ScopedInterpreterLock()};

View File

@ -368,12 +368,64 @@ void CoreFeatureSet::StartSuicideTimer(const std::string& action,
}
}
// auto CoreFeatureSet::InMainThread() -> bool {
// return std::this_thread::get_id() == main_thread_id;
// // if (main_event_loop_) {
// // return main_event_loop_->ThreadIsCurrent();
// // }
// // return false;
// }
void CoreFeatureSet::RegisterThread(const std::string& name) {
{
std::scoped_lock lock(thread_info_map_mutex_);
// Should be registering each thread just once.
assert(thread_info_map_.find(std::this_thread::get_id())
== thread_info_map_.end());
thread_info_map_[std::this_thread::get_id()] = name;
}
// Also set the name at the OS leve when possible. Prepend 'ballistica'
// since there's generally lots of other random threads in the mix.
//
// Note that we currently don't do this for our main thread because (on
// Linux at least) that changes the process name we see in top/etc. On
// other platforms we could reconsider, but its generally clear what the
// main thread is anyway in most scenarios.
if (!InMainThread()) {
g_core->platform->SetCurrentThreadName("ballistica " + name);
}
}
void CoreFeatureSet::UnregisterThread() {
std::scoped_lock lock(thread_info_map_mutex_);
auto i = thread_info_map_.find(std::this_thread::get_id());
assert(i != thread_info_map_.end());
if (i != thread_info_map_.end()) {
thread_info_map_.erase(i);
}
}
auto CoreFeatureSet::CurrentThreadName() -> std::string {
if (g_core == nullptr) {
return "unknown(not-yet-inited)";
}
{
std::scoped_lock lock(g_core->thread_info_map_mutex_);
auto i = g_core->thread_info_map_.find(std::this_thread::get_id());
if (i != g_core->thread_info_map_.end()) {
return i->second;
}
}
// Ask pthread for the thread name if we don't have one.
// FIXME - move this to platform.
#if BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS || BA_OSTYPE_LINUX
std::string name = "unknown (sys-name=";
char buffer[256];
int result = pthread_getname_np(pthread_self(), buffer, sizeof(buffer));
if (result == 0) {
name += std::string("\"") + buffer + "\")";
} else {
name += "<error " + std::to_string(result) + ">";
}
return name;
#else
return "unknown";
#endif
}
} // namespace ballistica::core

View File

@ -144,6 +144,12 @@ class CoreFeatureSet {
return using_custom_app_python_dir_;
}
/// Register various info about the current thread.
void RegisterThread(const std::string& name);
/// Should be called by a thread before it exits.
void UnregisterThread();
// Subsystems.
CorePython* const python;
CorePlatform* const platform;
@ -158,8 +164,6 @@ class CoreFeatureSet {
bool v1_cloud_log_full{};
int master_server_source{};
std::vector<EventLoop*> suspendable_event_loops;
std::mutex thread_name_map_mutex;
std::unordered_map<std::thread::id, std::string> thread_name_map;
std::mutex v1_cloud_log_mutex;
std::string v1_cloud_log;
@ -173,6 +177,7 @@ class CoreFeatureSet {
auto vr_mode() const { return vr_mode_; }
auto event_loops_suspended() const { return event_loops_suspended_; }
void set_event_loops_suspended(bool val) { event_loops_suspended_ = val; }
static auto CurrentThreadName() -> std::string;
private:
explicit CoreFeatureSet(CoreConfig config);
@ -204,6 +209,8 @@ class CoreFeatureSet {
std::optional<std::string> ba_env_user_python_dir_;
std::optional<std::string> ba_env_site_python_dir_;
std::string ba_env_data_dir_;
std::mutex thread_info_map_mutex_;
std::unordered_map<std::thread::id, std::string> thread_info_map_;
};
} // namespace ballistica::core

View File

@ -466,7 +466,7 @@ auto CorePlatformApple::CanShowBlockingFatalErrorDialog() -> bool {
if (g_buildconfig.xcode_build() && g_buildconfig.ostype_macos()) {
return true;
}
return false;
return CorePlatform::CanShowBlockingFatalErrorDialog();
}
void CorePlatformApple::BlockingFatalErrorDialog(const std::string& message) {

View File

@ -826,11 +826,9 @@ auto CorePlatform::MacMusicAppGetPlaylists() -> std::list<std::string> {
}
void CorePlatform::SetCurrentThreadName(const std::string& name) {
// Currently we leave the main thread alone, otherwise we show up as
// "BallisticaMainThread" under "top" on linux (should check other platforms).
if (g_core->InMainThread()) {
return;
}
// We should never be doing this for the main thread.
BA_PRECONDITION_FATAL(!g_core->InMainThread());
#if BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS
pthread_setname_np(name.c_str());
#elif BA_OSTYPE_LINUX || BA_OSTYPE_ANDROID

View File

@ -18,7 +18,7 @@ auto ConnectionToHostUDP::SwitchProtocol() -> bool {
// Need a new request id so we ignore further responses to our previous
// requests.
GetRequestID();
GetRequestID_();
return true;
}
return false;
@ -32,7 +32,7 @@ ConnectionToHostUDP::ConnectionToHostUDP(const SockAddr& addr)
did_die_(false),
last_host_response_time_millisecs_(
static_cast<millisecs_t>(g_base->logic->display_time() * 1000.0)) {
GetRequestID();
GetRequestID_();
if (auto* appmode = SceneV1AppMode::GetActiveOrWarn()) {
if (appmode->connections()->GetPrintUDPConnectProgress()) {
ScreenMessage(g_base->assets->GetResourceString("connectingToPartyText"));
@ -46,11 +46,11 @@ ConnectionToHostUDP::~ConnectionToHostUDP() {
set_connection_dying(true);
}
void ConnectionToHostUDP::GetRequestID() {
void ConnectionToHostUDP::GetRequestID_() {
// We store a unique-ish request ID to minimize the chance that data for
// previous connections/etc will muck with us.
// Try to start this value at something that won't be common in packets to
// minimize chance of garbage packets causing trouble.
// previous connections/etc will muck with us. Try to start this value at
// something that won't be common in packets to minimize chance of garbage
// packets causing trouble.
static auto next_request_id =
static_cast<uint8_t>(71 + (rand() % 151)); // NOLINT
request_id_ = next_request_id++;
@ -95,13 +95,14 @@ void ConnectionToHostUDP::Update() {
{1, 0, 0});
}
// Die immediately in this case; no use trying to wait for a disconnect-ack
// since we've already given up hope of hearing from them.
// Die immediately in this case; no use trying to wait for a
// disconnect-ack since we've already given up hope of hearing from
// them.
Die();
return;
} else if (errored()) {
// If we've errored, keep sending disconnect-requests periodically.
// Once we get a response (or time out in the above code) we'll die.
// If we've errored, keep sending disconnect-requests periodically. Once
// we get a response (or time out in the above code) we'll die.
if (current_time_millisecs - last_disconnect_request_time_ > 1000) {
last_disconnect_request_time_ = current_time_millisecs;
@ -189,8 +190,8 @@ void ConnectionToHostUDP::Error(const std::string& msg) {
auto ConnectionToHostUDP::GetAsUDP() -> ConnectionToHostUDP* { return this; }
void ConnectionToHostUDP::RequestDisconnect() {
// Mark us as errored so all future communication results in more disconnect
// requests.
// Mark us as errored so all future communication results in more
// disconnect requests.
set_errored(true);
if (client_id_ != -1) {
SendDisconnectRequest();

View File

@ -23,8 +23,8 @@ class ConnectionToHostUDP : public ConnectionToHost {
void set_client_id(int val) { client_id_ = val; }
auto client_id() const -> int { return client_id_; }
// Attempt connecting via a different protocol. If none are left to try,
// returns false.
/// Attempt connecting via a different protocol. If none are left to try,
/// returns false.
auto SwitchProtocol() -> bool;
void RequestDisconnect() override;
@ -32,16 +32,18 @@ class ConnectionToHostUDP : public ConnectionToHost {
void Error(const std::string& error_msg) override;
void Die();
void SendDisconnectRequest();
const auto& addr() const { return *addr_; }
private:
void GetRequestID();
uint8_t request_id_{};
std::unique_ptr<SockAddr> addr_;
void GetRequestID_();
bool did_die_{};
uint8_t request_id_{};
int client_id_{};
millisecs_t last_client_id_request_time_{};
millisecs_t last_disconnect_request_time_{};
int client_id_{};
millisecs_t last_host_response_time_millisecs_{};
std::unique_ptr<SockAddr> addr_;
};
} // namespace ballistica::scene_v1

View File

@ -5,13 +5,17 @@
#include "ballistica/base/assets/assets.h"
#include "ballistica/base/networking/network_reader.h"
#include "ballistica/base/python/base_python.h"
#include "ballistica/core/python/core_python.h"
#include "ballistica/scene_v1/connection/connection_set.h"
#include "ballistica/scene_v1/connection/connection_to_client.h"
#include "ballistica/scene_v1/connection/connection_to_host.h"
#include "ballistica/scene_v1/connection/connection_to_host_udp.h"
#include "ballistica/scene_v1/python/scene_v1_python.h"
#include "ballistica/scene_v1/support/scene_v1_app_mode.h"
#include "ballistica/shared/math/vector3f.h"
#include "ballistica/shared/networking/sockaddr.h"
#include "ballistica/shared/python/python.h"
#include "ballistica/shared/python/python_ref.h"
#include "ballistica/shared/python/python_sys.h"
namespace ballistica::scene_v1 {
@ -20,8 +24,7 @@ namespace ballistica::scene_v1 {
#pragma clang diagnostic push
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
// ------------------------- get_public_party_enabled
// ---------------------------
// ----------------------- get_public_party_enabled ---------------------------
static auto PyGetPublicPartyEnabled(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
@ -411,7 +414,10 @@ static auto PyGetConnectionToHostInfo(PyObject* self, PyObject* args,
const_cast<char**>(kwlist))) {
return nullptr;
}
// Error if we're not in our app-mode.
BA_LOG_ONCE(LogLevel::kWarning,
"bascenev1.get_connection_to_host_info() is deprecated; use "
"bascenev1.get_connection_to_host_info_2().");
BA_PRECONDITION(g_base->InLogicThread());
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
ConnectionToHost* hc = appmode->connections()->connection_to_host();
@ -435,6 +441,57 @@ static PyMethodDef PyGetConnectionToHostInfoDef = {
"(internal)",
};
// --------------------- get_connection_to_host_info_2 -------------------------
static auto PyGetConnectionToHostInfo2(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
static const char* kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "",
const_cast<char**>(kwlist))) {
return nullptr;
}
BA_PRECONDITION(g_base->InLogicThread());
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
ConnectionToHost* hc = appmode->connections()->connection_to_host();
if (hc) {
PythonRef addr_obj;
PythonRef port_obj;
if (ConnectionToHostUDP* hcu = dynamic_cast<ConnectionToHostUDP*>(hc)) {
addr_obj.Steal(PyUnicode_FromString(hcu->addr().AddressString().c_str()));
port_obj.Steal(PyLong_FromLong(hcu->addr().Port()));
} else {
addr_obj.Acquire(Py_None);
port_obj.Acquire(Py_None);
}
auto args =
g_core->python->objs().Get(core::CorePython::ObjID::kEmptyTuple);
auto keywds = PythonRef::Stolen(Py_BuildValue(
"{sssisOsO}", "name", hc->party_name().c_str(), "build_number",
hc->build_number(), "address", addr_obj.Get(), "port", port_obj.Get()));
auto result = g_scene_v1->python->objs()
.Get(SceneV1Python::ObjID::kHostInfoClass)
.Call(args, keywds);
if (!result.Exists()) {
throw Exception("Failed to instantiate HostInfo.", PyExcType::kRuntime);
}
return result.HandOver();
}
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyGetConnectionToHostInfo2Def = {
"get_connection_to_host_info_2", // name
(PyCFunction)PyGetConnectionToHostInfo2, // method
METH_VARARGS | METH_KEYWORDS, // flags
"get_connection_to_host_info_2() -> bascenev1.HostInfo | None\n"
"\n"
"Return info about the host we are currently connected to.",
};
// --------------------------- disconnect_from_host ----------------------------
static auto PyDisconnectFromHost(PyObject* self, PyObject* args,
@ -701,6 +758,7 @@ static auto PyChatMessage(PyObject* self, PyObject* args, PyObject* keywds)
&clients_obj, &sender_override_obj)) {
return nullptr;
}
BA_PRECONDITION(g_base->InLogicThread());
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
message = g_base->python->GetPyLString(message_obj);
@ -775,6 +833,7 @@ auto PythonMethodsNetworking::GetMethods() -> std::vector<PyMethodDef> {
PyDisconnectClientDef,
PyGetClientPublicDeviceUUIDDef,
PyGetConnectionToHostInfoDef,
PyGetConnectionToHostInfo2Def,
PyClientInfoQueryResponseDef,
PyConnectToPartyDef,
PySetAuthenticateClientsDef,

View File

@ -91,6 +91,7 @@ class SceneV1Python {
kGetPlayerIconCall,
kFilterChatMessageCall,
kHandleLocalChatMessageCall,
kHostInfoClass,
kLast // Sentinel; must be at end.
};

View File

@ -37,21 +37,16 @@ class ClientSessionNet : public ClientSession {
auto GetBucketNum() -> int;
bool writing_replay_{};
int delay_sample_counter_{};
float max_delay_smoothed_{};
float last_bucket_max_delay_{};
float current_delay_{};
millisecs_t base_time_received_{};
millisecs_t last_base_time_receive_time_{};
millisecs_t leading_base_time_received_{};
millisecs_t leading_base_time_receive_time_{};
Object::WeakRef<ConnectionToHost> connection_to_host_;
std::vector<SampleBucket> buckets_{5};
// float bucket_max_smoothed_{};
// float bucket_min_smoothed_{};
float max_delay_smoothed_{};
float last_bucket_max_delay_{};
float current_delay_{};
int delay_sample_counter_{};
// int adjust_counter_{};
};
} // namespace ballistica::scene_v1

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21700;
const int kEngineBuildNumber = 21707;
const char* kEngineVersion = "1.7.31";
const int kEngineApiVersion = 8;
@ -290,7 +290,7 @@ void ScreenMessage(const std::string& msg) {
auto CurrentThreadName() -> std::string {
// Currently just ask event-loop for this but perhaps should be talking
// more directly to the OS/etc. to cover more cases.
return EventLoop::CurrentThreadName();
return core::CoreFeatureSet::CurrentThreadName();
}
} // namespace ballistica

View File

@ -98,21 +98,6 @@ EventLoop::EventLoop(EventLoopID identifier_in, ThreadSource source)
}
}
void EventLoop::SetInternalThreadName_(const std::string& name) {
assert(g_core);
std::scoped_lock lock(g_core->thread_name_map_mutex);
g_core->thread_name_map[std::this_thread::get_id()] = name;
}
void EventLoop::ClearCurrentThreadName() {
assert(g_core);
std::scoped_lock lock(g_core->thread_name_map_mutex);
auto i = g_core->thread_name_map.find(std::this_thread::get_id());
if (i != g_core->thread_name_map.end()) {
g_core->thread_name_map.erase(i);
}
}
// These are all exactly the same; its just a way to try and clarify
// in stack traces which thread is running in case it is not otherwise
// evident.
@ -341,53 +326,40 @@ void EventLoop::GetThreadMessages_(std::list<ThreadMessage_>* messages) {
void EventLoop::BootstrapThread_() {
assert(!bootstrapped_);
assert(g_core);
thread_id_ = std::this_thread::get_id();
const char* id_string;
switch (identifier_) {
case EventLoopID::kLogic:
name_ = "logic";
id_string = "ballistica logic";
break;
case EventLoopID::kStdin:
name_ = "stdin";
id_string = "ballistica stdin";
break;
case EventLoopID::kAssets:
name_ = "assets";
id_string = "ballistica assets";
break;
case EventLoopID::kFileOut:
name_ = "fileout";
id_string = "ballistica file-out";
break;
case EventLoopID::kMain:
name_ = "main";
id_string = "ballistica main";
break;
case EventLoopID::kAudio:
name_ = "audio";
id_string = "ballistica audio";
break;
case EventLoopID::kBGDynamics:
name_ = "bgdynamics";
id_string = "ballistica bg-dynamics";
break;
case EventLoopID::kNetworkWrite:
name_ = "networkwrite";
id_string = "ballistica network-write";
break;
default:
throw Exception();
}
assert(!name_.empty() && id_string);
SetInternalThreadName_(name_);
// Note: we currently don't do this for our main thread because it
// changes the process name we see in top/etc. Should look into that.
if (identifier_ != EventLoopID::kMain) {
g_core->platform->SetCurrentThreadName(id_string);
}
assert(!name_.empty());
g_core->RegisterThread(name_);
bootstrapped_ = true;
}
@ -410,7 +382,7 @@ auto EventLoop::ThreadMain_() -> int {
RunToCompletion();
ClearCurrentThreadName();
g_core->UnregisterThread();
return 0;
} catch (const std::exception& e) {
auto error_msg = std::string("Unhandled exception in ")
@ -622,35 +594,6 @@ void EventLoop::DeleteTimer(int id) {
timers_.DeleteTimer(id);
}
auto EventLoop::CurrentThreadName() -> std::string {
if (g_core == nullptr) {
return "unknown(not-yet-inited)";
}
{
std::scoped_lock lock(g_core->thread_name_map_mutex);
auto i = g_core->thread_name_map.find(std::this_thread::get_id());
if (i != g_core->thread_name_map.end()) {
return i->second;
}
}
// Ask pthread for the thread name if we don't have one.
// FIXME - move this to platform.
#if BA_OSTYPE_MACOS || BA_OSTYPE_IOS_TVOS || BA_OSTYPE_LINUX
std::string name = "unknown (sys-name=";
char buffer[256];
int result = pthread_getname_np(pthread_self(), buffer, sizeof(buffer));
if (result == 0) {
name += std::string("\"") + buffer + "\")";
} else {
name += "<error " + std::to_string(result) + ">";
}
return name;
#else
return "unknown";
#endif
}
void EventLoop::RunPendingRunnables_() {
// Pull all runnables off the list first (its possible for one of these
// runnables to add more) and then process them.

View File

@ -25,10 +25,6 @@ class EventLoop {
ThreadSource source = ThreadSource::kCreate);
virtual ~EventLoop();
void ClearCurrentThreadName();
static auto CurrentThreadName() -> std::string;
static void SetEventLoopsSuspended(bool enable);
static auto AreEventLoopsSuspended() -> bool;
@ -113,7 +109,6 @@ class EventLoop {
: type(type), runnable(runnable), completion_flag{completion_flag} {}
};
auto CheckPushRunnableSafety_() -> bool;
void SetInternalThreadName_(const std::string& name);
void WaitForNextEvent_(bool single_cycle);
void LogThreadMessageTally_(
std::vector<std::pair<LogLevel, std::string>>* log_entries);

View File

@ -91,12 +91,16 @@ void FatalError::ReportFatalError(const std::string& message,
if (trace) {
std::string tracestr = trace->FormatForDisplay();
if (!tracestr.empty()) {
logmsg += ("\nCPP-STACK-TRACE-BEGIN:\n" + tracestr
+ "\nCPP-STACK-TRACE-END");
logmsg +=
(("\n----------------------- BALLISTICA-NATIVE-STACK-TRACE-BEGIN "
"--------------------\n")
+ tracestr
+ ("\n----------------------- BALLISTICA-NATIVE-STACK-TRACE-END "
"----------------------"));
}
delete trace;
} else {
logmsg += "\n(CPP-STACK-TRACE-UNAVAILABLE)";
logmsg += "\n(BALLISTICA-NATIVE-STACK-TRACE-UNAVAILABLE)";
}
}
}
@ -155,12 +159,10 @@ void FatalError::DoBlockingFatalErrorDialog(const std::string& message) {
bool* startedptr{&started};
bool* finishedptr{&finished};
// If our thread is holding the GIL, release it to give the main thread
// a better chance of getting to the point of displaying the fatal
// error.
if (Python::HaveGIL()) {
Python::PermanentlyReleaseGIL();
}
// If our thread is holding the GIL, release it while we spin; otherwise
// we can wind up in deadlock if the main thread wants it.
Python::ScopedInterpreterLockRelease gil_release;
g_base_soft->PushMainThreadRunnable(
NewLambdaRunnableUnmanaged([message, startedptr, finishedptr] {
*startedptr = true;

View File

@ -14,22 +14,48 @@ SockAddr::SockAddr(const std::string& addr, int port) {
if (result == 1) {
auto* a = reinterpret_cast<sockaddr_in*>(&addr_);
a->sin_family = AF_INET;
a->sin_port = htons(port); // NOLINT
a->sin_port = htons(port);
a->sin_addr = addr_out;
return;
} else {
struct in6_addr addr6Out {};
result = inet_pton(AF_INET6, addr.c_str(), &addr6Out);
struct in6_addr addr6_out {};
result = inet_pton(AF_INET6, addr.c_str(), &addr6_out);
if (result == 1) {
auto* a = reinterpret_cast<sockaddr_in6*>(&addr_);
a->sin6_family = AF_INET6;
a->sin6_port = htons(port); // NOLINT
a->sin6_addr = addr6Out;
a->sin6_port = htons(port);
a->sin6_addr = addr6_out;
return;
}
}
}
throw Exception("Invalid address: '" + addr + "'.");
throw Exception("Invalid address: '" + addr + "'.", PyExcType::kValue);
}
auto SockAddr::AddressString() const -> std::string {
if (IsV6()) {
char ip_str[INET6_ADDRSTRLEN];
if (inet_ntop(AF_INET6, &(AsSockAddrIn6()->sin6_addr), ip_str,
INET6_ADDRSTRLEN)
== nullptr) {
throw Exception("inet_ntop failed for v6 addr", PyExcType::kValue);
}
return ip_str;
}
char ip_str[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &(AsSockAddrIn()->sin_addr), ip_str, INET_ADDRSTRLEN)
== nullptr) {
throw Exception("inet_ntop failed for v4 addr", PyExcType::kValue);
}
return ip_str;
}
auto SockAddr::Port() const -> int {
if (IsV6()) {
return ntohs(AsSockAddrIn6()->sin6_port);
} else {
return ntohs(AsSockAddrIn()->sin_port);
}
}
} // namespace ballistica

View File

@ -15,16 +15,33 @@ class SockAddr {
public:
SockAddr() { memset(&addr_, 0, sizeof(addr_)); }
// Creates from an ipv4 or ipv6 address string;
// throws an exception on error.
// Creates from an ipv4 or ipv6 address string; throws an exception on
// error.
SockAddr(const std::string& addr, int port);
explicit SockAddr(const sockaddr_storage& addr_in) {
addr_ = addr_in;
assert(addr_.ss_family == AF_INET || addr_.ss_family == AF_INET6);
}
auto GetSockAddr() const -> const sockaddr* {
auto AsSockAddr() const -> const sockaddr* {
return reinterpret_cast<const sockaddr*>(&addr_);
}
auto AsSockAddrIn() const -> const sockaddr_in* {
assert(!IsV6());
return reinterpret_cast<const sockaddr_in*>(&addr_);
}
auto AsSockAddrIn6() const -> const sockaddr_in6* {
assert(IsV6());
return reinterpret_cast<const sockaddr_in6*>(&addr_);
}
auto AddressString() const -> std::string;
auto Port() const -> int;
auto GetSockAddrLen() const -> socklen_t {
switch (addr_.ss_family) {
case AF_INET:
@ -32,9 +49,10 @@ class SockAddr {
case AF_INET6:
return sizeof(sockaddr_in6);
default:
throw Exception();
throw Exception(PyExcType::kValue);
}
}
auto IsV6() const -> bool {
switch (addr_.ss_family) {
case AF_INET:
@ -45,25 +63,22 @@ class SockAddr {
throw Exception();
}
}
auto operator==(const SockAddr& other) const -> bool {
if (addr_.ss_family != other.addr_.ss_family) return false;
if (addr_.ss_family == AF_INET) {
return (reinterpret_cast<const sockaddr_in&>(addr_).sin_addr.s_addr
== reinterpret_cast<const sockaddr_in&>(other.addr_)
.sin_addr.s_addr)
&& (reinterpret_cast<const sockaddr_in&>(addr_).sin_port
== reinterpret_cast<const sockaddr_in&>(other.addr_).sin_port);
auto* a1 = AsSockAddrIn();
auto* a2 = other.AsSockAddrIn();
return !memcmp(&(a1->sin_addr), &(a2->sin_addr), sizeof(in_addr))
&& a1->sin_port == a2->sin_port;
}
if (addr_.ss_family == AF_INET6) {
return !memcmp(&(reinterpret_cast<const sockaddr_in6&>(addr_).sin6_addr),
&(reinterpret_cast<const sockaddr_in6&>(other.addr_)
.sin6_addr),
sizeof(in6_addr))
&& (reinterpret_cast<const sockaddr_in6&>(addr_).sin6_port
== reinterpret_cast<const sockaddr_in6&>(other.addr_)
.sin6_port);
auto* a1 = AsSockAddrIn6();
auto* a2 = other.AsSockAddrIn6();
return !memcmp(&(a1->sin6_addr), &(a2->sin6_addr), sizeof(in6_addr))
&& a1->sin6_port == a2->sin6_port;
}
throw Exception();
throw Exception(PyExcType::kValue);
}
private:

View File

@ -416,9 +416,7 @@ class Python::ScopedInterpreterLock::Impl {
};
Python::ScopedInterpreterLock::ScopedInterpreterLock()
: impl_{new Python::ScopedInterpreterLock::Impl()}
// impl_{std::make_unique<Python::ScopedInterpreterLock::Impl>()}
{}
: impl_{new Python::ScopedInterpreterLock::Impl()} {}
Python::ScopedInterpreterLock::~ScopedInterpreterLock() { delete impl_; }

View File

@ -41,7 +41,8 @@ class Python {
/// Use this to protect Python code that may be run in cases where we
/// don't hold the Global Interpreter Lock (GIL). (Basically anything
/// outside of the logic thread).
/// outside of the logic thread). This will release and then restore
/// the GIL if it is held initially; otherwise it is a no-op.
class ScopedInterpreterLock {
public:
ScopedInterpreterLock();
@ -49,9 +50,6 @@ class Python {
private:
class Impl;
// Note: should use unique_ptr for this, but build fails on raspberry pi
// (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later.
// std::unique_ptr<Impl> impl_{};
Impl* impl_{};
};
@ -64,9 +62,6 @@ class Python {
private:
class Impl;
// Note: should use unique_ptr for this, but build fails on raspberry pi
// (gcc 8.3.0). Works on Ubuntu 9.3 so should try again later.
// std::unique_ptr<Impl> impl_{};
Impl* impl_{};
};

View File

@ -118,7 +118,9 @@ class PythonRef {
/// Release the held reference (if one is held).
void Release();
/// Clear the ref without decrementing its count and return the raw PyObject*
/// Clear the ref without decrementing its count and return the raw
/// PyObject*. Useful for functions that are expected to return a new
/// Python ref.
auto HandOver() -> PyObject* {
assert(obj_);
PyObject* obj = obj_;
@ -151,8 +153,9 @@ class PythonRef {
/// Throws Exception if an error occurs.
auto DictGetItem(const char* name) const -> PythonRef;
/// The equivalent of calling Python str() on the contained PyObject.
/// Gracefully handles invalid refs.
/// The equivalent of calling Python str() on the contained PyObject, and
/// gracefully handles invalid refs. To throw exceptions on invalid refs,
/// use ValueAsString();
auto Str() const -> std::string;
/// The equivalent of calling repr() on the contained PyObject.

View File

@ -2589,90 +2589,6 @@ static PyMethodDef PyGetSpecialWidgetDef = {
"(internal)",
};
// -------------------------- have_incentivized_ad -----------------------------
// returns an extra hash value that can be incorporated into security checks;
// this contains things like whether console commands have been run, etc.
static auto PyHaveIncentivizedAd(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
static const char* kwlist[] = {nullptr};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "",
const_cast<char**>(kwlist))) {
return nullptr;
}
if (g_core->have_incentivized_ad) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
BA_PYTHON_CATCH;
}
static PyMethodDef PyHaveIncentivizedAdDef = {
"have_incentivized_ad", // name
(PyCFunction)PyHaveIncentivizedAd, // method
METH_VARARGS | METH_KEYWORDS, // flags
"have_incentivized_ad() -> bool\n"
"\n"
"(internal)",
};
// ----------------------------- can_show_ad -----------------------------------
// this returns whether it makes sense to show an currently
static auto PyCanShowAd(PyObject* self, PyObject* args, PyObject* keywds)
-> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
// if we've got any network connections, no ads.
// (don't want to make someone on the other end wait or risk disconnecting
// them or whatnot). Also disallow ads if remote apps are connected; at least
// on Android, ads pause our activity which disconnects the remote app.
// (need to fix this).
if (g_base->app_mode()->HasConnectionToHost()
|| g_base->app_mode()->HasConnectionToClients()
|| g_base->input->HaveRemoteAppController()) {
Py_RETURN_FALSE;
}
Py_RETURN_TRUE; // all systems go..
BA_PYTHON_CATCH;
}
static PyMethodDef PyCanShowAdDef = {
"can_show_ad", // name
(PyCFunction)PyCanShowAd, // method
METH_VARARGS | METH_KEYWORDS, // flags
"can_show_ad() -> bool\n"
"\n"
"(internal)",
};
// ---------------------------- has_video_ads ----------------------------------
static auto PyHasVideoAds(PyObject* self, PyObject* args, PyObject* keywds)
-> PyObject* {
BA_PYTHON_TRY;
if (g_core->platform->GetHasVideoAds()) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
}
BA_PYTHON_CATCH;
}
static PyMethodDef PyHasVideoAdsDef = {
"has_video_ads", // name
(PyCFunction)PyHasVideoAds, // method
METH_VARARGS | METH_KEYWORDS, // flags
"has_video_ads() -> bool\n"
"\n"
"(internal)",
};
// ------------------------------ back_press -----------------------------------
static auto PyBackPress(PyObject* self, PyObject* args, PyObject* keywds)
@ -2893,9 +2809,6 @@ auto PythonMethodsUIV1::GetMethods() -> std::vector<PyMethodDef> {
PyOpenFileExternallyDef,
PyOpenURLDef,
PyBackPressDef,
PyHasVideoAdsDef,
PyCanShowAdDef,
PyHaveIncentivizedAdDef,
PyGetSpecialWidgetDef,
PySetPartyWindowOpenDef,
PySetPartyIconAlwaysVisibleDef,

View File

@ -10,6 +10,7 @@ from bascenev1._player import Player
from bascenev1._dependency import AssetPackage
from bascenev1._activity import Activity
from bascenev1._session import Session
from bascenev1._net import HostInfo
import _bascenev1
# The C++ layer looks for this variable:
@ -30,4 +31,5 @@ values = [
AssetPackage, # kAssetPackageClass
Activity, # kActivityClass
Session, # kSceneV1SessionClass
HostInfo, # kHostInfoClass
]

View File

@ -5,22 +5,49 @@
from __future__ import annotations
from enum import Enum
from typing import TYPE_CHECKING
from dataclasses import dataclass
from typing import TYPE_CHECKING, Annotated
from efro.dataclassio import ioprepped, IOAttrs
if TYPE_CHECKING:
pass
class AppExperience(Enum):
"""Overall experience that can be provided by a Ballistica app.
class AppInterfaceIdiom(Enum):
"""A general form-factor or way of experiencing a Ballistica app.
This corresponds generally, but not exactly, to distinct apps built
with Ballistica. However, a single app may support multiple experiences,
or there may be multiple apps targeting one experience. Cloud components
such as leagues are generally associated with an AppExperience.
Note that it is possible for a running app to switch idioms (for
instance if a mobile device or computer is connected to a TV).
"""
# A special experience category that is supported everywhere. Used
PHONE = 'phone'
TABLET = 'tablet'
DESKTOP = 'desktop'
TV = 'tv'
XR = 'xr'
class AppExperience(Enum):
"""A particular experience that can be provided by a Ballistica app.
This is one metric used to isolate different playerbases from
eachother where there might be no technical barriers doing so.
For example, a casual one-hand-playable phone game and an augmented
reality tabletop game may both use the same scene-versions and
networking-protocols and whatnot, but it would make no sense to
allow players of one join servers for the other. AppExperience can
be used to keep these player bases separate.
Generally a single Ballistica app targets a single AppExperience.
This is not a technical requirement, however. A single app may
support multiple experiences, or there may be multiple apps
targeting one experience. Cloud components such as leagues are
generally associated with an AppExperience so that they are only
visible to client apps designed for that play style.
"""
# An experience that is supported everywhere. Used
# for the default empty AppMode when starting the app, etc.
EMPTY = 'empty'
@ -33,3 +60,79 @@ class AppExperience(Enum):
# touch-screen allowing a mobile device to be used as a game
# controller.
REMOTE = 'remote'
class AppArchitecture(Enum):
"""Processor architecture the App is running on."""
ARM = 'arm'
ARM64 = 'arm64'
X86 = 'x86'
X86_64 = 'x86_64'
class AppPlatform(Enum):
"""Overall platform a Ballistica build can be targeting.
Each distinct flavor of an app has a unique combination
of AppPlatform and AppVariant. Generally platform describes
a set of hardware, while variant describes a destination or
purpose for the build.
"""
MAC = 'mac'
WINDOWS = 'windows'
LINUX = 'linux'
ANDROID = 'android'
IOS = 'ios'
TVOS = 'tvos'
class AppVariant(Enum):
"""A unique Ballistica build type within a single platform.
Each distinct flavor of an app has a unique combination
of AppPlatform and AppVariant. Generally platform describes
a set of hardware, while variant describes a destination or
purpose for the build.
"""
# Default builds.
GENERIC = 'generic'
# Builds intended for public testing (may have some extra checks
# or logging enabled).
TEST = 'test'
# Various stores.
AMAZON_APPSTORE = 'amazon_appstore'
GOOGLE_PLAY = 'google_play'
APP_STORE = 'app_store'
WINDOWS_STORE = 'windows_store'
STEAM = 'steam'
META = 'meta'
EPIC_GAMES_STORE = 'epic_games_store'
# Other.
ARCADE = 'arcade'
DEMO = 'demo'
@ioprepped
@dataclass
class AppInstanceInfo:
"""General info about an individual running app."""
name = Annotated[str, IOAttrs('n')]
version = Annotated[str, IOAttrs('v')]
build = Annotated[int, IOAttrs('b')]
platform = Annotated[AppPlatform, IOAttrs('p')]
variant = Annotated[AppVariant, IOAttrs('va')]
architecture = Annotated[AppArchitecture, IOAttrs('a')]
os_version = Annotated[str | None, IOAttrs('o')]
interface_idiom: Annotated[AppInterfaceIdiom, IOAttrs('i')]
locale: Annotated[str, IOAttrs('l')]
device: Annotated[str | None, IOAttrs('d')]

View File

@ -216,6 +216,12 @@ def _writefuncs(
'import bascenev1 # pylint: disable=cyclic-import\n'
'return bascenev1.Time(0.0)'
)
elif returns == 'bascenev1.HostInfo | None':
returnstr = (
'import bascenev1 # pylint: disable=cyclic-import\n'
'return bascenev1.HostInfo(\'dummyname\', -1,'
' \'dummy_addr\', -1)'
)
elif returns == 'babase.DisplayTime':
returnstr = (
'import babase # pylint: disable=cyclic-import\n'

View File

@ -426,7 +426,6 @@ class ProjectUpdater:
# from batools.xcode import update_xcode_project
for projpath in [
# 'ballisticakit-mac.xcodeproj/project.pbxproj',
# 'ballisticakit-ios.xcodeproj/project.pbxproj',
'ballisticakit-xcode/BallisticaKit.xcodeproj/project.pbxproj',
]:

View File

@ -62,7 +62,7 @@ def build_openal(arch: str, mode: str) -> None:
)
# subprocess.run(['git', 'checkout', '1.23.1'], check=True, cwd=builddir)
subprocess.run(
['git', 'checkout', '5b5b948516f7340810ebbfdd5e46eb40f85d2e56'],
['git', 'checkout', 'b81a270f6c1e795ca70d7684e0ccf35a19f247e2'],
check=True,
cwd=builddir,
)