diff --git a/.efrocachemap b/.efrocachemap
index 3c3b59f8..9987ce92 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -3934,14 +3934,14 @@
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ac/96/c3b9934061393fe09cc90ff24b8d",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/38/2b/5641b3b40846f74f232771ac0457",
- "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/55/e7/7493c35661e347a164ccc9a6e150",
- "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f4/a8/5f874f2c8ee0de54649b3142c2c5",
- "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/87/cd/e155776004a096cd1981e8c45539",
- "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/44/90/8453cc086294eaf8bd15f4df8332",
- "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/e8/98/2363d625af50c24c6ef3d2e9c58d",
- "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7a/fd/1b7ecd5d084ea0e52974e463b0be",
- "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/e8/88/8fe7875aa34660db68e74f25051d",
- "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/23/2d/8239623b2d8745b4feb4b380b12a",
- "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c3/2f/03140734daf10cd7e46a29c5c820",
- "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/26/7a/d23e25fdda6f6b1d9ed3b03040b6"
+ "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/07/e7/d8f0add439e55e3cce5e5768c80f",
+ "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/72/faa94ff6532a95c121fcb5a4f788",
+ "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d2/d1/99514fbe084fb0480d75f92ecb2c",
+ "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/dd/5d/f8c5b24579236bef5209d7089044",
+ "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5f/ff/5d34815d90dd4cd36f2a6f587958",
+ "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/45/1e/cea9badaf52032adb40e6c3b5e21",
+ "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/5d/63/96c2bbbedc03bd23824d7354b07d",
+ "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/44/94/4fa92ae4a1e726fb0b37e626e107",
+ "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/66/fd/8bb36157e75f78caa5373d9def18",
+ "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/af/2d/7546ed3c987435a743442603c21b"
}
\ No newline at end of file
diff --git a/docs/ba_module.md b/docs/ba_module.md
index a98f543a..a4b30a75 100644
--- a/docs/ba_module.md
+++ b/docs/ba_module.md
@@ -1,5 +1,5 @@
-
last updated on 2020-09-30 for Ballistica version 1.5.26 build 20190
+last updated on 2020-10-02 for Ballistica version 1.5.26 build 20194
This page documents the Python classes and functions in the 'ba' module,
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!
diff --git a/src/ballistica/app/app_config.cc b/src/ballistica/app/app_config.cc
deleted file mode 100644
index 5a9bbcce..00000000
--- a/src/ballistica/app/app_config.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2011-2020 Eric Froemling
-
-#include "ballistica/app/app_config.h"
-
-#include
-
-#include "ballistica/ballistica.h"
-#include "ballistica/platform/platform.h"
-#include "ballistica/python/python.h"
-
-namespace ballistica {
-
-void AppConfig::Init() { new AppConfig(); }
-
-auto AppConfig::Entry::FloatValue() const -> float {
- throw Exception("not a float entry");
-}
-
-auto AppConfig::Entry::StringValue() const -> std::string {
- throw Exception("not a string entry");
-}
-
-auto AppConfig::Entry::IntValue() const -> int {
- throw Exception("not an int entry");
-}
-
-auto AppConfig::Entry::BoolValue() const -> bool {
- throw Exception("not a bool entry");
-}
-
-auto AppConfig::Entry::DefaultFloatValue() const -> float {
- throw Exception("not a float entry");
-}
-
-auto AppConfig::Entry::DefaultStringValue() const -> std::string {
- throw Exception("not a string entry");
-}
-
-auto AppConfig::Entry::DefaultIntValue() const -> int {
- throw Exception("not an int entry");
-}
-
-auto AppConfig::Entry::DefaultBoolValue() const -> bool {
- throw Exception("not a bool entry");
-}
-
-class AppConfig::StringEntry : public AppConfig::Entry {
- public:
- StringEntry() = default;
- StringEntry(const char* name, std::string default_value)
- : Entry(name), default_value_(std::move(default_value)) {}
- auto GetType() const -> Type override { return Type::kString; }
- auto Resolve() const -> std::string {
- return g_python->GetRawConfigValue(name().c_str(), default_value_.c_str());
- }
- auto StringValue() const -> std::string override { return Resolve(); }
- auto DefaultStringValue() const -> std::string override {
- return default_value_;
- }
-
- private:
- std::string default_value_;
-};
-
-class AppConfig::FloatEntry : public AppConfig::Entry {
- public:
- FloatEntry() = default;
- FloatEntry(const char* name, float default_value)
- : Entry(name), default_value_(default_value) {}
- auto GetType() const -> Type override { return Type::kFloat; }
- auto Resolve() const -> float {
- return g_python->GetRawConfigValue(name().c_str(), default_value_);
- }
- auto FloatValue() const -> float override { return Resolve(); }
- auto DefaultFloatValue() const -> float override { return default_value_; }
-
- private:
- float default_value_{};
-};
-
-class AppConfig::IntEntry : public AppConfig::Entry {
- public:
- IntEntry() = default;
- IntEntry(const char* name, int default_value)
- : Entry(name), default_value_(default_value) {}
- auto GetType() const -> Type override { return Type::kInt; }
- auto Resolve() const -> int {
- return g_python->GetRawConfigValue(name().c_str(), default_value_);
- }
- auto IntValue() const -> int override { return Resolve(); }
- auto DefaultIntValue() const -> int override { return default_value_; }
-
- private:
- int default_value_{};
-};
-
-class AppConfig::BoolEntry : public AppConfig::Entry {
- public:
- BoolEntry() = default;
- BoolEntry(const char* name, bool default_value)
- : Entry(name), default_value_(default_value) {}
- auto GetType() const -> Type override { return Type::kBool; }
- auto Resolve() const -> bool {
- return g_python->GetRawConfigValue(name().c_str(), default_value_);
- }
- auto BoolValue() const -> bool override { return Resolve(); }
- auto DefaultBoolValue() const -> bool override { return default_value_; }
-
- private:
- bool default_value_{};
-};
-
-AppConfig::AppConfig() {
- // (We're a singleton).
- assert(g_app_config == nullptr);
- g_app_config = this;
- SetupEntries();
-}
-
-template
-void AppConfig::CompleteMap(const T& entry_map) {
- for (auto&& i : entry_map) {
- assert(entries_by_name_.find(i.second.name()) == entries_by_name_.end());
- assert(i.first < decltype(i.first)::kLast);
- entries_by_name_[i.second.name()] = &i.second;
- }
-
- // Make sure all values have entries.
-#if BA_DEBUG_BUILD
- int last = static_cast(decltype(entry_map.begin()->first)::kLast); // ew
- for (int j = 0; j < last; ++j) {
- auto i2 =
- entry_map.find(static_castfirst)>(j));
- if (i2 == entry_map.end()) {
- throw Exception("Missing appconfig entry " + std::to_string(j));
- }
- }
-#endif
-}
-
-void AppConfig::SetupEntries() {
- // Register all our typed entries.
- float_entries_[FloatID::kScreenGamma] = FloatEntry("Screen Gamma", 1.0F);
- float_entries_[FloatID::kScreenPixelScale] =
- FloatEntry("Screen Pixel Scale", 1.0F);
- float_entries_[FloatID::kTouchControlsScale] =
- FloatEntry("Touch Controls Scale", 1.0F);
- float_entries_[FloatID::kTouchControlsScaleMovement] =
- FloatEntry("Touch Controls Scale Movement", 1.0F);
- float_entries_[FloatID::kTouchControlsScaleActions] =
- FloatEntry("Touch Controls Scale Actions", 1.0F);
- float_entries_[FloatID::kSoundVolume] = FloatEntry("Sound Volume", 1.0F);
- float_entries_[FloatID::kMusicVolume] = FloatEntry("Music Volume", 1.0F);
-
- // Note: keep this synced with the defaults in MainActivity.java.
- float gvrrts_default = g_platform->IsRunningOnDaydream() ? 1.0F : 0.5F;
- float_entries_[FloatID::kGoogleVRRenderTargetScale] =
- FloatEntry("GVR Render Target Scale", gvrrts_default);
-
- string_entries_[StringID::kResolutionAndroid] =
- StringEntry("Resolution (Android)", "Auto");
- string_entries_[StringID::kTouchActionControlType] =
- StringEntry("Touch Action Control Type", "buttons");
- string_entries_[StringID::kTouchMovementControlType] =
- StringEntry("Touch Movement Control Type", "swipe");
- string_entries_[StringID::kGraphicsQuality] =
- StringEntry("Graphics Quality", "Auto");
- string_entries_[StringID::kTextureQuality] =
- StringEntry("Texture Quality", "Auto");
- string_entries_[StringID::kVerticalSync] =
- StringEntry("Vertical Sync", "Auto");
- string_entries_[StringID::kVRHeadRelativeAudio] =
- StringEntry("VR Head Relative Audio", "Auto");
- string_entries_[StringID::kMacControllerSubsystem] =
- StringEntry("Mac Controller Subsystem", "Classic");
- string_entries_[StringID::kTelnetPassword] =
- StringEntry("Telnet Password", "changeme");
-
- int_entries_[IntID::kPort] = IntEntry("Port", kDefaultPort);
- int_entries_[IntID::kTelnetPort] =
- IntEntry("Telnet Port", kDefaultTelnetPort);
-
- bool_entries_[BoolID::kTouchControlsSwipeHidden] =
- BoolEntry("Touch Controls Swipe Hidden", false);
- bool_entries_[BoolID::kFullscreen] = BoolEntry("Fullscreen", false);
- bool_entries_[BoolID::kKickIdlePlayers] =
- BoolEntry("Kick Idle Players", false);
- bool_entries_[BoolID::kAlwaysUseInternalKeyboard] =
- BoolEntry("Always Use Internal Keyboard", false);
- bool_entries_[BoolID::kShowFPS] = BoolEntry("Show FPS", false);
- bool_entries_[BoolID::kTVBorder] =
- BoolEntry("TV Border", g_platform->IsRunningOnTV());
- bool_entries_[BoolID::kKeyboardP2Enabled] =
- BoolEntry("Keyboard P2 Enabled", false);
- bool_entries_[BoolID::kEnablePackageMods] =
- BoolEntry("Enable Package Mods", false);
- bool_entries_[BoolID::kChatMuted] = BoolEntry("Chat Muted", false);
- bool_entries_[BoolID::kEnableRemoteApp] =
- BoolEntry("Enable Remote App", true);
- bool_entries_[BoolID::kEnableTelnet] = BoolEntry("Enable Telnet", true);
- bool_entries_[BoolID::kDisableCameraShake] =
- BoolEntry("Disable Camera Shake", false);
- bool_entries_[BoolID::kDisableCameraGyro] =
- BoolEntry("Disable Camera Gyro", false);
-
- // Now add everything to our name map and make sure all is kosher.
- CompleteMap(float_entries_);
- CompleteMap(int_entries_);
- CompleteMap(string_entries_);
- CompleteMap(bool_entries_);
-}
-
-auto AppConfig::Resolve(FloatID id) -> float {
- auto i = float_entries_.find(id);
- if (i == float_entries_.end()) {
- throw Exception("Invalid config entry");
- }
- return i->second.Resolve();
-}
-
-auto AppConfig::Resolve(StringID id) -> std::string {
- auto i = string_entries_.find(id);
- if (i == string_entries_.end()) {
- throw Exception("Invalid config entry");
- }
- return i->second.Resolve();
-}
-
-auto AppConfig::Resolve(BoolID id) -> bool {
- auto i = bool_entries_.find(id);
- if (i == bool_entries_.end()) {
- throw Exception("Invalid config entry");
- }
- return i->second.Resolve();
-}
-
-auto AppConfig::Resolve(IntID id) -> int {
- auto i = int_entries_.find(id);
- if (i == int_entries_.end()) {
- throw Exception("Invalid config entry");
- }
- return i->second.Resolve();
-}
-
-} // namespace ballistica
diff --git a/src/ballistica/app/app_globals.cc b/src/ballistica/app/app_globals.cc
deleted file mode 100644
index 3afbb3fe..00000000
--- a/src/ballistica/app/app_globals.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2011-2020 Eric Froemling
-
-#include "ballistica/app/app_globals.h"
-
-namespace ballistica {
-
-AppGlobals::AppGlobals(int argc_in, char** argv_in)
- : argc{argc_in},
- argv{argv_in},
- main_thread_id{std::this_thread::get_id()} {}
-
-} // namespace ballistica
diff --git a/src/ballistica/app/app_globals.h b/src/ballistica/app/app_globals.h
index 7af2803e..67b91272 100644
--- a/src/ballistica/app/app_globals.h
+++ b/src/ballistica/app/app_globals.h
@@ -10,7 +10,6 @@
#include
#include "ballistica/ballistica.h"
-#include "ballistica/networking/master_server_config.h"
namespace ballistica {
@@ -85,8 +84,6 @@ class AppGlobals {
std::mutex real_time_mutex;
std::mutex thread_name_map_mutex;
std::map thread_name_map;
- std::string master_server_addr{BA_MASTER_SERVER_DEFAULT_ADDR};
- std::string master_server_fallback_addr{BA_MASTER_SERVER_FALLBACK_ADDR};
#if BA_DEBUG_BUILD
std::mutex object_list_mutex;
Object* object_list_first{};
diff --git a/src/ballistica/app/headless_app.cc b/src/ballistica/app/headless_app.cc
deleted file mode 100644
index 6d88748e..00000000
--- a/src/ballistica/app/headless_app.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2011-2020 Eric Froemling
-#if BA_HEADLESS_BUILD
-
-#include "ballistica/app/headless_app.h"
-
-#include "ballistica/ballistica.h"
-
-namespace ballistica {
-
-// We could technically use the vanilla App class here since we're not
-// changing anything.
-HeadlessApp::HeadlessApp(Thread* thread) : App(thread) {
- // NewThreadTimer(10, true, NewLambdaRunnable([this] {
- // assert(g_app);
- // g_app->RunEvents();
- // }));
-}
-
-} // namespace ballistica
-
-#endif // BA_HEADLESS_BUILD
diff --git a/src/ballistica/app/stress_test.cc b/src/ballistica/app/stress_test.cc
deleted file mode 100644
index 4846e9ac..00000000
--- a/src/ballistica/app/stress_test.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2011-2020 Eric Froemling
-
-#include "ballistica/app/stress_test.h"
-
-#include "ballistica/ballistica.h"
-#include "ballistica/graphics/graphics_server.h"
-#include "ballistica/graphics/renderer.h"
-#include "ballistica/input/input.h"
-#include "ballistica/platform/platform.h"
-
-namespace ballistica {
-
-void StressTest::Update() {
- assert(InMainThread());
-
- // Handle a little misc stuff here.
- // If we're currently running stress-tests, update that stuff.
- if (stress_testing_ && g_input) {
- // Update our fake inputs to make our dudes run around.
- g_input->ProcessStressTesting(stress_test_player_count_);
-
- // Every 10 seconds update our stress-test stats.
- millisecs_t t = GetRealTime();
- if (t - last_stress_test_update_time_ >= 10000) {
- if (stress_test_stats_file_ == nullptr) {
- assert(g_platform);
- std::string f_name =
- g_platform->GetUserPythonDirectory() + "/stress_test_stats.csv";
- stress_test_stats_file_ = g_platform->FOpen(f_name.c_str(), "wb");
- if (stress_test_stats_file_ != nullptr) {
- fprintf(stress_test_stats_file_,
- "time,averageFps,nodes,models,collide_models,textures,sounds,"
- "pssMem,sharedDirtyMem,privateDirtyMem\n");
- fflush(stress_test_stats_file_);
- if (g_buildconfig.ostype_android()) {
- // On android, let the OS know we've added or removed a file
- // (limit to android or we'll get an unimplemented warning).
- g_platform->AndroidRefreshFile(f_name);
- }
- }
- }
- if (stress_test_stats_file_ != nullptr) {
- // See how many frames we've rendered this past interval.
- int total_frames_rendered;
- if (g_graphics_server && g_graphics_server->renderer()) {
- total_frames_rendered =
- g_graphics_server->renderer()->total_frames_rendered();
- } else {
- total_frames_rendered = last_total_frames_rendered_;
- }
- float avg =
- static_cast(total_frames_rendered
- - last_total_frames_rendered_)
- / (static_cast(t - last_stress_test_update_time_) / 1000.0f);
- last_total_frames_rendered_ = total_frames_rendered;
- uint32_t model_count = 0;
- uint32_t collide_model_count = 0;
- uint32_t texture_count = 0;
- uint32_t sound_count = 0;
- uint32_t node_count = 0;
- if (g_media) {
- model_count = g_media->total_model_count();
- collide_model_count = g_media->total_collide_model_count();
- texture_count = g_media->total_texture_count();
- sound_count = g_media->total_sound_count();
- }
- assert(g_game);
- std::string mem_usage = g_platform->GetMemUsageInfo();
- fprintf(stress_test_stats_file_, "%d,%.1f,%d,%d,%d,%d,%d,%s\n",
- static_cast_check_fit(GetRealTime()), avg, node_count,
- model_count, collide_model_count, texture_count, sound_count,
- mem_usage.c_str());
- fflush(stress_test_stats_file_);
- }
- last_stress_test_update_time_ = t;
- }
- }
-}
-
-void StressTest::Set(bool enable, int player_count) {
- assert(InMainThread());
- bool was_stress_testing = stress_testing_;
- stress_testing_ = enable;
- stress_test_player_count_ = player_count;
-
- // If we're turning on, reset our intervals and things.
- if (!was_stress_testing && stress_testing_) {
- // So our first sample is 1 interval from now.
- last_stress_test_update_time_ = GetRealTime();
-
- // Reset our frames-rendered tally.
- if (g_graphics_server && g_graphics_server->renderer()) {
- last_total_frames_rendered_ =
- g_graphics_server->renderer()->total_frames_rendered();
- } else {
- // Assume zero if there's no graphics yet.
- last_total_frames_rendered_ = 0;
- }
- }
-}
-} // namespace ballistica
diff --git a/src/ballistica/app/vr_app.cc b/src/ballistica/app/vr_app.cc
deleted file mode 100644
index e7d8909e..00000000
--- a/src/ballistica/app/vr_app.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2011-2020 Eric Froemling
-#if BA_VR_BUILD
-
-#include "ballistica/app/vr_app.h"
-
-#include "ballistica/game/game.h"
-#include "ballistica/graphics/graphics_server.h"
-#include "ballistica/graphics/renderer.h"
-
-namespace ballistica {
-
-VRApp::VRApp(Thread* thread) : App(thread) {}
-
-void VRApp::PushVRSimpleRemoteStateCall(const VRSimpleRemoteState& state) {
- PushCall([this, state] {
- // Convert this to a full hands state, adding in some simple elbow
- // positioning of our own and left/right.
- VRHandsState s;
- s.l.tx = -0.2f;
- s.l.ty = -0.2f;
- s.l.tz = -0.3f;
-
- // Hmm; for now lets always assign this as right hand even when its in
- // left-handed mode to keep things simple on the back-end. Can change later
- // if there's a downside to that.
- s.r.type = VRHandType::kDaydreamRemote;
- s.r.tx = 0.2f;
- s.r.ty = -0.2f;
- s.r.tz = -0.3f;
- s.r.yaw = state.r0;
- s.r.pitch = state.r1;
- s.r.roll = state.r2;
- VRSetHands(s);
- });
-}
-
-void VRApp::VRSetDrawDimensions(int w, int h) {
- g_graphics_server->VideoResize(w, h);
-}
-
-void VRApp::VRPreDraw() {
- if (!g_graphics_server || !g_graphics_server->renderer()) {
- return;
- }
- assert(InMainThread());
- if (FrameDef* frame_def = g_graphics_server->GetRenderFrameDef()) {
- // Note: this could be part of PreprocessRenderFrameDef but
- // the non-vr path needs it to be separate since preprocess doesn't
- // happen sometimes. Should probably clean that up.
- g_graphics_server->RunFrameDefMeshUpdates(frame_def);
-
- // store this for the duration of this frame
- vr_render_frame_def_ = frame_def;
- g_graphics_server->PreprocessRenderFrameDef(frame_def);
- }
-}
-
-void VRApp::VRPostDraw() {
- assert(InMainThread());
- if (!g_graphics_server || !g_graphics_server->renderer()) {
- return;
- }
- if (vr_render_frame_def_) {
- g_graphics_server->FinishRenderFrameDef(vr_render_frame_def_);
- vr_render_frame_def_ = nullptr;
- }
- RunRenderUpkeepCycle();
-}
-
-void VRApp::VRSetHead(float tx, float ty, float tz, float yaw, float pitch,
- float roll) {
- assert(InMainThread());
- Renderer* renderer = g_graphics_server->renderer();
- if (renderer == nullptr) return;
- renderer->VRSetHead(tx, ty, tz, yaw, pitch, roll);
-}
-
-void VRApp::VRSetHands(const VRHandsState& state) {
- assert(InMainThread());
-
- // Pass this along to the renderer (in this same thread) for drawing
- // (so hands can be drawn at their absolute most up-to-date positions, etc).
- Renderer* renderer = g_graphics_server->renderer();
- if (renderer == nullptr) return;
- renderer->VRSetHands(state);
-
- // ALSO ship it off to the game/ui thread to actually handle input from it.
- g_game->PushVRHandsState(state);
-}
-
-void VRApp::VRDrawEye(int eye, float yaw, float pitch, float roll, float tan_l,
- float tan_r, float tan_b, float tan_t, float eye_x,
- float eye_y, float eye_z, int viewport_x,
- int viewport_y) {
- if (!g_graphics_server || !g_graphics_server->renderer()) {
- return;
- }
- assert(InMainThread());
- if (vr_render_frame_def_) {
- // set up VR eye stuff...
- Renderer* renderer = g_graphics_server->renderer();
- renderer->VRSetEye(eye, yaw, pitch, roll, tan_l, tan_r, tan_b, tan_t, eye_x,
- eye_y, eye_z, viewport_x, viewport_y);
- g_graphics_server->DrawRenderFrameDef(vr_render_frame_def_);
- }
-}
-
-} // namespace ballistica
-
-#endif // BA_VR_BUILD
diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc
index 8c0228e7..3bbb99db 100644
--- a/src/ballistica/ballistica.cc
+++ b/src/ballistica/ballistica.cc
@@ -29,7 +29,7 @@
namespace ballistica {
// These are set automatically via script; don't change here.
-const int kAppBuildNumber = 20193;
+const int kAppBuildNumber = 20194;
const char* kAppVersion = "1.5.26";
const char* kBlessingHash = nullptr;
diff --git a/src/ballistica/game/account.cc b/src/ballistica/game/account.cc
new file mode 100644
index 00000000..b432f315
--- /dev/null
+++ b/src/ballistica/game/account.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2011-2020 Eric Froemling
+
+#include "ballistica/game/account.h"
+
+#include "ballistica/app/app_globals.h"
+#include "ballistica/game/game.h"
+#include "ballistica/generic/utils.h"
+#include "ballistica/python/python.h"
+
+namespace ballistica {
+
+auto Account::AccountTypeFromString(const std::string& val) -> AccountType {
+ if (val == "Game Center") {
+ return AccountType::kGameCenter;
+ } else if (val == "Game Circle") {
+ return AccountType::kGameCircle;
+ } else if (val == "Google Play") {
+ return AccountType::kGooglePlay;
+ } else if (val == "Steam") {
+ return AccountType::kSteam;
+ } else if (val == "Oculus") {
+ return AccountType::kOculus;
+ } else if (val == "NVIDIA China") {
+ return AccountType::kNvidiaChina;
+ } else if (val == "Test") {
+ return AccountType::kTest;
+ } else if (val == "Local") {
+ return AccountType::kDevice;
+ } else if (val == "Server") {
+ return AccountType::kServer;
+ } else {
+ return AccountType::kInvalid;
+ }
+}
+
+auto Account::AccountTypeToString(AccountType type) -> std::string {
+ switch (type) {
+ case AccountType::kGameCenter:
+ return "Game Center";
+ case AccountType::kGameCircle:
+ return "Game Circle";
+ case AccountType::kGooglePlay:
+ return "Google Play";
+ case AccountType::kSteam:
+ return "Steam";
+ case AccountType::kOculus:
+ return "Oculus";
+ case AccountType::kTest:
+ return "Test";
+ case AccountType::kDevice:
+ return "Local";
+ case AccountType::kServer:
+ return "Server";
+ case AccountType::kNvidiaChina:
+ return "NVIDIA China";
+ default:
+ return "";
+ }
+}
+
+auto Account::AccountTypeToIconString(AccountType type) -> std::string {
+ switch (type) {
+ case AccountType::kTest:
+ return g_game->CharStr(SpecialChar::kTestAccount);
+ case AccountType::kNvidiaChina:
+ return g_game->CharStr(SpecialChar::kNvidiaLogo);
+ case AccountType::kGooglePlay:
+ return g_game->CharStr(SpecialChar::kGooglePlayGamesLogo);
+ case AccountType::kSteam:
+ return g_game->CharStr(SpecialChar::kSteamLogo);
+ case AccountType::kOculus:
+ return g_game->CharStr(SpecialChar::kOculusLogo);
+ case AccountType::kGameCenter:
+ return g_game->CharStr(SpecialChar::kGameCenterLogo);
+ case AccountType::kGameCircle:
+ return g_game->CharStr(SpecialChar::kGameCircleLogo);
+ case AccountType::kDevice:
+ case AccountType::kServer:
+ return g_game->CharStr(SpecialChar::kLocalAccount);
+ default:
+ return "";
+ }
+}
+
+Account::Account() = default;
+
+auto Account::GetAccountName() -> std::string {
+ std::lock_guard lock(mutex_);
+ return account_name_;
+}
+
+auto Account::GetAccountID() -> std::string {
+ std::lock_guard lock(mutex_);
+ return account_id_;
+}
+
+auto Account::GetAccountToken() -> std::string {
+ std::lock_guard lock(mutex_);
+ return account_token_;
+}
+
+auto Account::GetAccountExtra() -> std::string {
+ std::lock_guard lock(mutex_);
+ return account_extra_;
+}
+
+auto Account::GetAccountExtra2() -> std::string {
+ std::lock_guard lock(mutex_);
+ return account_extra_2_;
+}
+
+auto Account::GetAccountState(int* state_num) -> AccountState {
+ std::lock_guard lock(mutex_);
+ if (state_num) {
+ *state_num = account_state_num_;
+ }
+ return account_state_;
+}
+
+void Account::SetAccountExtra(const std::string& extra) {
+ std::lock_guard lock(mutex_);
+ account_extra_ = extra;
+}
+
+void Account::SetAccountExtra2(const std::string& extra) {
+ std::lock_guard lock(mutex_);
+ account_extra_2_ = extra;
+}
+
+void Account::SetAccountToken(const std::string& account_id,
+ const std::string& token) {
+ std::lock_guard lock(mutex_);
+ // Hmm does this compare logic belong in here?
+ if (account_id_ == account_id) {
+ account_token_ = token;
+ }
+}
+
+void Account::SetAccount(AccountType account_type, AccountState account_state,
+ const std::string& account_name,
+ const std::string& account_id) {
+ bool call_account_changed = false;
+ {
+ std::lock_guard lock(mutex_);
+
+ // We call out to python so need to be in game thread.
+ assert(InGameThread());
+ if (account_state_ != account_state
+ || g_app_globals->account_type != account_type
+ || account_id_ != account_id || account_name_ != account_name) {
+ // Special case: if they sent a sign-out for an account type that is.
+ // currently not signed in, ignore it.
+ if (account_state == AccountState::kSignedOut
+ && (account_type != g_app_globals->account_type)) {
+ // No-op.
+ } else {
+ account_state_ = account_state;
+ g_app_globals->account_type = account_type;
+ account_id_ = account_id;
+ account_name_ = Utils::GetValidUTF8(account_name.c_str(), "gthm");
+
+ // If they signed out of an account, account type switches to invalid.
+ if (account_state == AccountState::kSignedOut) {
+ g_app_globals->account_type = AccountType::kInvalid;
+ }
+ account_state_num_ += 1;
+ call_account_changed = true;
+ }
+ }
+ }
+ if (call_account_changed) {
+ // Inform python layer this has changed.
+ g_python->AccountChanged();
+ }
+}
+
+void Account::SetProductsPurchased(const std::vector& products) {
+ std::lock_guard lock(mutex_);
+ std::map purchases_old = product_purchases_;
+ product_purchases_.clear();
+ for (auto&& i : products) {
+ product_purchases_[i] = true;
+ }
+ if (product_purchases_ != purchases_old) {
+ product_purchases_state_++;
+ }
+}
+
+auto Account::GetProductPurchased(const std::string& product) -> bool {
+ std::lock_guard lock(mutex_);
+ auto i = product_purchases_.find(product);
+ if (i == product_purchases_.end()) {
+ return false;
+ } else {
+ return i->second;
+ }
+}
+
+} // namespace ballistica
diff --git a/src/ballistica/game/account.h b/src/ballistica/game/account.h
new file mode 100644
index 00000000..79dc2f8b
--- /dev/null
+++ b/src/ballistica/game/account.h
@@ -0,0 +1,64 @@
+// Released under the MIT License. See LICENSE for details.
+
+#ifndef BALLISTICA_GAME_ACCOUNT_H_
+#define BALLISTICA_GAME_ACCOUNT_H_
+
+#include