From 3baa77c18e4ba671001c771d6409bda9fda3f175 Mon Sep 17 00:00:00 2001 From: Eric Froemling Date: Wed, 2 Mar 2022 06:03:11 -0600 Subject: [PATCH] Added public device id and various cleanup --- .idea/dictionaries/ericf.xml | 2 + CHANGELOG.md | 5 + README.md | 2 +- assets/src/ba_data/python/ba/_hooks.py | 10 + assets/src/ba_data/python/ba/_language.py | 2 +- assets/src/ba_data/python/ba/_net.py | 5 +- assets/src/ba_data/python/bastd/ui/party.py | 51 - .../python/bastd/ui/settings/advanced.py | 4 +- .../python/bastd/ui/settings/nettesting.py | 12 +- .../.idea/dictionaries/ericf.xml | 2 + .../Generic/BallisticaCoreGeneric.vcxproj | 513 +----- .../BallisticaCoreGeneric.vcxproj.filters | 1443 ++--------------- .../Headless/BallisticaCoreHeadless.vcxproj | 513 +----- .../BallisticaCoreHeadless.vcxproj.filters | 1443 ++--------------- src/ballistica/app/app.cc | 13 +- src/ballistica/app/app.h | 2 +- src/ballistica/app/app_globals.h | 2 - src/ballistica/ballistica.cc | 22 +- src/ballistica/ballistica.h | 6 +- .../game/connection/connection_set.h | 18 - .../game/connection/connection_to_client.h | 41 +- .../connection/connection_to_client_udp.h | 17 +- .../game/connection/connection_to_host_udp.h | 15 +- src/ballistica/game/game.cc | 41 +- src/ballistica/game/game.h | 6 - src/ballistica/generic/utils.cc | 1 + .../platform/apple/platform_apple.h | 9 +- .../platform/linux/platform_linux.cc | 20 + .../platform/linux/platform_linux.h | 17 +- src/ballistica/platform/platform.cc | 139 +- src/ballistica/platform/platform.h | 363 +++-- src/ballistica/platform/sdl/sdl_app.cc | 2 +- .../platform/windows/platform_windows.cc | 103 +- .../platform/windows/platform_windows.h | 5 +- .../python/methods/python_methods_input.cc | 33 - .../python/methods/python_methods_ui.cc | 24 +- src/ballistica/python/python.cc | 42 +- src/ballistica/python/python.h | 10 +- src/ballistica/python/python_ref.cc | 6 + src/ballistica/python/python_ref.h | 3 + src/meta/bameta/python_embedded/binding.py | 3 +- tools/bacommon/servermanager.py | 2 +- tools/batools/project.py | 25 +- 43 files changed, 870 insertions(+), 4127 deletions(-) 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 @@ ![](https://github.com/efroemling/ballistica/workflows/CI/badge.svg) -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('/')