diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index ef8083cd..b0d3e764 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -1159,6 +1159,7 @@
ioprep
ioprepped
ioprepping
+ ioreg
ipaddress
ipos
iprof
@@ -1203,6 +1204,7 @@
keepalives
keepaway
keeprefs
+ kerploople
keyanntype
keyfilt
keyint
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce4810ba..f6d54ff1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+### 1.6.10 (20501, 2022-03-02)
+- Added `_ba.get_client_public_device_uuid` function which returns a semi-permanent device id for a connected client running 1.6.10 or newer. Can be useful to combat spam attacks or other mischief.
+- Fixed an issue with `make update` not properly rewriting Visual Studio project files to account for new/deleted source files.
+- Removed various bits of code associated with the (no-longer-functional) Google Play Games multiplayer connections.
+
### 1.6.9 (20486, 2022-02-22)
- Upgraded Android Python to 3.9.10
- Fixed an issue with SSL in Android builds that was preventing communication with the master-server in 1.6.8
diff --git a/README.md b/README.md
index 65c96357..65fe61ee 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@

-The Ballistica project is the foundation for the next generation of [BombSquad](http://bombsquadgame.com). It debuted with version 1.5 of the game and lays the foundation for some of the big changes coming in 2.0.
+The Ballistica project is the foundation for the next generation of [BombSquad](https://www.froemling.net/apps/bombsquad). It debuted with version 1.5 of the game and lays the foundation for some of the big changes coming in 2.0.
[Head to the project wiki to get started](https://github.com/efroemling/ballistica/wiki), or learn more about the project below.
diff --git a/assets/src/ba_data/python/ba/_hooks.py b/assets/src/ba_data/python/ba/_hooks.py
index 11dd8235..11ddae36 100644
--- a/assets/src/ba_data/python/ba/_hooks.py
+++ b/assets/src/ba_data/python/ba/_hooks.py
@@ -352,3 +352,13 @@ def get_player_icon(sessionplayer: ba.SessionPlayer) -> dict[str, Any]:
'tint_color': info['tint_color'],
'tint2_color': info['tint2_color']
}
+
+
+def hash_strings(inputs: list[str]) -> str:
+ """Hash provided strings into a short output string."""
+ import hashlib
+ sha = hashlib.sha1()
+ for inp in inputs:
+ sha.update(inp.encode())
+
+ return sha.hexdigest()
diff --git a/assets/src/ba_data/python/ba/_language.py b/assets/src/ba_data/python/ba/_language.py
index 6bf49f3e..b637bb49 100644
--- a/assets/src/ba_data/python/ba/_language.py
+++ b/assets/src/ba_data/python/ba/_language.py
@@ -374,7 +374,7 @@ class Lstr:
currently-active language.
To see available resource keys, look at any of the bs_language_*.py files
- in the game or the translations pages at bombsquadgame.com/translate.
+ in the game or the translations pages at legacy.ballistica.net/translate.
# EXAMPLE 1: specify a string from a resource path
mynode.text = ba.Lstr(resource='audioSettingsWindow.titleText')
diff --git a/assets/src/ba_data/python/ba/_net.py b/assets/src/ba_data/python/ba/_net.py
index 8ccc5c95..d427ccce 100644
--- a/assets/src/ba_data/python/ba/_net.py
+++ b/assets/src/ba_data/python/ba/_net.py
@@ -118,15 +118,14 @@ class MasterServerCallThread(threading.Thread):
if self._request_type == 'get':
response = urllib.request.urlopen(
urllib.request.Request(
- (_ba.get_master_server_address(internal=True) + '/' +
+ (_ba.get_master_server_address() + '/' +
self._request + '?' + parse.urlencode(self._data)),
None, {'User-Agent': _ba.app.user_agent_string}),
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
elif self._request_type == 'post':
response = urllib.request.urlopen(
urllib.request.Request(
- _ba.get_master_server_address(internal=True) + '/' +
- self._request,
+ _ba.get_master_server_address() + '/' + self._request,
parse.urlencode(self._data).encode(),
{'User-Agent': _ba.app.user_agent_string}),
timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
diff --git a/assets/src/ba_data/python/bastd/ui/party.py b/assets/src/ba_data/python/bastd/ui/party.py
index 307b5704..f0b65d38 100644
--- a/assets/src/ba_data/python/bastd/ui/party.py
+++ b/assets/src/ba_data/python/bastd/ui/party.py
@@ -5,7 +5,6 @@
from __future__ import annotations
import math
-import weakref
from typing import TYPE_CHECKING, cast
import _ba
@@ -413,53 +412,3 @@ class PartyWindow(ba.Window):
"""Close the window and make a lovely sound."""
ba.playsound(ba.getsound('swish'))
self.close()
-
-
-def handle_party_invite(name: str, invite_id: str) -> None:
- """Handle an incoming party invitation."""
- from bastd import mainmenu
- from bastd.ui import confirm
- ba.playsound(ba.getsound('fanfare'))
-
- # if we're not in the main menu, just print the invite
- # (don't want to screw up an in-progress game)
- in_game = not isinstance(_ba.get_foreground_host_session(),
- mainmenu.MainMenuSession)
- if in_game:
- ba.screenmessage(ba.Lstr(
- value='${A}\n${B}',
- subs=[('${A}',
- ba.Lstr(resource='gatherWindow.partyInviteText',
- subs=[('${NAME}', name)])),
- ('${B}',
- ba.Lstr(
- resource='gatherWindow.partyInviteGooglePlayExtraText'))
- ]),
- color=(0.5, 1, 0))
- else:
-
- def do_accept(inv_id: str) -> None:
- _ba.accept_party_invitation(inv_id)
-
- conf = confirm.ConfirmWindow(
- ba.Lstr(resource='gatherWindow.partyInviteText',
- subs=[('${NAME}', name)]),
- ba.Call(do_accept, invite_id),
- width=500,
- height=150,
- color=(0.75, 1.0, 0.0),
- ok_text=ba.Lstr(resource='gatherWindow.partyInviteAcceptText'),
- cancel_text=ba.Lstr(resource='gatherWindow.partyInviteIgnoreText'))
-
- # FIXME: Ugly.
- # Let's store the invite-id away on the confirm window so we know if
- # we need to kill it later.
- conf.party_invite_id = invite_id # type: ignore
-
- # store a weak-ref so we can get at this later
- ba.app.invite_confirm_windows.append(weakref.ref(conf))
-
- # go ahead and prune our weak refs while we're here.
- ba.app.invite_confirm_windows = [
- w for w in ba.app.invite_confirm_windows if w() is not None
- ]
diff --git a/assets/src/ba_data/python/bastd/ui/settings/advanced.py b/assets/src/ba_data/python/bastd/ui/settings/advanced.py
index d281b4f3..73a1338a 100644
--- a/assets/src/ba_data/python/bastd/ui/settings/advanced.py
+++ b/assets/src/ba_data/python/bastd/ui/settings/advanced.py
@@ -322,8 +322,8 @@ class AdvancedSettingsWindow(ba.Window):
subs=[('${APP_NAME}', ba.Lstr(resource='titleText'))
]),
autoselect=True,
- on_activate_call=ba.Call(ba.open_url,
- 'http://bombsquadgame.com/translate'))
+ on_activate_call=ba.Call(
+ ba.open_url, 'https://legacy.ballistica.net/translate'))
self._lang_status_text = ba.textwidget(parent=self._subcontainer,
position=(self._sub_width * 0.5,
diff --git a/assets/src/ba_data/python/bastd/ui/settings/nettesting.py b/assets/src/ba_data/python/bastd/ui/settings/nettesting.py
index 59224ffa..31dd809e 100644
--- a/assets/src/ba_data/python/bastd/ui/settings/nettesting.py
+++ b/assets/src/ba_data/python/bastd/ui/settings/nettesting.py
@@ -167,16 +167,12 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
_print_test_results(_dummy_fail)
# V1 ping
- baseaddr = _ba.get_master_server_address(internal=True,
- source=0,
- version=1)
+ baseaddr = _ba.get_master_server_address(source=0, version=1)
_print(f'\nContacting V1 master-server src0 ({baseaddr})...')
_print_test_results(lambda: _test_fetch(baseaddr))
# V1 alternate ping
- baseaddr = _ba.get_master_server_address(internal=True,
- source=1,
- version=1)
+ baseaddr = _ba.get_master_server_address(source=1, version=1)
_print(f'\nContacting V1 master-server src1 ({baseaddr})...')
_print_test_results(lambda: _test_fetch(baseaddr))
@@ -185,14 +181,14 @@ def _run_diagnostics(weakwin: weakref.ref[NetTestingWindow]) -> None:
for srcid, result in sorted(ba.app.net.v1_ctest_results.items()):
_print(f'\nV1 src{srcid} result: {result}')
- curv1addr = _ba.get_master_server_address(internal=True, version=1)
+ curv1addr = _ba.get_master_server_address(version=1)
_print(f'\nUsing V1 address: {curv1addr}')
_print('\nRunning V1 transaction...')
_print_test_results(_test_v1_transaction)
# V2 ping
- baseaddr = _ba.get_master_server_address(internal=True, version=2)
+ baseaddr = _ba.get_master_server_address(version=2)
_print(f'\nContacting V2 master-server ({baseaddr})...')
_print_test_results(lambda: _test_fetch(baseaddr))
diff --git a/ballisticacore-cmake/.idea/dictionaries/ericf.xml b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
index 5a9ec647..652abd5f 100644
--- a/ballisticacore-cmake/.idea/dictionaries/ericf.xml
+++ b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
@@ -560,6 +560,7 @@
ioprep
ioprepped
ioprepping
+ ioreg
iserverget
iserverput
isinst
@@ -587,6 +588,7 @@
jnames
json's
keepalives
+ kerploople
keyanntype
keycode
keyfilt
diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
index 0d0dc72c..7dcc6f9c 100644
--- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
+++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj
@@ -189,453 +189,72 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
index 25c8e135..1f8490f9 100644
--- a/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
+++ b/ballisticacore-windows/Generic/BallisticaCoreGeneric.vcxproj.filters
@@ -1,1347 +1,204 @@
-
+
ballistica\app
-
+
ballistica\app
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica
-
-
- ballistica
-
-
+
ballistica\config
-
+
ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
+
ballistica\game
-
-
- ballistica\game
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
- ballistica\game
-
-
+
+
ballistica\game
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
- ballistica\generic
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media
-
-
- ballistica\media
-
-
- ballistica\media
-
-
- ballistica\media
-
-
+
ballistica\networking
-
- ballistica\networking
-
-
- ballistica\networking
-
-
- ballistica\networking
-
-
+
ballistica\networking
-
- ballistica\networking
-
-
+
ballistica\networking
-
+
ballistica\networking
+
+
+ ballistica\platform\android\amazon
+
+
+ ballistica\platform\android\amazon
-
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android\cardboard
+
+
+ ballistica\platform\android\cardboard
+
+
+ ballistica\platform\android\google
+
+
+ ballistica\platform\android\google
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android\utf8
+
+
+ ballistica\platform\android\utf8
+
+
+ ballistica\platform\android\utf8
+
+
ballistica\platform\apple
-
- ballistica\platform\linux
+
+ ballistica\platform\apple
+
+
+ ballistica\platform\apple
-
- ballistica\platform\linux
+
+ ballistica\platform\apple
-
- ballistica\platform
+
+ ballistica\platform\apple
-
- ballistica\platform
+
+ ballistica\platform\oculus
-
- ballistica\platform
-
-
- ballistica\platform\sdl
+
+ ballistica\platform\oculus
-
- ballistica\platform\sdl
+
+ ballistica\platform\oculus
-
- ballistica\python\class
+
+ ballistica\platform\windows
-
- ballistica\python\class
+
+ ballistica\platform\windows
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene
-
-
- ballistica\scene
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
external\open_dynamics_engine-ef\ode
@@ -1577,40 +434,22 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
-
diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
index d3df0a33..b0295807 100644
--- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
+++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj
@@ -184,453 +184,72 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
index 25c8e135..1f8490f9 100644
--- a/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
+++ b/ballisticacore-windows/Headless/BallisticaCoreHeadless.vcxproj.filters
@@ -1,1347 +1,204 @@
-
+
ballistica\app
-
+
ballistica\app
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\app
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica\audio
-
-
- ballistica
-
-
- ballistica
-
-
+
ballistica\config
-
+
ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
-
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\core
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
+
+ ballistica\config
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics\bg
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics\material
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
- ballistica\dynamics
-
-
+
ballistica\game
-
-
- ballistica\game
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
+
+
ballistica\game\connection
-
-
- ballistica\game
-
-
+
+
ballistica\game
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
- ballistica\game
-
-
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
+
+
ballistica\game\session
-
-
- ballistica\generic
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\generic
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics\component
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics\gl
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics\mesh
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\text
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics\texture
-
-
- ballistica\graphics
-
-
- ballistica\graphics
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input\device
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\input
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\math
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\component
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media\data
-
-
- ballistica\media
-
-
- ballistica\media
-
-
- ballistica\media
-
-
- ballistica\media
-
-
+
ballistica\networking
-
- ballistica\networking
-
-
- ballistica\networking
-
-
- ballistica\networking
-
-
+
ballistica\networking
-
- ballistica\networking
-
-
+
ballistica\networking
-
+
ballistica\networking
+
+
+ ballistica\platform\android\amazon
+
+
+ ballistica\platform\android\amazon
-
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android\cardboard
+
+
+ ballistica\platform\android\cardboard
+
+
+ ballistica\platform\android\google
+
+
+ ballistica\platform\android\google
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android
+
+
+ ballistica\platform\android\utf8
+
+
+ ballistica\platform\android\utf8
+
+
+ ballistica\platform\android\utf8
+
+
ballistica\platform\apple
-
- ballistica\platform\linux
+
+ ballistica\platform\apple
+
+
+ ballistica\platform\apple
-
- ballistica\platform\linux
+
+ ballistica\platform\apple
-
- ballistica\platform
+
+ ballistica\platform\apple
-
- ballistica\platform
+
+ ballistica\platform\oculus
-
- ballistica\platform
-
-
- ballistica\platform\sdl
+
+ ballistica\platform\oculus
-
- ballistica\platform\sdl
+
+ ballistica\platform\oculus
-
- ballistica\python\class
+
+ ballistica\platform\windows
-
- ballistica\python\class
+
+ ballistica\platform\windows
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
- ballistica\python\class
-
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
+
ballistica\python\methods
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python\methods
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\python
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene\node
-
-
- ballistica\scene
-
-
- ballistica\scene
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
-
- ballistica\ui\widget
-
external\open_dynamics_engine-ef\ode
@@ -1577,40 +434,22 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
-
diff --git a/src/ballistica/app/app.cc b/src/ballistica/app/app.cc
index f891ae0f..c0996f34 100644
--- a/src/ballistica/app/app.cc
+++ b/src/ballistica/app/app.cc
@@ -39,7 +39,7 @@ void App::PostInit() {
App::~App() = default;
-auto App::UsesEventLoop() const -> bool {
+auto App::ManagesEventLoop() const -> bool {
// We have 2 redundant values for essentially the same thing;
// should get rid of IsEventPushMode() once we've created
// App subclasses for our various platforms.
@@ -48,8 +48,8 @@ auto App::UsesEventLoop() const -> bool {
void App::RunRenderUpkeepCycle() {
// This should only be used in cases where the OS is handling the event loop.
- assert(!UsesEventLoop());
- if (UsesEventLoop()) {
+ assert(!ManagesEventLoop());
+ if (ManagesEventLoop()) {
return;
}
@@ -111,13 +111,10 @@ void App::ShutdownComplete() {
assert(InMainThread());
assert(g_platform);
- // Need to call our cleanup stuff that would otherwise get called in main.
- g_platform->FinalCleanup();
-
done_ = true;
// Kill our own event loop (or tell the OS to kill its).
- if (UsesEventLoop()) {
+ if (ManagesEventLoop()) {
thread()->Quit();
} else {
g_platform->QuitApp();
@@ -249,7 +246,7 @@ void App::ResumeApp() {
void App::DidFinishRenderingFrame(FrameDef* frame) {}
void App::PrimeEventPump() {
- assert(!UsesEventLoop());
+ assert(!ManagesEventLoop());
// Pump events manually until a screen gets created.
// At that point we use frame-draws to drive our event loop.
diff --git a/src/ballistica/app/app.h b/src/ballistica/app/app.h
index 30576afc..3bfa0878 100644
--- a/src/ballistica/app/app.h
+++ b/src/ballistica/app/app.h
@@ -30,7 +30,7 @@ class App : public Module {
/// If false, BallisticaMain returns immediately and it is assumed
/// that the OS handles the app lifecycle and pushes events to the app
/// via callbacks/etc.
- auto UsesEventLoop() const -> bool;
+ auto ManagesEventLoop() const -> bool;
/// Called for non-event-loop apps to give them an opportunity to
/// ensure they are self-sustaining. For instance, an app relying on
diff --git a/src/ballistica/app/app_globals.h b/src/ballistica/app/app_globals.h
index 87689a1f..89c9c2c1 100644
--- a/src/ballistica/app/app_globals.h
+++ b/src/ballistica/app/app_globals.h
@@ -77,8 +77,6 @@ class AppGlobals {
int delay_bucket_samples{60};
bool vr_mode{g_buildconfig.vr_build()};
- // Temp dirty way to do some shutdown stuff (FIXME: move to an App method).
- void (*temp_cleanup_callback)() = nullptr;
millisecs_t real_time{};
millisecs_t last_real_time_ticks{};
std::mutex real_time_mutex;
diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc
index dc11d331..be5e2b8a 100644
--- a/src/ballistica/ballistica.cc
+++ b/src/ballistica/ballistica.cc
@@ -21,8 +21,8 @@
namespace ballistica {
// These are set automatically via script; don't modify them here.
-const int kAppBuildNumber = 20486;
-const char* kAppVersion = "1.6.9";
+const int kAppBuildNumber = 20501;
+const char* kAppVersion = "1.6.10";
// Our standalone globals.
// These are separated out for easy access.
@@ -138,9 +138,9 @@ auto BallisticaMain(int argc, char** argv) -> int {
// Phase 3/4: Create a screen and/or kick off game (in other threads).
// -------------------------------------------------------------------------
- if (g_app->UsesEventLoop()) {
- // On our event-loop using platforms we now simply sit in our event loop
- // until the app is quit.
+ if (g_app->ManagesEventLoop()) {
+ // On our event-loop-managing platforms we now simply sit in our event
+ // loop until the app is quit.
g_main_thread->RunEventLoop(false);
} else {
// In this case we'll now simply return and let the OS feed us events
@@ -156,8 +156,8 @@ auto BallisticaMain(int argc, char** argv) -> int {
std::string("Unhandled exception in BallisticaMain(): ") + exc.what();
// Exiting the app via an exception tends to trigger crash reports
- // on various platforms. If it doesn't appear that we're an official live
- // build then we'd rather just exit cleanly with an error code and avoid
+ // on various platforms. If it seems we're not on an official live
+ // build then we'd rather just exit cleanly with an error code and avoid
// polluting crash report logs from dev builds.
FatalError::ReportFatalError(error_msg, true);
bool exit_cleanly = !IsUnmodifiedBlessedBuild();
@@ -210,7 +210,7 @@ auto FatalError(const std::string& message) -> void {
assert(handled);
}
-auto GetUniqueSessionIdentifier() -> const std::string& {
+auto GetAppInstanceUUID() -> const std::string& {
static std::string session_id;
static bool have_session_id = false;
@@ -225,7 +225,7 @@ auto GetUniqueSessionIdentifier() -> const std::string& {
}
if (!have_session_id) {
// As an emergency fallback simply use a single random number.
- Log("WARNING: GetUniqueSessionIdentifier() using rand fallback.");
+ Log("WARNING: GetSessionUUID() using rand fallback.");
srand(static_cast(
Platform::GetCurrentMilliseconds())); // NOLINT
session_id = std::to_string(static_cast(rand())); // NOLINT
@@ -256,11 +256,7 @@ auto InAudioThread() -> bool {
}
auto InBGDynamicsThread() -> bool {
-#if !BA_HEADLESS_BUILD
return (g_bg_dynamics_server && g_bg_dynamics_server->thread()->IsCurrent());
-#else
- return false;
-#endif
}
auto InMediaThread() -> bool {
diff --git a/src/ballistica/ballistica.h b/src/ballistica/ballistica.h
index 47b37dfd..699ce0c9 100644
--- a/src/ballistica/ballistica.h
+++ b/src/ballistica/ballistica.h
@@ -147,9 +147,9 @@ extern Utils* g_utils;
/// Main ballistica entry point.
auto BallisticaMain(int argc, char** argv) -> int;
-/// Return a string that should be universally unique to this device and
+/// Return a string that should be universally unique to this particular
/// running instance of the app.
-auto GetUniqueSessionIdentifier() -> const std::string&;
+auto GetAppInstanceUUID() -> const std::string&;
/// Have our main threads/modules all been inited yet?
auto IsBootstrapped() -> bool;
@@ -242,7 +242,7 @@ inline auto HeadlessMode() -> bool {
/// by significant amounts (even if the app has been sleeping or whatnot).
auto GetRealTime() -> millisecs_t;
-/// Return a random float value. Not guaranteed to be deterministic or
+/// Return a random float value. Not guaranteed to be deterministic or
/// consistent across platforms.
inline auto RandomFloat() -> float {
// FIXME: should convert this to something thread-safe.
diff --git a/src/ballistica/game/connection/connection_set.h b/src/ballistica/game/connection/connection_set.h
index 50335629..29db4fc2 100644
--- a/src/ballistica/game/connection/connection_set.h
+++ b/src/ballistica/game/connection/connection_set.h
@@ -94,19 +94,6 @@ class ConnectionSet {
const std::vector& clients)
-> void;
-#if BA_GOOGLE_BUILD
- auto PushClientDisconnectedGooglePlayCall(int id) -> void;
- int GetGooglePlayClientCount() const;
- auto PushHostConnectedGooglePlayCall() -> void;
- auto PushClientConnectedGooglePlayCall(int id) -> void;
- auto PushCompressedGamePacketFromHostGooglePlayCall(
- const std::vector& data) -> void;
- auto PushCompressedGamePacketFromClientGooglePlayCall(
- int google_client_id, const std::vector& data) -> void;
- auto ClientIDFromGooglePlayClientID(int google_id) -> int;
- auto GooglePlayClientIDFromClientID(int client_id) -> int;
-#endif
-
auto UDPConnectionPacket(const std::vector& data,
const SockAddr& addr) -> void;
auto PushClientDisconnectedCall(int id) -> void;
@@ -125,11 +112,6 @@ class ConnectionSet {
// Prevents us from printing multiple 'you got disconnected' messages.
bool printed_host_disconnect_{};
-
-#if BA_GOOGLE_BUILD
- std::unordered_map google_play_id_to_client_id_map_;
- std::unordered_map client_id_to_google_play_id_map_;
-#endif
};
} // namespace ballistica
diff --git a/src/ballistica/game/connection/connection_to_client.h b/src/ballistica/game/connection/connection_to_client.h
index 2a509344..bb58023d 100644
--- a/src/ballistica/game/connection/connection_to_client.h
+++ b/src/ballistica/game/connection/connection_to_client.h
@@ -41,34 +41,45 @@ class ConnectionToClient : public Connection {
/// account id has been verified by the master server.
auto IsAdmin() const -> bool;
- private:
- virtual auto ShouldPrintIncompatibleClientErrors() const -> bool;
+ auto kick_voted() const { return kick_voted_; }
+ auto set_kick_voted(bool val) { kick_voted_ = val; }
+ auto kick_vote_choice() const { return kick_vote_choice_; }
+ auto set_kick_vote_choice(bool val) { kick_vote_choice_ = val; }
+ auto set_next_kick_vote_allow_time(millisecs_t val) {
+ next_kick_vote_allow_time_ = val;
+ }
+ auto next_kick_vote_allow_time() const { return next_kick_vote_allow_time_; }
+
+ auto public_device_id() const { return public_device_id_; }
// Returns a spec for this client that incorporates their player names
// or their peer name if they have no players.
auto GetCombinedSpec() -> PlayerSpec;
+
+ private:
+ virtual auto ShouldPrintIncompatibleClientErrors() const -> bool;
auto GetClientInputDevice(int remote_id) -> ClientInputDevice*;
void Error(const std::string& error_msg) override;
std::string our_handshake_player_spec_str_;
std::string our_handshake_salt_;
std::string peer_public_account_id_;
- ClientControllerInterface* controller_ = nullptr;
+ std::string public_device_id_;
+ ClientControllerInterface* controller_{};
std::unordered_map client_input_devices_;
- millisecs_t last_hand_shake_send_time_ = 0;
- int id_ = -1;
- int build_number_ = 0;
- bool got_client_info_ = false;
- bool kick_voted_ = false;
- bool kick_vote_choice_ = false;
+ millisecs_t last_hand_shake_send_time_{};
+ int id_{-1};
+ int build_number_{};
+ bool got_client_info_{};
+ bool kick_voted_{};
+ bool kick_vote_choice_{};
std::string token_;
std::string peer_hash_;
PythonRef player_profiles_;
- bool got_info_from_master_server_ = false;
+ bool got_info_from_master_server_{};
std::vector last_chat_times_;
- millisecs_t next_kick_vote_allow_time_ = 0;
- millisecs_t chat_block_time_ = 0;
- millisecs_t last_remove_player_time_ = -99999;
- int next_chat_block_seconds_ = 10;
- friend class Game;
+ millisecs_t next_kick_vote_allow_time_{};
+ millisecs_t chat_block_time_{};
+ millisecs_t last_remove_player_time_{-99999};
+ int next_chat_block_seconds_{10};
};
} // namespace ballistica
diff --git a/src/ballistica/game/connection/connection_to_client_udp.h b/src/ballistica/game/connection/connection_to_client_udp.h
index 357017ed..58c3d045 100644
--- a/src/ballistica/game/connection/connection_to_client_udp.h
+++ b/src/ballistica/game/connection/connection_to_client_udp.h
@@ -20,19 +20,20 @@ class ConnectionToClientUDP : public ConnectionToClient {
~ConnectionToClientUDP() override;
void Update() override;
void HandleGamePacket(const std::vector& buffer) override;
- auto client_name() const -> const std::string& { return client_name_; }
+ auto client_instance_uuid() const { return client_instance_uuid_; }
auto GetAsUDP() -> ConnectionToClientUDP* override;
void RequestDisconnect() override;
-
- protected:
- uint8_t request_id_;
- std::unique_ptr addr_;
- std::string client_name_;
- bool did_die_;
void Die();
void SendDisconnectRequest();
+ auto SendGamePacketCompressed(const std::vector& data)
+ -> void override;
+
+ private:
+ uint8_t request_id_;
+ std::unique_ptr addr_;
+ std::string client_instance_uuid_;
+ bool did_die_;
millisecs_t last_client_response_time_;
- void SendGamePacketCompressed(const std::vector& data) override;
};
} // namespace ballistica
diff --git a/src/ballistica/game/connection/connection_to_host_udp.h b/src/ballistica/game/connection/connection_to_host_udp.h
index d318a8e0..d3fe9cbe 100644
--- a/src/ballistica/game/connection/connection_to_host_udp.h
+++ b/src/ballistica/game/connection/connection_to_host_udp.h
@@ -28,21 +28,20 @@ class ConnectionToHostUDP : public ConnectionToHost {
auto SwitchProtocol() -> bool;
void RequestDisconnect() override;
- protected:
+ void SendGamePacketCompressed(const std::vector& data) override;
+ void Error(const std::string& error_msg) override;
+ void Die();
+ void SendDisconnectRequest();
+
+ private:
+ void GetRequestID();
uint8_t request_id_{};
std::unique_ptr addr_;
bool did_die_{};
- void Die();
- void SendDisconnectRequest();
millisecs_t last_client_id_request_time_{};
millisecs_t last_disconnect_request_time_{};
int client_id_{};
millisecs_t last_host_response_time_{};
- void SendGamePacketCompressed(const std::vector& data) override;
- void Error(const std::string& error_msg) override;
-
- private:
- void GetRequestID();
};
} // namespace ballistica
diff --git a/src/ballistica/game/game.cc b/src/ballistica/game/game.cc
index 6f5d111b..34e618fa 100644
--- a/src/ballistica/game/game.cc
+++ b/src/ballistica/game/game.cc
@@ -396,7 +396,7 @@ void Game::UpdateKickVote() {
kick_vote_in_progress_ = false;
return;
}
- millisecs_t current_time = GetRealTime();
+ millisecs_t current_time{GetRealTime()};
int total_client_count = 0;
int yes_votes = 0;
int no_votes = 0;
@@ -405,8 +405,8 @@ void Game::UpdateKickVote() {
// the update and possibly perform the kick.
for (ConnectionToClient* client : connections()->GetConnectionsToClients()) {
++total_client_count;
- if (client->kick_voted_) {
- if (client->kick_vote_choice_) {
+ if (client->kick_voted()) {
+ if (client->kick_vote_choice()) {
++yes_votes;
} else {
++no_votes;
@@ -437,8 +437,8 @@ void Game::UpdateKickVote() {
if (client == kick_vote_starter) {
delay += kKickVoteFailRetryDelayInitiatorExtra;
}
- client->next_kick_vote_allow_time_ =
- std::max(client->next_kick_vote_allow_time_, current_time + delay);
+ client->set_next_kick_vote_allow_time(
+ std::max(client->next_kick_vote_allow_time(), current_time + delay));
}
} else {
int votes_required;
@@ -1826,26 +1826,6 @@ void Game::CleanUpBeforeConnectingToHost() {
SetPublicPartyEnabled(false);
}
-void Game::PushV1PartyInviteCall(const std::string& name,
- const std::string& invite_id) {
- PushCall([this, name, invite_id] { V1PartyInvite(name, invite_id); });
-}
-
-void Game::V1PartyInvite(const std::string& name,
- const std::string& invite_id) {
- assert(InGameThread());
- g_python->V1PartyInvite(name, invite_id);
-}
-
-void Game::PushV1PartyInviteRevokeCall(const std::string& invite_id) {
- PushCall([this, invite_id] { V1PartyInviteRevoke(invite_id); });
-}
-
-void Game::V1PartyInviteRevoke(const std::string& invite_id) {
- assert(InGameThread());
- g_python->V1PartyInviteRevoke(invite_id);
-}
-
auto Game::GetPartySize() const -> int {
assert(InGameThread());
assert(game_roster_ != nullptr);
@@ -1897,7 +1877,6 @@ auto Game::GetGameRosterMessage() -> std::vector {
// This message is simply a flattened json string of our roster (including
// terminating char).
char* s = cJSON_PrintUnformatted(game_roster_);
- // printf("ROSTER MESSAGE %s\n", s);
auto s_len = strlen(s);
std::vector msg(1 + s_len + 1);
msg[0] = BA_MESSAGE_PARTY_ROSTER;
@@ -1965,13 +1944,13 @@ void Game::StartKickVote(ConnectionToClient* starter,
starter->SendScreenMessage(R"({"r":"kickVoteFailedNotEnoughVotersText",)"
R"("f":"kickVoteFailedText"})",
1, 0, 0);
- } else if (current_time < starter->next_kick_vote_allow_time_) {
+ } else if (current_time < starter->next_kick_vote_allow_time()) {
// Not yet allowed error.
starter->SendScreenMessage(
R"({"r":"voteDelayText","s":[["${NUMBER}",")"
+ std::to_string(std::max(
millisecs_t{1},
- (starter->next_kick_vote_allow_time_ - current_time) / 1000))
+ (starter->next_kick_vote_allow_time() - current_time) / 1000))
+ "\"]]}",
1, 0, 0);
} else {
@@ -2014,10 +1993,10 @@ void Game::StartKickVote(ConnectionToClient* starter,
for (ConnectionToClient* client :
connections()->GetConnectionsToClients()) {
if (client == starter) {
- client->kick_voted_ = true;
- client->kick_vote_choice_ = true;
+ client->set_kick_voted(true);
+ client->set_kick_vote_choice(true);
} else {
- client->kick_voted_ = false;
+ client->set_kick_voted(false);
}
}
}
diff --git a/src/ballistica/game/game.h b/src/ballistica/game/game.h
index a298166a..7e922ded 100644
--- a/src/ballistica/game/game.h
+++ b/src/ballistica/game/game.h
@@ -36,9 +36,6 @@ class Game : public Module {
V1LoginState account_state,
const std::string& account_name,
const std::string& account_id) -> void;
- auto PushV1PartyInviteCall(const std::string& name,
- const std::string& invite_id) -> void;
- auto PushV1PartyInviteRevokeCall(const std::string& invite_id) -> void;
auto PushInitialScreenCreatedCall() -> void;
auto PushApplyConfigCall() -> void;
auto PushRemoveGraphicsServerRenderHoldCall() -> void;
@@ -252,9 +249,6 @@ class Game : public Module {
auto HandleQuitOnIdle() -> void;
auto InitSpecialChars() -> void;
auto Draw() -> void;
- auto V1PartyInvite(const std::string& name, const std::string& invite_id)
- -> void;
- auto V1PartyInviteRevoke(const std::string& invite_id) -> void;
auto InitialScreenCreated() -> void;
auto MainMenuPress(InputDevice* device) -> void;
auto ScreenResize(float virtual_width, float virtual_height,
diff --git a/src/ballistica/generic/utils.cc b/src/ballistica/generic/utils.cc
index 34a736dc..2e9be5b7 100644
--- a/src/ballistica/generic/utils.cc
+++ b/src/ballistica/generic/utils.cc
@@ -408,6 +408,7 @@ auto Utils::PtrToString(const void* val) -> std::string {
return buffer;
}
+// FIXME: This should not live here.
static const char* g_default_random_names[] = {
"Flopsy", "Skippy", "Boomer", "Jolly", "Zeus", "Garth",
"Dizzy", "Mullet", "Ogre", "Ginger", "Nippy", "Murphy",
diff --git a/src/ballistica/platform/apple/platform_apple.h b/src/ballistica/platform/apple/platform_apple.h
index c9d137a8..5cd9ff0b 100644
--- a/src/ballistica/platform/apple/platform_apple.h
+++ b/src/ballistica/platform/apple/platform_apple.h
@@ -16,8 +16,8 @@ namespace ballistica {
class PlatformApple : public Platform {
public:
PlatformApple();
- auto GetDeviceUUIDPrefix() -> std::string override;
- auto GetRealDeviceUUID(std::string* uuid) -> bool override;
+ auto GetDeviceAccountUUIDPrefix() -> std::string override;
+ auto GetRealLegacyDeviceUUID(std::string* uuid) -> bool override;
auto GenerateUUID() -> std::string override;
auto GetDefaultConfigDir() -> std::string override;
auto GetLocale() -> std::string override;
@@ -68,8 +68,6 @@ class PlatformApple : public Platform {
auto MacMusicAppStop() -> void override;
auto MacMusicAppPlayPlaylist(const std::string& playlist) -> bool override;
auto MacMusicAppGetPlaylists() -> std::list override;
- auto StartListeningForWiiRemotes() -> void override;
- auto StopListeningForWiiRemotes() -> void override;
auto IsEventPushMode() -> bool override;
auto ContainsPythonDist() -> bool override;
auto GetPlatformName() -> std::string override;
@@ -79,10 +77,9 @@ class PlatformApple : public Platform {
auto DoClipboardHasText() -> bool override;
auto DoClipboardSetText(const std::string& text) -> void override;
auto DoClipboardGetText() -> std::string override;
+ auto GetPublicDeviceUUIDInputs() -> std::list override;
private:
- // std::mutex log_mutex_;
- // std::string log_line_;
};
} // namespace ballistica
diff --git a/src/ballistica/platform/linux/platform_linux.cc b/src/ballistica/platform/linux/platform_linux.cc
index a126fc8b..18bfb5a8 100644
--- a/src/ballistica/platform/linux/platform_linux.cc
+++ b/src/ballistica/platform/linux/platform_linux.cc
@@ -29,6 +29,26 @@ std::string PlatformLinux::GenerateUUID() {
return val;
}
+auto PlatformLinux::GetPublicDeviceUUIDInputs() -> std::list {
+ std::list out;
+
+ // For now let's just go with machine-id.
+ // Perhaps can add kernel version or something later.
+ char buffer[100];
+ if (FILE* infile = fopen("/etc/machine-id", "r")) {
+ int size = fread(buffer, 1, 99, infile);
+ fclose(infile);
+ if (size < 10) {
+ throw Exception("unexpected machine-id value");
+ }
+ buffer[size] = 0;
+ out.push_back(buffer);
+ } else {
+ throw Exception("/etc/machine-id not accessible");
+ }
+ return out;
+};
+
bool PlatformLinux::DoHasTouchScreen() { return false; }
void PlatformLinux::DoOpenURL(const std::string& url) {
diff --git a/src/ballistica/platform/linux/platform_linux.h b/src/ballistica/platform/linux/platform_linux.h
index bebeefc7..07f09b5b 100644
--- a/src/ballistica/platform/linux/platform_linux.h
+++ b/src/ballistica/platform/linux/platform_linux.h
@@ -13,14 +13,15 @@ namespace ballistica {
class PlatformLinux : public Platform {
public:
PlatformLinux();
- std::string GetDeviceUUIDPrefix() override { return "l"; }
- std::string GenerateUUID() override;
- bool DoHasTouchScreen() override;
- void DoOpenURL(const std::string& url) override;
- void OpenFileExternally(const std::string& path) override;
- void OpenDirExternally(const std::string& path) override;
- std::string GetPlatformName() override;
- std::string GetSubplatformName() override;
+ auto GetDeviceAccountUUIDPrefix() -> std::string override { return "l"; }
+ auto GenerateUUID() -> std::string override;
+ auto DoHasTouchScreen() -> bool override;
+ auto DoOpenURL(const std::string& url) -> void override;
+ auto OpenFileExternally(const std::string& path) -> void override;
+ auto OpenDirExternally(const std::string& path) -> void override;
+ auto GetPlatformName() -> std::string override;
+ auto GetSubplatformName() -> std::string override;
+ auto GetPublicDeviceUUIDInputs() -> std::list override;
};
} // namespace ballistica
diff --git a/src/ballistica/platform/platform.cc b/src/ballistica/platform/platform.cc
index 6fba02cd..5032a513 100644
--- a/src/ballistica/platform/platform.cc
+++ b/src/ballistica/platform/platform.cc
@@ -110,33 +110,27 @@ auto Platform::Create() -> Platform* {
return platform;
}
-void Platform::FinalCleanup() {
- if (g_app_globals->temp_cleanup_callback) {
- g_app_globals->temp_cleanup_callback();
- }
-}
-
Platform::Platform() : starttime_(GetCurrentMilliseconds()) {}
auto Platform::PostInit() -> void {}
Platform::~Platform() = default;
-auto Platform::GetUniqueDeviceIdentifier() -> const std::string& {
+auto Platform::GetLegacyDeviceUUID() -> const std::string& {
if (!have_device_uuid_) {
- device_uuid_ = GetDeviceUUIDPrefix();
+ legacy_device_uuid_ = GetDeviceAccountUUIDPrefix();
std::string real_unique_uuid;
- bool have_real_unique_uuid = GetRealDeviceUUID(&real_unique_uuid);
+ bool have_real_unique_uuid = GetRealLegacyDeviceUUID(&real_unique_uuid);
if (have_real_unique_uuid) {
- device_uuid_ += real_unique_uuid;
+ legacy_device_uuid_ += real_unique_uuid;
}
// Keep demo/arcade uuids unique.
if (g_buildconfig.demo_build()) {
- device_uuid_ += "_d";
+ legacy_device_uuid_ += "_d";
} else if (g_buildconfig.arcade_build()) {
- device_uuid_ += "_a";
+ legacy_device_uuid_ += "_a";
}
// Ok, as a fallback on platforms where we don't yet have a way to get a
@@ -153,13 +147,13 @@ auto Platform::GetUniqueDeviceIdentifier() -> const std::string& {
if (size >= 0) {
assert(size < 100);
buffer[size] = 0;
- device_uuid_ += buffer;
+ legacy_device_uuid_ += buffer;
}
fclose(f);
} else {
// No existing one; generate it.
std::string val = GenerateUUID();
- device_uuid_ += val;
+ legacy_device_uuid_ += val;
if (FILE* f2 = FOpen(path.c_str(), "wb")) {
size_t result = fwrite(val.c_str(), val.size(), 1, f2);
if (result != 1) Log("unable to write bsuuid file.");
@@ -171,20 +165,50 @@ auto Platform::GetUniqueDeviceIdentifier() -> const std::string& {
}
have_device_uuid_ = true;
}
- return device_uuid_;
+ return legacy_device_uuid_;
}
-auto Platform::GetDeviceUUIDPrefix() -> std::string {
- Log("GetDeviceUUIDPrefix() unimplemented");
+auto Platform::GetDeviceAccountUUIDPrefix() -> std::string {
+ Log("GetDeviceAccountUUIDPrefix() unimplemented");
return "u";
}
-auto Platform::GetRealDeviceUUID(std::string* uuid) -> bool { return false; }
+auto Platform::GetRealLegacyDeviceUUID(std::string* uuid) -> bool {
+ return false;
+}
auto Platform::GenerateUUID() -> std::string {
throw Exception("GenerateUUID() unimplemented");
}
+auto Platform::GetPublicDeviceUUID() -> std::string {
+ assert(g_python);
+ if (public_device_uuid_.empty()) {
+ std::list inputs{GetPublicDeviceUUIDInputs()};
+
+ // This UUID is supposed to change periodically, so let's plug in
+ // some stuff to enforce that.
+ inputs.emplace_back(GetOSVersionString());
+ inputs.emplace_back(kAppVersion);
+ inputs.emplace_back("kerploople");
+ // int i{};
+ // for (auto&& input : inputs) {
+ // printf("INPUT %d IS %s\n", i + 1, input.c_str());
+ // }
+ auto gil{Python::ScopedInterpreterLock()};
+ auto pylist{g_python->StringList(inputs)};
+ auto args{g_python->SingleMemberTuple(pylist)};
+ auto result = g_python->obj(Python::ObjID::kHashStringsCall).Call(args);
+ assert(result.UnicodeCheck());
+ public_device_uuid_ = result.Str();
+ }
+ return public_device_uuid_;
+}
+
+auto Platform::GetPublicDeviceUUIDInputs() -> std::list {
+ throw Exception("GetPublicDeviceUUIDInputs unimplemented");
+}
+
auto Platform::GetDefaultConfigDir() -> std::string {
std::string config_dir;
// As a default, look for a HOME env var and use that if present
@@ -301,7 +325,7 @@ auto Platform::GetReplaysDir() -> std::string {
// rename() supporting UTF8 strings.
auto Platform::Rename(const char* oldname, const char* newname) -> int {
- // this covers non-windows platforms
+ // This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -310,7 +334,7 @@ auto Platform::Rename(const char* oldname, const char* newname) -> int {
}
auto Platform::Remove(const char* path) -> int {
- // this covers non-windows platforms
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -320,7 +344,7 @@ auto Platform::Remove(const char* path) -> int {
// stat() supporting UTF8 strings.
auto Platform::Stat(const char* path, struct BA_STAT* buffer) -> int {
- // this covers non-windows platforms
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -330,7 +354,7 @@ auto Platform::Stat(const char* path, struct BA_STAT* buffer) -> int {
// fopen() supporting UTF8 strings.
auto Platform::FOpen(const char* path, const char* mode) -> FILE* {
- // this covers non-windows platforms
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -349,12 +373,12 @@ auto Platform::GetSocketErrorString() -> std::string {
}
auto Platform::GetSocketError() -> int {
- // by default this is simply errno
+ // By default this is simply errno.
return errno;
}
auto Platform::GetErrnoString() -> std::string {
- // this covers non-windows platforms
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#elif BA_OSTYPE_LINUX
@@ -419,7 +443,7 @@ auto Platform::DoGetUserPythonDirectory() -> std::string {
}
void Platform::DoMakeDir(const std::string& dir, bool quiet) {
- // Default case here covers all non-windows platforms.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -740,7 +764,7 @@ auto Platform::BlockingFatalErrorDialog(const std::string& message) -> void {
}
void Platform::SetupDataDirectory() {
-// This covers non-windows cases.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -763,7 +787,7 @@ void Platform::SetupDataDirectory() {
}
void Platform::SetEnv(const std::string& name, const std::string& value) {
-// This covers non-windows cases.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -784,7 +808,7 @@ auto Platform::IsStdinATerminal() -> bool {
#endif
}
-auto Platform::GetOSVersionString() -> std::string { return ""; }
+auto Platform::GetOSVersionString() -> std::string { return "?"; }
auto Platform::GetUserAgentString() -> std::string {
std::string device = GetDeviceName();
@@ -843,7 +867,7 @@ auto Platform::GetUserAgentString() -> std::string {
}
auto Platform::GetCWD() -> std::string {
-// Covers non-windows cases.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -931,15 +955,15 @@ void Platform::AndroidQuitActivity() {
auto Platform::GetDeviceAccountID() -> std::string {
if (HeadlessMode()) {
- return "S-" + GetUniqueDeviceIdentifier();
+ return "S-" + GetLegacyDeviceUUID();
}
// Everything else is just considered a 'local' account, though we may
// give unique ids for unique builds..
if (g_buildconfig.iircade_build()) {
- return "L-iRc" + GetUniqueDeviceIdentifier();
+ return "L-iRc" + GetLegacyDeviceUUID();
}
- return "L-" + GetUniqueDeviceIdentifier();
+ return "L-" + GetLegacyDeviceUUID();
}
auto Platform::DemangleCXXSymbol(const std::string& s) -> std::string {
@@ -970,17 +994,6 @@ auto Platform::NewAutoReleasePool() -> void* { throw Exception(); }
void Platform::DrainAutoReleasePool(void* pool) { throw Exception(); }
-auto Platform::AndroidGPGSNewConnectionToClient(int id) -> ConnectionToClient* {
- throw Exception();
-}
-auto Platform::AndroidGPGSNewConnectionToHost() -> ConnectionToHost* {
- throw Exception();
-}
-
-auto Platform::AndroidIsGPGSConnectionToClient(ConnectionToClient* c) -> bool {
- throw Exception();
-}
-
void Platform::OpenURL(const std::string& url) {
// Can't open URLs in VR - just tell the game thread to show the url.
if (IsVRMode()) {
@@ -1064,18 +1077,6 @@ auto Platform::GetHasVideoAds() -> bool {
return GetHasAds();
}
-void Platform::AndroidGPGSPartyInvitePlayers() {
- Log("AndroidGPGSPartyInvitePlayers() unimplemented");
-}
-
-void Platform::AndroidGPGSPartyShowInvites() {
- Log("AndroidGPGSPartyShowInvites() unimplemented");
-}
-
-void Platform::AndroidGPGSPartyInviteAccept(const std::string& invite_id) {
- Log("AndroidGPGSPartyInviteAccept() unimplemented");
-}
-
void Platform::SignIn(const std::string& account_type) {
Log("SignIn() unimplemented");
}
@@ -1140,14 +1141,6 @@ auto Platform::MacMusicAppGetPlaylists() -> std::list {
return {};
}
-void Platform::StartListeningForWiiRemotes() {
- Log("StartListeningForWiiRemotes() unimplemented");
-}
-
-void Platform::StopListeningForWiiRemotes() {
- Log("StopListeningForWiiRemotes() unimplemented");
-}
-
void Platform::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).
@@ -1162,7 +1155,7 @@ void Platform::SetCurrentThreadName(const std::string& name) {
}
void Platform::Unlink(const char* path) {
- // This covers all but windows.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -1199,7 +1192,7 @@ auto Platform::IsEventPushMode() -> bool { return false; }
auto Platform::GetDisplayResolution(int* x, int* y) -> bool { return false; }
void Platform::CloseSocket(int socket) {
-// This covers all but windows.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -1207,18 +1200,8 @@ void Platform::CloseSocket(int socket) {
#endif
}
-auto Platform::SocketPair(int domain, int type, int protocol, int socks[2])
- -> int {
- // This covers all but windows.
-#if BA_OSTYPE_WINDOWS
- throw Exception();
-#else
- return socketpair(domain, type, protocol, socks);
-#endif
-}
-
auto Platform::GetBroadcastAddrs() -> std::vector {
-// This covers all but windows.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -1252,7 +1235,7 @@ auto Platform::GetBroadcastAddrs() -> std::vector {
}
auto Platform::SetSocketNonBlocking(int sd) -> bool {
-// This covers all but windows.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
@@ -1363,7 +1346,7 @@ static void HandleSIGINT(int s) {
#endif
void Platform::SetupInterruptHandling() {
- // For non-windows platforms, set up posix-y SIGINT handling.
+// This default implementation covers non-windows platforms.
#if BA_OSTYPE_WINDOWS
throw Exception();
#else
diff --git a/src/ballistica/platform/platform.h b/src/ballistica/platform/platform.h
index 7f68738f..e8a130fe 100644
--- a/src/ballistica/platform/platform.h
+++ b/src/ballistica/platform/platform.h
@@ -15,12 +15,12 @@ namespace ballistica {
/// For capturing and printing stack-traces and related errors.
/// Platforms should subclass this and return instances in GetStackTrace().
+/// Stack trace classes should capture the stack state immediately upon
+/// construction but should do the bare minimum amount of work to store it.
+/// Any expensive operations such as symbolification should be deferred until
+/// GetDescription().
class PlatformStackTrace {
public:
- // The stack trace should capture the stack state immediately upon
- // construction but should do the bare minimum amount of work to store it. Any
- // expensive operations such as symbolification should be deferred until
- // GetDescription().
virtual ~PlatformStackTrace() = default;
// Return a human readable version of the trace (with symbolification if
@@ -32,9 +32,9 @@ class PlatformStackTrace {
virtual auto copy() const noexcept -> PlatformStackTrace* = 0;
};
-// This class attempts to abstract away most platform-specific functionality.
-// Ideally we should need to pull in no platform-specific system headers outside
-// of the platform*.cc files and can just go through this.
+/// This class attempts to abstract away most platform-specific functionality.
+/// Ideally we should need to pull in no platform-specific system headers
+/// outside of the platform*.cc files and can just go through this.
class Platform {
public:
static auto Create() -> Platform*;
@@ -49,60 +49,58 @@ class Platform {
virtual auto PostInit() -> void;
/// Create the proper App module and add it to the main_thread.
- void CreateApp();
+ auto CreateApp() -> void;
/// Create the appropriate Graphics subclass for the app.
- Graphics* CreateGraphics();
+ auto CreateGraphics() -> Graphics*;
- virtual void CreateAuxiliaryModules();
- virtual void WillExitMain(bool errored);
+ virtual auto CreateAuxiliaryModules() -> void;
+ virtual auto WillExitMain(bool errored) -> void;
- // Inform the platform that all subsystems are up and running and it can
- // start talking to them.
- virtual void OnBootstrapComplete();
+ /// Inform the platform that all subsystems are up and running and it can
+ /// start talking to them.
+ virtual auto OnBootstrapComplete() -> void;
// Get/set values before standard game settings are available
// (for values needed before SDL init/etc).
// FIXME: We should have some sort of 'bootconfig.json' file for these.
- // (or simply read the regular config in via c++ immediately)
+ // (or simply read the regular config in via c++ immediately)
auto GetLowLevelConfigValue(const char* key, int default_value) -> int;
- void SetLowLevelConfigValue(const char* key, int value);
+ auto SetLowLevelConfigValue(const char* key, int value) -> void;
- // Called when the app config is being read/applied.
- virtual void ApplyConfig();
+ /// Called when the app config is being read/applied.
+ virtual auto ApplyConfig() -> void;
- // Called when the app should set itself up to intercept ctrl-c presses.
- virtual void SetupInterruptHandling();
-
- void FinalCleanup();
+ /// Called when the app should set itself up to intercept ctrl-c presses.
+ virtual auto SetupInterruptHandling() -> void;
#pragma mark FILES -------------------------------------------------------------
- // remove() support UTF8 strings.
+ /// remove() support UTF8 strings.
virtual auto Remove(const char* path) -> int;
- // stat() supporting UTF8 strings.
+ /// stat() supporting UTF8 strings.
virtual auto Stat(const char* path, struct BA_STAT* buffer) -> int;
- // fopen() supporting UTF8 strings.
+ /// fopen() supporting UTF8 strings.
virtual auto FOpen(const char* path, const char* mode) -> FILE*;
- // rename() supporting UTF8 strings.
- // For cross-platform consistency, this should also remove any file that
- // exists at the target location first.
+ /// rename() supporting UTF8 strings.
+ /// For cross-platform consistency, this should also remove any file that
+ /// exists at the target location first.
virtual auto Rename(const char* oldname, const char* newname) -> int;
- // Simple cross-platform check for existence of a file.
+ /// Simple cross-platform check for existence of a file.
auto FilePathExists(const std::string& name) -> bool;
/// Attempt to make a directory; raise an Exception if unable,
/// unless quiet is true.
- void MakeDir(const std::string& dir, bool quiet = false);
+ auto MakeDir(const std::string& dir, bool quiet = false) -> void;
- // Return the current working directory.
+ /// Return the current working directory.
virtual auto GetCWD() -> std::string;
- // Unlink a file.
+ /// Unlink a file.
virtual auto Unlink(const char* path) -> void;
/// Return the absolute path for the provided path. Note that this requires
@@ -132,7 +130,7 @@ class Platform {
// Send a message to the default platform handler.
// IMPORTANT: No Object::Refs should be created or destroyed within this call,
// or deadlock can occur.
- virtual void HandleLog(const std::string& msg);
+ virtual auto HandleLog(const std::string& msg) -> void;
#pragma mark ENVIRONMENT -------------------------------------------------------
@@ -150,15 +148,6 @@ class Platform {
// Return the interface type based on the environment (phone, tablet, etc).
virtual auto GetUIScale() -> UIScale;
- // Return a string *reasonably* likely to be unique and consistent for this
- // device. Do not assume this is globally unique and *do not* assume that it
- // will never ever change (hardware upgrades may affect it, etc).
- // IMPORTANT: This value should NEVER be sent over the wire to peers.
- virtual auto GetUniqueDeviceIdentifier() -> const std::string&;
-
- // Returns the ID to use for the device account
- auto GetDeviceAccountID() -> std::string;
-
auto GetConfigDirectory() -> std::string;
auto GetConfigFilePath() -> std::string;
auto GetUserPythonDirectory() -> std::string;
@@ -176,36 +165,62 @@ class Platform {
/// Raises an exception on errors.
virtual void SetEnv(const std::string& name, const std::string& value);
- // Are we being run from a terminal? (should we show prompts, etc?).
+ /// Are we being run from a terminal? (should we show prompts, etc?).
virtual auto IsStdinATerminal() -> bool;
- // Return hostname or other id suitable for network searches, etc.
+ /// Return hostname or other id suitable for displaying in network search
+ /// results, etc.
auto GetDeviceName() -> std::string;
- // Are we running on a tv?
+ /// Get a UUID for use with things like device-accounts. This function
+ /// should not be used for other purposes, should not be modified, and
+ /// eventually should go away after device accounts are phased out.
+ /// Also, this value should never be shared beyond the local device.
+ auto GetLegacyDeviceUUID() -> const std::string&;
+
+ /// Get a UUID for the current device that is meant to be publicly shared.
+ /// This value will change occasionally due to OS updates, app updates, or
+ /// other factors, so it can not be used as a permanent identifier, but it
+ /// should remain constant over short periods and should not be easily
+ /// changeable by the user, making it useful for purposes such as temporary
+ /// server bans or spam prevention.
+ auto GetPublicDeviceUUID() -> std::string;
+
+ /// Return values which will be hashed to create a public device uuid.
+ /// These values may include things that may change periodically such
+ /// as minor os version numbers, but they should not include things
+ /// that change constantly or that can be changed easily by the user.
+ /// Only hashed versions of these values should ever be shared beyond
+ /// the local device.
+ virtual auto GetPublicDeviceUUIDInputs() -> std::list;
+
+ /// Return whether there is an actual legacy-device-uuid value for
+ /// this platform, and also return it if so.
+ virtual auto GetRealLegacyDeviceUUID(std::string* uuid) -> bool;
+
+ /// Are we running on a tv?
virtual auto IsRunningOnTV() -> bool;
- // Are we on a daydream enabled android device?
+ /// Are we on a daydream-enabled Android device?
virtual auto IsRunningOnDaydream() -> bool;
- // Do we have touchscreen hardware?
+ /// Do we have touchscreen hardware?
auto HasTouchScreen() -> bool;
- // Are we running on a desktop setup in general?
+ /// Are we running on a desktop setup in general?
virtual auto IsRunningOnDesktop() -> bool;
- // Are we running on fireTV hardware?
+ /// Are we running on fireTV hardware?
virtual auto IsRunningOnFireTV() -> bool;
- // Return the external storage path (currently only relevant on android).
+ /// Return the external storage path (currently only relevant on Android).
virtual auto GetExternalStoragePath() -> std::string;
// For enabling some special hardware optimizations for nvidia.
auto is_tegra_k1() const -> bool { return is_tegra_k1_; }
- void set_is_tegra_k1(bool val) { is_tegra_k1_ = val; }
+ auto set_is_tegra_k1(bool val) -> void { is_tegra_k1_ = val; }
- // Return true if this platform includes its own python distribution
- // (defaults to false).
+ /// Return whether this platform includes its own Python distribution
virtual auto ContainsPythonDist() -> bool;
#pragma mark INPUT DEVICES -----------------------------------------------------
@@ -215,32 +230,26 @@ class Platform {
#pragma mark IN APP PURCHASES --------------------------------------------------
- virtual void Purchase(const std::string& item);
+ virtual auto Purchase(const std::string& item) -> void;
- // Restore purchases (currently only relevant on apple platforms).
- virtual void RestorePurchases();
+ // Restore purchases (currently only relevant on Apple platforms).
+ virtual auto RestorePurchases() -> void;
- // purchase ack'ed by the master-server (so can consume)
- virtual void PurchaseAck(const std::string& purchase,
- const std::string& order_id);
+ // Purchase was ack'ed by the master-server (so can consume).
+ virtual auto PurchaseAck(const std::string& purchase,
+ const std::string& order_id) -> void;
#pragma mark ANDROID -----------------------------------------------------------
virtual auto GetAndroidExecArg() -> std::string;
- virtual void AndroidSetResString(const std::string& res);
- virtual auto AndroidIsGPGSConnectionToClient(ConnectionToClient* c) -> bool;
- virtual auto AndroidGPGSNewConnectionToClient(int id) -> ConnectionToClient*;
- virtual auto AndroidGPGSNewConnectionToHost() -> ConnectionToHost*;
- virtual void AndroidSynthesizeBackPress();
- virtual void AndroidQuitActivity();
- virtual void AndroidShowAppInvite(const std::string& title,
+ virtual auto AndroidSetResString(const std::string& res) -> void;
+ virtual auto AndroidSynthesizeBackPress() -> void;
+ virtual auto AndroidQuitActivity() -> void;
+ virtual auto AndroidShowAppInvite(const std::string& title,
const std::string& message,
- const std::string& code);
- virtual void AndroidRefreshFile(const std::string& file);
- virtual void AndroidGPGSPartyInvitePlayers();
- virtual void AndroidGPGSPartyShowInvites();
- virtual void AndroidGPGSPartyInviteAccept(const std::string& invite_id);
- virtual void AndroidShowWifiSettings();
+ const std::string& code) -> void;
+ virtual auto AndroidRefreshFile(const std::string& file) -> void;
+ virtual auto AndroidShowWifiSettings() -> void;
#pragma mark PERMISSIONS -------------------------------------------------------
@@ -249,7 +258,7 @@ class Platform {
/// then this may also present a message or pop-up instructing the user how
/// to manually grant the permission (up to individual platforms to
/// implement).
- virtual void RequestPermission(Permission p);
+ virtual auto RequestPermission(Permission p) -> void;
/// Returns true if this permission has been granted (or if asking is not
/// required for it).
@@ -257,24 +266,26 @@ class Platform {
#pragma mark ANALYTICS ---------------------------------------------------------
- virtual void SetAnalyticsScreen(const std::string& screen);
- virtual void IncrementAnalyticsCount(const std::string& name, int increment);
- virtual void IncrementAnalyticsCountRaw(const std::string& name,
- int increment);
- virtual void IncrementAnalyticsCountRaw2(const std::string& name,
- int uses_increment, int increment);
- virtual void SubmitAnalyticsCounts();
+ virtual auto SetAnalyticsScreen(const std::string& screen) -> void;
+ virtual auto IncrementAnalyticsCount(const std::string& name, int increment)
+ -> void;
+ virtual auto IncrementAnalyticsCountRaw(const std::string& name,
+ int increment) -> void;
+ virtual auto IncrementAnalyticsCountRaw2(const std::string& name,
+ int uses_increment, int increment)
+ -> void;
+ virtual auto SubmitAnalyticsCounts() -> void;
#pragma mark APPLE -------------------------------------------------------------
virtual auto NewAutoReleasePool() -> void*;
- virtual void DrainAutoReleasePool(void* pool);
+ virtual auto DrainAutoReleasePool(void* pool) -> void;
// FIXME: Can we consolidate these with the general music playback calls?
- virtual void MacMusicAppInit();
+ virtual auto MacMusicAppInit() -> void;
virtual auto MacMusicAppGetVolume() -> int;
- virtual void MacMusicAppSetVolume(int volume);
- virtual void MacMusicAppGetLibrarySource();
- virtual void MacMusicAppStop();
+ virtual auto MacMusicAppSetVolume(int volume) -> void;
+ virtual auto MacMusicAppGetLibrarySource() -> void;
+ virtual auto MacMusicAppStop() -> void;
virtual auto MacMusicAppPlayPlaylist(const std::string& playlist) -> bool;
virtual auto MacMusicAppGetPlaylists() -> std::list;
@@ -282,9 +293,9 @@ class Platform {
// Set bounds/width info for a bit of text.
// (will only be called in BA_ENABLE_OS_FONT_RENDERING is set)
- virtual void GetTextBoundsAndWidth(const std::string& text, Rect* r,
- float* width);
- virtual void FreeTextTexture(void* tex);
+ virtual auto GetTextBoundsAndWidth(const std::string& text, Rect* r,
+ float* width) -> void;
+ virtual auto FreeTextTexture(void* tex) -> void;
virtual auto CreateTextTexture(int width, int height,
const std::vector& strings,
const std::vector& positions,
@@ -296,21 +307,28 @@ class Platform {
virtual auto SignIn(const std::string& account_type) -> void;
virtual auto SignOut() -> void;
+
virtual auto GameCenterLogin() -> void;
virtual auto LoginDidChange() -> void;
+ /// Returns the ID to use for the device account.
+ auto GetDeviceAccountID() -> std::string;
+
+ /// Return the prefix to use for device-account ids on this platform.
+ virtual auto GetDeviceAccountUUIDPrefix() -> std::string;
+
#pragma mark MUSIC PLAYBACK ----------------------------------------------------
- // FIXME: currently these are wired up on android; need to generalize
+ // FIXME: currently these are wired up on Android; need to generalize
// to support mac/itunes or other music player types.
- virtual void MusicPlayerPlay(PyObject* target);
- virtual void MusicPlayerStop();
- virtual void MusicPlayerShutdown();
- virtual void MusicPlayerSetVolume(float volume);
+ virtual auto MusicPlayerPlay(PyObject* target) -> void;
+ virtual auto MusicPlayerStop() -> void;
+ virtual auto MusicPlayerShutdown() -> void;
+ virtual auto MusicPlayerSetVolume(float volume) -> void;
#pragma mark ADS ---------------------------------------------------------------
- virtual void ShowAd(const std::string& purpose);
+ virtual auto ShowAd(const std::string& purpose) -> void;
// Return whether we have the ability to show *any* ads.
virtual auto GetHasAds() -> bool;
@@ -327,62 +345,60 @@ class Platform {
virtual auto ConvertIncomingLeaderboardScore(
const std::string& leaderboard_id, int score) -> int;
- virtual void GetFriendScores(const std::string& game,
+ virtual auto GetFriendScores(const std::string& game,
const std::string& game_version,
- void* py_callback);
- virtual void SubmitScore(const std::string& game, const std::string& version,
- int64_t score);
- virtual void ReportAchievement(const std::string& achievement);
+ void* py_callback) -> void;
+ virtual auto SubmitScore(const std::string& game, const std::string& version,
+ int64_t score) -> void;
+ virtual auto ReportAchievement(const std::string& achievement) -> void;
virtual auto HaveLeaderboard(const std::string& game,
const std::string& config) -> bool;
- virtual void ShowOnlineScoreUI(const std::string& show,
+ virtual auto ShowOnlineScoreUI(const std::string& show,
const std::string& game,
- const std::string& game_version);
- virtual void ResetAchievements();
+ const std::string& game_version) -> void;
+ virtual auto ResetAchievements() -> void;
#pragma mark NETWORKING --------------------------------------------------------
- virtual void CloseSocket(int socket);
- virtual auto SocketPair(int domain, int type, int protocol, int socks[2])
- -> int;
+ virtual auto CloseSocket(int socket) -> void;
virtual auto GetBroadcastAddrs() -> std::vector;
virtual auto SetSocketNonBlocking(int sd) -> bool;
#pragma mark ERRORS & DEBUGGING ------------------------------------------------
- // Should return a subclass of PlatformStackTrace allocated via new.
- // Platforms with no meaningful stack trace functionality can return nullptr.
+ /// Should return a subclass of PlatformStackTrace allocated via new.
+ /// Platforms with no meaningful stack trace functionality can return nullptr.
virtual auto GetStackTrace() -> PlatformStackTrace*;
// Called during stress testing.
virtual auto GetMemUsageInfo() -> std::string;
- // Optionally override fatal error reporting. If true is returned, default
- // fatal error reporting will not run.
+ /// Optionally override fatal error reporting. If true is returned, default
+ /// fatal error reporting will not run.
virtual auto ReportFatalError(const std::string& message,
bool in_top_level_exception_handler) -> bool;
- // Optionally override fatal error handling. If true is returned, default
- // fatal error handling will not run.
+ /// Optionally override fatal error handling. If true is returned, default
+ /// fatal error handling will not run.
virtual auto HandleFatalError(bool exit_cleanly,
bool in_top_level_exception_handler) -> bool;
- // If this platform has the ability to show a blocking dialog on the main
- // thread for fatal errors, return true here.
+ /// If this platform has the ability to show a blocking dialog on the main
+ /// thread for fatal errors, return true here.
virtual auto CanShowBlockingFatalErrorDialog() -> bool;
- // Called on the main thread when a fatal error occurs.
- // Will only be called if CanShowBlockingFatalErrorDialog() is true.
+ /// Called on the main thread when a fatal error occurs.
+ /// Will only be called if CanShowBlockingFatalErrorDialog() is true.
virtual auto BlockingFatalErrorDialog(const std::string& message) -> void;
- // Use this instead of looking at errno (translates winsock errors to errno).
+ /// Use this instead of looking at errno (translates winsock errors to errno).
virtual auto GetSocketError() -> int;
- // Return a string for the current value of errno.
+ /// Return a string for the current value of errno.
virtual auto GetErrnoString() -> std::string;
- // Return a description of errno (unix) or WSAGetLastError() (windows).
+ /// Return a description of errno (unix) or WSAGetLastError() (windows).
virtual auto GetSocketErrorString() -> std::string;
/// Set a key to be included in crash logs or other debug cases.
@@ -426,60 +442,58 @@ class Platform {
static auto GetCurrentMilliseconds() -> millisecs_t;
static auto GetCurrentSeconds() -> int64_t;
- static void SleepMS(millisecs_t ms);
+ static auto SleepMS(millisecs_t ms) -> void;
- // Pop up a text edit dialog.
- virtual void EditText(const std::string& title, const std::string& value,
- int max_chars);
+ /// Pop up a text edit dialog.
+ virtual auto EditText(const std::string& title, const std::string& value,
+ int max_chars) -> void;
- // Open the provided URL in a browser or whatnot.
- void OpenURL(const std::string& url);
+ /// Open the provided URL in a browser or whatnot.
+ auto OpenURL(const std::string& url) -> void;
+
+ /// Given a C++ symbol, attempt to return a pretty one.
virtual auto DemangleCXXSymbol(const std::string& s) -> std::string;
- // Called each time through the main event loop; for custom pumping/handling.
- virtual void RunEvents();
+ /// Called each time through the main event loop;
+ /// for custom pumping/handling.
+ virtual auto RunEvents() -> void;
- // Called when the app module is pausing.
- // Note: only app-thread (main thread) stuff should happen here.
- // (don't push calls to other threads/etc).
- virtual void OnAppPause();
+ /// Called when the app module is pausing.
+ /// Note: only app-thread (main thread) stuff should happen here.
+ /// (don't push calls to other threads/etc).
+ virtual auto OnAppPause() -> void;
- // Called when the app module is resuming.
- virtual void OnAppResume();
+ /// Called when the app module is resuming.
+ virtual auto OnAppResume() -> void;
- // Is the OS currently playing music? (so we can avoid doing so).
+ /// Is the OS currently playing music? (so we can avoid doing so).
virtual auto IsOSPlayingMusic() -> bool;
- // Pass platform-specific misc-read-vals along to the OS (as a json string).
- virtual void SetPlatformMiscReadVals(const std::string& vals);
+ /// Pass platform-specific misc-read-vals along to the OS (as a json string).
+ virtual auto SetPlatformMiscReadVals(const std::string& vals) -> void;
- // Show/hide the hardware cursor.
- virtual void SetHardwareCursorVisible(bool visible);
+ /// Show/hide the hardware cursor.
+ virtual auto SetHardwareCursorVisible(bool visible) -> void;
- // Get the most up-to-date cursor position.
- virtual void GetCursorPosition(float* x, float* y);
+ /// Get the most up-to-date cursor position.
+ virtual auto GetCursorPosition(float* x, float* y) -> void;
- // Quit the app (can be immediate or via posting some high level event).
- virtual void QuitApp();
+ /// Quit the app (can be immediate or via posting some high level event).
+ virtual auto QuitApp() -> void;
- // Do we want to deprecate this?...
- virtual void GetScoresToBeat(const std::string& level,
- const std::string& config, void* py_callback);
+ // Note to self: do we want to deprecate this?...
+ virtual auto GetScoresToBeat(const std::string& level,
+ const std::string& config, void* py_callback)
+ -> void;
- // Open a file using the system default method (in another app, etc.)
- virtual void OpenFileExternally(const std::string& path);
+ /// Open a file using the system default method (in another app, etc.)
+ virtual auto OpenFileExternally(const std::string& path) -> void;
- // Open a directory using the system default method (Finder, etc.)
- virtual void OpenDirExternally(const std::string& path);
+ /// Open a directory using the system default method (Finder, etc.)
+ virtual auto OpenDirExternally(const std::string& path) -> void;
- // Currently mac-only (could be generalized though).
- virtual void StartListeningForWiiRemotes();
-
- // Currently mac-only (could be generalized though).
- virtual void StopListeningForWiiRemotes();
-
- // Set the name of the current thread (for debugging).
- virtual void SetCurrentThreadName(const std::string& name);
+ /// Set the name of the current thread (for debugging).
+ virtual auto SetCurrentThreadName(const std::string& name) -> void;
// If display-resolution can be directly set on this platform,
// return true and set the native full res here. Otherwise return false;
@@ -490,36 +504,32 @@ class Platform {
}
protected:
- // Open the provided URL in a browser or whatnot.
- virtual void DoOpenURL(const std::string& url);
+ /// Open the provided URL in a browser or whatnot.
+ virtual auto DoOpenURL(const std::string& url) -> void;
- // Called once per platform to determine touchscreen presence.
+ /// Called once per platform to determine touchscreen presence.
virtual auto DoHasTouchScreen() -> bool;
+
+ /// Platforms should override this to provide device name.
virtual auto DoGetDeviceName() -> std::string;
- // Attempt to actually create a directory.
- // Should not except if it already exists or if quiet is true.
- virtual void DoMakeDir(const std::string& dir, bool quiet);
+ /// Attempt to actually create a directory.
+ /// Should not raise Exceptions if it already exists or
+ /// if quiet is true.
+ virtual auto DoMakeDir(const std::string& dir, bool quiet) -> void;
- // Attempt to actually get an abs path. This will only be called if
- // the path is valid and exists.
+ /// Attempt to actually get an abs path. This will only be called if
+ /// the path is valid and exists.
virtual auto DoAbsPath(const std::string& path, std::string* outpath) -> bool;
- // Calc the user scripts dir path for this platform.
- // This will be called once and the path cached.
+ /// Calc the user scripts dir path for this platform.
+ /// This will be called once and the path cached.
virtual auto DoGetUserPythonDirectory() -> std::string;
- // Return the default config directory for this platform.
+ /// Return the default config directory for this platform.
virtual auto GetDefaultConfigDir() -> std::string;
- // Return the prefix to use for device UUIDs on this platform.
- virtual auto GetDeviceUUIDPrefix() -> std::string;
-
- // Return whether there is an actual unique UUID available for this platform,
- // and also return it if so.
- virtual auto GetRealDeviceUUID(std::string* uuid) -> bool;
-
- // Generate a random UUID string.
+ /// Generate a random UUID string.
virtual auto GenerateUUID() -> std::string;
virtual auto DoClipboardIsSupported() -> bool;
@@ -537,13 +547,14 @@ class Platform {
bool have_clipboard_is_supported_{};
bool clipboard_is_supported_{};
millisecs_t starttime_{};
- std::string device_uuid_;
+ std::string legacy_device_uuid_;
bool have_device_uuid_{};
std::string config_dir_;
std::string user_scripts_dir_;
std::string app_python_dir_;
std::string site_python_dir_;
std::string replays_dir_;
+ std::string public_device_uuid_;
};
} // namespace ballistica
diff --git a/src/ballistica/platform/sdl/sdl_app.cc b/src/ballistica/platform/sdl/sdl_app.cc
index 69dea3b3..42bdb72a 100644
--- a/src/ballistica/platform/sdl/sdl_app.cc
+++ b/src/ballistica/platform/sdl/sdl_app.cc
@@ -325,7 +325,7 @@ SDLApp::SDLApp(Thread* thread) : App(thread) {
// SDL events the moment they're generated and we process them immediately.
// This way we don't have to poll for events and can be purely callback-based,
// which fits in nicely with most modern event models.
- if (!UsesEventLoop()) {
+ if (!ManagesEventLoop()) {
#if BA_SDL2_BUILD
SDL_SetEventFilter(FilterSDL2Event, nullptr);
#else
diff --git a/src/ballistica/platform/windows/platform_windows.cc b/src/ballistica/platform/windows/platform_windows.cc
index 2948c519..26710c19 100644
--- a/src/ballistica/platform/windows/platform_windows.cc
+++ b/src/ballistica/platform/windows/platform_windows.cc
@@ -127,6 +127,28 @@ void PlatformWindows::SetupInterruptHandling() {
}
}
+auto PlatformWindows::GetPublicDeviceUUIDInputs() -> std::list {
+ std::list out;
+
+ std::string ret;
+ char value[64];
+ DWORD size = _countof(value);
+ DWORD type = REG_SZ;
+ HKEY key;
+ LONG retKey =
+ ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography",
+ 0, KEY_READ | KEY_WOW64_64KEY, &key);
+ LONG retVal = ::RegQueryValueExA(key, "MachineGuid", nullptr, &type,
+ (LPBYTE)value, &size);
+ if (retKey == ERROR_SUCCESS && retVal == ERROR_SUCCESS) {
+ ret = value;
+ }
+ ::RegCloseKey(key);
+
+ out.push_back(ret);
+ return out;
+}
+
std::string PlatformWindows::GenerateUUID() {
std::string val;
UUID uuid;
@@ -828,87 +850,6 @@ void PlatformWindows::Unlink(const char* path) { _unlink(path); }
void PlatformWindows::CloseSocket(int socket) { closesocket(socket); }
-int PlatformWindows::SocketPair(int domain, int type, int protocol,
- int socks_out[2]) {
- assert(type == SOCK_STREAM);
-
- int make_overlapped = false;
- union {
- struct sockaddr_in inaddr;
- struct sockaddr addr;
- } a;
- SOCKET listener;
- int e;
- socklen_t addrlen = sizeof(a.inaddr);
- DWORD flags = 0;
- int reuse = 1;
- int nodelay = 1;
-
- listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (listener < 0) {
- return SOCKET_ERROR;
- }
-
- memset(&a, 0, sizeof(a));
- a.inaddr.sin_family = AF_INET;
- a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- a.inaddr.sin_port = 0;
-
- SOCKET socks[2];
- socks[0] = socks[1] = INVALID_SOCKET;
- do {
- if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
- reinterpret_cast(&reuse), (socklen_t)sizeof(reuse))
- == -1) {
- break;
- }
- if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
- break;
- }
- if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) {
- break;
- }
- if (listen(listener, 1) == SOCKET_ERROR) {
- break;
- }
- socks[0] = socket(AF_INET, SOCK_STREAM, 0);
- if (socks[0] < 0) {
- break;
- }
- if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
- break;
- }
- socks[1] = accept(listener, nullptr, nullptr);
-
- // not sure if this helps but what the hey...
- if (setsockopt(socks[0], IPPROTO_TCP, TCP_NODELAY,
- reinterpret_cast(&nodelay),
- (socklen_t)sizeof(nodelay))
- == -1)
- break;
- if (setsockopt(socks[1], IPPROTO_TCP, TCP_NODELAY,
- reinterpret_cast(&nodelay),
- (socklen_t)sizeof(nodelay))
- == -1) {
- break;
- }
-
- if (socks[1] < 0) break;
-
- closesocket(listener);
- socks_out[0] = static_cast_check_fit(socks[0]);
- socks_out[1] = static_cast_check_fit(socks[1]);
- return 0;
- } while (0);
-
- e = WSAGetLastError();
- closesocket(listener);
- closesocket(socks[0]);
- closesocket(socks[1]);
- WSASetLastError(e);
- return SOCKET_ERROR;
-}
-
std::vector PlatformWindows::GetBroadcastAddrs() {
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
diff --git a/src/ballistica/platform/windows/platform_windows.h b/src/ballistica/platform/windows/platform_windows.h
index 67883ed8..844f8801 100644
--- a/src/ballistica/platform/windows/platform_windows.h
+++ b/src/ballistica/platform/windows/platform_windows.h
@@ -15,7 +15,8 @@ class PlatformWindows : public Platform {
public:
PlatformWindows();
void SetupInterruptHandling() override;
- auto GetDeviceUUIDPrefix() -> std::string override { return "w"; }
+ auto GetDeviceAccountUUIDPrefix() -> std::string override { return "w"; }
+ auto GetPublicDeviceUUIDInputs() -> std::list override;
auto GenerateUUID() -> std::string override;
auto GetDefaultConfigDir() -> std::string override;
auto Remove(const char* path) -> int;
@@ -42,8 +43,6 @@ class PlatformWindows : public Platform {
void OpenDirExternally(const std::string& path) override;
void Unlink(const char* path) override;
void CloseSocket(int socket) override;
- auto SocketPair(int domain, int type, int protocol, int socks[2])
- -> int override;
auto GetBroadcastAddrs() -> std::vector override;
auto SetSocketNonBlocking(int sd) -> bool override;
auto GetPlatformName() -> std::string override;
diff --git a/src/ballistica/python/methods/python_methods_input.cc b/src/ballistica/python/methods/python_methods_input.cc
index f523bd40..a38b9620 100644
--- a/src/ballistica/python/methods/python_methods_input.cc
+++ b/src/ballistica/python/methods/python_methods_input.cc
@@ -43,23 +43,6 @@ auto PyHaveTouchScreenInput(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_CATCH;
}
-auto PyStartListeningForWiiRemotes(PyObject* self, PyObject* args)
- -> PyObject* {
- BA_PYTHON_TRY;
- Platform::SetLastPyCall("start_listening_for_wii_remotes");
- g_platform->StartListeningForWiiRemotes();
- Py_RETURN_NONE;
- BA_PYTHON_CATCH;
-}
-
-auto PyStopListeningForWiiRemotes(PyObject* self, PyObject* args) -> PyObject* {
- BA_PYTHON_TRY;
- Platform::SetLastPyCall("stop_listening_for_wii_remotes");
- g_platform->StopListeningForWiiRemotes();
- Py_RETURN_NONE;
- BA_PYTHON_CATCH;
-}
-
auto PySetTouchscreenEditing(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_TRY;
Platform::SetLastPyCall("set_touchscreen_editing");
@@ -314,22 +297,6 @@ auto PythonMethodsInput::GetMethods() -> std::vector {
"\n"
"(internal)"},
- {"stop_listening_for_wii_remotes", PyStopListeningForWiiRemotes,
- METH_VARARGS,
- "stop_listening_for_wii_remotes() -> None\n"
- "\n"
- "(internal)\n"
- "\n"
- "Stop listening for connections from wii remotes."},
-
- {"start_listening_for_wii_remotes", PyStartListeningForWiiRemotes,
- METH_VARARGS,
- "start_listening_for_wii_remotes() -> None\n"
- "\n"
- "(internal)\n"
- "\n"
- "Start listening for connections from wii remotes."},
-
{"have_touchscreen_input", PyHaveTouchScreenInput, METH_VARARGS,
"have_touchscreen_input() -> bool\n"
"\n"
diff --git a/src/ballistica/python/methods/python_methods_ui.cc b/src/ballistica/python/methods/python_methods_ui.cc
index ee0ac6f7..5456da43 100644
--- a/src/ballistica/python/methods/python_methods_ui.cc
+++ b/src/ballistica/python/methods/python_methods_ui.cc
@@ -22,7 +22,7 @@
#include "ballistica/ui/widget/scroll_widget.h"
#if !BA_HEADLESS_BUILD
-extern "C" void SDL_ericf_focus();
+extern "C" void SDL_ericf_focus(void);
#endif
namespace ballistica {
@@ -2010,20 +2010,6 @@ auto PyShowProgressBar(PyObject* self, PyObject* args, PyObject* keywds)
BA_PYTHON_CATCH;
}
-auto PyShowInvitesUI(PyObject* self, PyObject* args, PyObject* keywds)
- -> PyObject* {
- BA_PYTHON_TRY;
- Platform::SetLastPyCall("show_invites_ui");
- static const char* kwlist[] = {nullptr};
- if (!PyArg_ParseTupleAndKeywords(args, keywds, "",
- const_cast(kwlist))) {
- return nullptr;
- }
- g_platform->AndroidGPGSPartyShowInvites();
- Py_RETURN_NONE;
- BA_PYTHON_CATCH;
-}
-
auto PySetPartyIconAlwaysVisible(PyObject* self, PyObject* args,
PyObject* keywds) -> PyObject* {
BA_PYTHON_TRY;
@@ -2389,14 +2375,6 @@ auto PythonMethodsUI::GetMethods() -> std::vector {
"\n"
"(internal)"},
- {"show_invites_ui", (PyCFunction)PyShowInvitesUI,
- METH_VARARGS | METH_KEYWORDS,
- "show_invites_ui() -> None\n"
- "\n"
- "(internal)\n"
- "\n"
- "Category: General Utility Functions"},
-
{"show_progress_bar", (PyCFunction)PyShowProgressBar,
METH_VARARGS | METH_KEYWORDS,
"show_progress_bar() -> None\n"
diff --git a/src/ballistica/python/python.cc b/src/ballistica/python/python.cc
index 668496f9..8d86e081 100644
--- a/src/ballistica/python/python.cc
+++ b/src/ballistica/python/python.cc
@@ -1182,6 +1182,24 @@ void Python::ShowURL(const std::string& url) {
}
}
+auto Python::StringList(const std::list& values) -> PythonRef {
+ assert(HaveGIL());
+ PythonRef pylist{PyList_New(values.size()), PythonRef::kSteal};
+ int i{};
+ for (auto&& value : values) {
+ PyObject* item{PyUnicode_FromString(value.c_str())};
+ assert(item);
+ PyList_SET_ITEM(pylist.get(), i, item);
+ ++i;
+ }
+ return pylist;
+}
+
+auto Python::SingleMemberTuple(const PythonRef& member) -> PythonRef {
+ assert(HaveGIL());
+ return PythonRef(Py_BuildValue("(O)", member.NewRef()), PythonRef::kSteal);
+}
+
auto Python::FilterChatMessage(std::string* message, int client_id) -> bool {
assert(message);
ScopedSetContext cp(g_game->GetUIContext());
@@ -2322,30 +2340,6 @@ auto Python::ObjToString(PyObject* obj) -> std::string {
}
}
-void Python::V1PartyInvite(const std::string& player,
- const std::string& invite_id) {
- ScopedSetContext cp(g_game->GetUIContext());
- PythonRef args(
- Py_BuildValue(
- "(OO)",
- PythonRef(PyUnicode_FromString(player.c_str()), PythonRef::kSteal)
- .get(),
- PythonRef(PyUnicode_FromString(invite_id.c_str()), PythonRef::kSteal)
- .get()),
- PythonRef::kSteal);
- obj(ObjID::kHandlePartyInviteCall).Call(args);
-}
-
-void Python::V1PartyInviteRevoke(const std::string& invite_id) {
- ScopedSetContext cp(g_game->GetUIContext());
- PythonRef args(
- Py_BuildValue("(O)", PythonRef(PyUnicode_FromString(invite_id.c_str()),
- PythonRef::kSteal)
- .get()),
- PythonRef::kSteal);
- obj(ObjID::kHandlePartyInviteRevokeCall).Call(args);
-}
-
void Python::StoreObj(ObjID id, PyObject* pyobj, bool incref) {
assert(id < ObjID::kLast);
assert(pyobj);
diff --git a/src/ballistica/python/python.h b/src/ballistica/python/python.h
index 343934b0..1fbfbbd5 100644
--- a/src/ballistica/python/python.h
+++ b/src/ballistica/python/python.h
@@ -142,8 +142,6 @@ class Python {
/// is useful as an object identifier/etc.
static auto GetPythonFileLocation(bool pretty = true) -> std::string;
- void V1PartyInvite(const std::string& player, const std::string& invite_id);
- void V1PartyInviteRevoke(const std::string& invite_id);
void set_env_obj(PyObject* obj) { env_ = obj; }
auto env_obj() const -> PyObject* {
assert(env_);
@@ -270,7 +268,6 @@ class Python {
kOnScreenKeyboardClass,
kFilterChatMessageCall,
kHandleLocalChatMessageCall,
- kHandlePartyInviteCall,
kHandlePartyInviteRevokeCall,
kDoPlayMusicCall,
kDeepLinkCall,
@@ -352,6 +349,7 @@ class Python {
kGetPlayerIconCall,
kLstrFromJsonCall,
kUUIDStrCall,
+ kHashStringsCall,
kLast // Sentinel; must be at end.
};
@@ -373,6 +371,12 @@ class Python {
return objs_[static_cast(id)].exists();
}
+ /// Create a Python list of strings.
+ auto StringList(const std::list& values) -> PythonRef;
+
+ /// Create a Python single-member tuple.
+ auto SingleMemberTuple(const PythonRef& member) -> PythonRef;
+
/// Push a call to a preset obj to the game thread
/// (will be run in the UI context).
void PushObjCall(ObjID obj);
diff --git a/src/ballistica/python/python_ref.cc b/src/ballistica/python/python_ref.cc
index e5be1ae5..a91b6ada 100644
--- a/src/ballistica/python/python_ref.cc
+++ b/src/ballistica/python/python_ref.cc
@@ -140,6 +140,12 @@ auto PythonRef::CallableCheck() const -> bool {
return static_cast(PyCallable_Check(obj_));
}
+auto PythonRef::UnicodeCheck() const -> bool {
+ BA_PRECONDITION(obj_);
+ assert(Python::HaveGIL());
+ return static_cast(PyUnicode_Check(obj_));
+}
+
auto PythonRef::Call(PyObject* args, PyObject* keywds, bool print_errors) const
-> PythonRef {
assert(obj_);
diff --git a/src/ballistica/python/python_ref.h b/src/ballistica/python/python_ref.h
index 6eecd5b2..80eebbec 100644
--- a/src/ballistica/python/python_ref.h
+++ b/src/ballistica/python/python_ref.h
@@ -107,6 +107,9 @@ class PythonRef {
/// Returns whether the underlying PyObject is callable.
auto CallableCheck() const -> bool;
+ /// Return whether the underlying PyObject is unicode.
+ auto UnicodeCheck() const -> bool;
+
/// Call the PyObject. On error, (optionally) prints errors and returns empty
/// ref.
auto Call(PyObject* args, PyObject* keywds = nullptr,
diff --git a/src/meta/bameta/python_embedded/binding.py b/src/meta/bameta/python_embedded/binding.py
index bcb7bf65..90c1830e 100644
--- a/src/meta/bameta/python_embedded/binding.py
+++ b/src/meta/bameta/python_embedded/binding.py
@@ -24,7 +24,6 @@ import _ba
# FIXME: There should be no bastd in here;
# should pull in bases from ba which get overridden by bastd (or other).
from bastd.ui.onscreenkeyboard import OnScreenKeyboardWindow
-from bastd.ui import party
if TYPE_CHECKING:
from typing import Any
@@ -107,7 +106,6 @@ def get_binding_values() -> tuple[Any, ...]:
json.dumps, # kJsonDumpsCall
json.loads, # kJsonLoadsCall
OnScreenKeyboardWindow, # kOnScreenKeyboardClass
- party.handle_party_invite, # kHandlePartyInviteCall
_music.do_play_music, # kDoPlayMusicCall
ba.app.handle_deep_link, # kDeepLinkCall
ba.app.lang.get_resource, # kGetResourceCall
@@ -135,4 +133,5 @@ def get_binding_values() -> tuple[Any, ...]:
_hooks.get_player_icon, # kGetPlayerIconCall
_language.Lstr.from_json, # kLstrFromJsonCall
_hooks.uuid_str, # kUUIDStrCall
+ _hooks.hash_strings, # kHashStringsCall
) # yapf: disable
diff --git a/tools/bacommon/servermanager.py b/tools/bacommon/servermanager.py
index b767006a..5516dbb2 100644
--- a/tools/bacommon/servermanager.py
+++ b/tools/bacommon/servermanager.py
@@ -104,7 +104,7 @@ class ServerConfig:
# if ${ACCOUNT} is present in the string, it will be replaced by the
# currently-signed-in account's id. To fetch info about an account,
# your back-end server can use the following url:
- # http://bombsquadgame.com/accountquery?id=ACCOUNT_ID_HERE
+ # https://legacy.ballistica.net/accountquery?id=ACCOUNT_ID_HERE
stats_url: Optional[str] = None
# If present, the server subprocess will attempt to gracefully exit after
diff --git a/tools/batools/project.py b/tools/batools/project.py
index 5c8967e6..2a1bbb74 100755
--- a/tools/batools/project.py
+++ b/tools/batools/project.py
@@ -448,23 +448,24 @@ class Updater:
def _update_visual_studio_project(self, basename: str) -> None:
- fname = f'ballisticacore-windows/{basename}/{basename}.vcxproj'
+ fname = (f'ballisticacore-windows/{basename}/'
+ f'BallisticaCore{basename}.vcxproj')
# Currently just silently skipping if not found (for public repo).
if not os.path.exists(fname):
- return
+ raise CleanError(f'Visual Studio project not found: {fname}')
with open(fname, encoding='utf-8') as infile:
lines = infile.read().splitlines()
src_root = '..\\..\\src'
- public = 'Internal' not in basename
+ public_project = 'Internal' in basename
all_files = sorted([
f for f in (self._source_files + self._header_files)
- if not f.endswith('.m') and not f.endswith('.mm') and
- not f.endswith('.c') and self._is_public_source_file(f) == public
+ if not f.endswith('.m') and not f.endswith('.mm') and not f.
+ endswith('.c') and self._is_public_source_file(f) == public_project
])
# Find the ItemGroup containing stdafx.cpp. This is where we'll dump
@@ -491,6 +492,7 @@ class Updater:
+ src_root + '\\ballistica' + src.replace('/', '\\') + '" />'
for src in all_files
] + group_lines
+
filtered = lines[:begin_index + 1] + group_lines + lines[end_index:]
self._file_changes[fname] = '\r\n'.join(filtered) + '\r\n'
@@ -537,12 +539,13 @@ class Updater:
'.filters'] = '\r\n'.join(filterlines) + '\r\n'
def _update_visual_studio_projects(self) -> None:
- self._update_visual_studio_project('BallisticaCoreGeneric')
- self._update_visual_studio_project('BallisticaCoreGenericInternal')
- self._update_visual_studio_project('BallisticaCoreHeadless')
- self._update_visual_studio_project('BallisticaCoreHeadlessInternal')
- self._update_visual_studio_project('BallisticaCoreOculus')
- self._update_visual_studio_project('BallisticaCoreOculusInternal')
+ self._update_visual_studio_project('Generic')
+ self._update_visual_studio_project('Headless')
+ if not self._public:
+ self._update_visual_studio_project('GenericInternal')
+ self._update_visual_studio_project('HeadlessInternal')
+ self._update_visual_studio_project('Oculus')
+ self._update_visual_studio_project('OculusInternal')
def _is_public_source_file(self, filename: str) -> bool:
assert filename.startswith('/')