diff --git a/.efrocachemap b/.efrocachemap index d16eda12..22375bdd 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3932,40 +3932,40 @@ "assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450", "assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e", "assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f", - "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d1/cd/67331a44c2d6f296bf77f33ee306", - "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/eb/0e/9ce47318a17ce9ae48c91c2da8d0", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6c/e6/7446860570852b068f72af2fb9fe", - "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/85/61/ce38df8bbb8ea1472a9669e4b6d7", - "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/61/83/1111ea2ea7fc3761acde2dc06292", - "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/88/9c/931d1c5f404fc66a5e458bb2f428", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/dc/52/6ad3df68aeaa90e9a43093f5b4d9", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6d/b8/1ecbd98f66ec260fcffeb64a9b37", - "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/67/78/2af711de47c5239ef26017aa30c5", - "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/13/94/db30b2bc3e2c1106a8fe83a079c6", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b5/88/4cf938c5876c74060ae87be8739f", - "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/fd/0e/c35f6920f03ef6b762948133b316", - "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/47/08/9bf4c023631178c59ae1bd272ca4", - "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/71/19/42f7719d481349cc1f5fe9a7d99d", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f5/57/af559c12b01375b3fcaf33481655", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5a/9d/870578d93d2b3b2c1bcc784f55e7", - "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/f5/14/a1ccbdf25ba24d1d46bcde6ae015", - "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/4a/ea/967d2fe1adab321afadc6144c56c", - "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/cb/d1/c43570bda2cbb6e6f8e767c054b9", - "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/cc/15/803086f664162eb61aae4363ee76", - "build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/bf/393694ea67f3d590dd2706c9955e", - "build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/78/cb/bb9ae4f896f862074057c8e36e1d", - "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ae/bd/39d7b885f7f01e81d0e96f0f85ce", - "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/30/da/709e6b36f4f3158843d3a39032c6", - "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c0/9b/5d60f10dbe2e6f670b9e177bce16", - "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/52/d9/563a6949d2c4db5a915c54460fbc", - "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d0/6a/42fe8d2e34f95e1b3282e8422344", - "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/50/cf/bad44b07a4022aee3001002086b5", - "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/30/e6/1f20540e32ee690d548bbe78e038", - "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/e8/4153e97345a2405df151702b8fc9", - "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ef/d5/76b650d50e50a839fda4e499c270", - "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b3/3d/38218c0f9a876513c854ed75e960", - "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7c/58/c16677ab8794b977e95671e007e1", - "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2e/e5/d6af87158a6209d96b5c0ef797c0", - "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c4/11/2082e99d03f4454f10dda7e56e6d", - "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7f/0a/fe4b2c683075cf837b9f0c37fe87" + "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/41/a1ef000678c7cb89f87133a8f570", + "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f8/12/c69a75fae714824ad525e43876d9", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/13/c2/f88ae12e42b164cc7ca9ed61e230", + "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/05/01/9aca815693cfc9200fe937a2ae58", + "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d6/20/7061a88a9dbd5c51eea45fce76bf", + "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/90/cb/be6d4aa11eb87cef4716d7e31901", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/17/df/23215ac9d4dacaa44edfd2310b91", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a7/ad/1ec53567ccbd6a83334516b1c29b", + "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/4c/f5/d4bb7ed9f5f8dd2e7a5efbdeb5fe", + "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d9/9c/0e65f40739f4023f2fd5c7c4fdf2", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ba/fd/ac27673e2a5d56edf1b01d88da67", + "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/39/4c/206eecc8816ba3d46c28030cb795", + "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b5/b5/7b5e887b9f0223f4372b97bd3e70", + "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/c0/388a49b4a8b2879c6924fade2cc6", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/55/9e/e4a8a4458b7582883873d473fb42", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b3/c6/8c6ef646c2aa04e218b8f4974dc2", + "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/65/73/6d3ed79e37a08f575df04145b43d", + "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/e9/03/60abb7a8cd8850fe4e1da24ff5ec", + "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/e2/76/0d2133bb2cbde40f684dc33e0720", + "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/e0/0e/36917b6deb6a079b73da41af358d", + "build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/11/a7/73334288aedb6a2f990ae204ada6", + "build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/14/20/4225a2af6c3893b9ab8b6ebd3e23", + "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a9/62/6166bba0b039be543105d1d7b642", + "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/eb/93/9d28ef49f8848703dfc6b233f7c1", + "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4c/51/0461da41b8cd8c02ff9260035e61", + "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ad/fa/7e4876b066d04ddef7d0cb60f44c", + "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/54/e3/ebd341c2c759ce067db1a740238b", + "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ec/bf/eb162e4704b9d970537ffe210d8d", + "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/aa/3a/a9ab538fb7754ae31870703fb253", + "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/51/8b/0fed5e510cc87557a79814211a05", + "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c4/6c/5f22862278b52e6d1b63d1f28b94", + "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b5/1f/983902fc58ea15a69653678f53b0", + "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a0/90/0d1a8771ad1798153180a28e453b", + "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/be/69/9072e5c66d0eb21727212843be8c", + "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/64/20/ee2ab6fee781ee8f1e2532c00dc2", + "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/22/1e/7178ea47b9331addd638c8e81b55" } \ No newline at end of file diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml index a2c67a25..6c885280 100644 --- a/.idea/dictionaries/ericf.xml +++ b/.idea/dictionaries/ericf.xml @@ -871,6 +871,7 @@ getcurrency getcwd getdata + gethostbyname getinputdevice getkillerplayer getlevel diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ab23ca..f58c665a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ ### 1.6.0 (20308) +- Revamped netcode significantly. We still don't have client-prediction, but things should (hopefully) feel much lower latency now. +- Added network debug graphs accessible by hitting F8. - Added private parties functionality (cloud hosted parties with associated codes making it easier to play with friends) - The meta subsystem now enables new plugins by default in headless builds. - Added option to save party in Manual tab diff --git a/ballisticacore-cmake/.idea/dictionaries/ericf.xml b/ballisticacore-cmake/.idea/dictionaries/ericf.xml index 1c5e9252..d2859507 100644 --- a/ballisticacore-cmake/.idea/dictionaries/ericf.xml +++ b/ballisticacore-cmake/.idea/dictionaries/ericf.xml @@ -372,6 +372,7 @@ getbitshigh getcollidemodel getdata + gethostbyname getifaddrs getinputdevice getline diff --git a/docs/ba_module.md b/docs/ba_module.md index b1229d5b..3d315ec9 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -

last updated on 2021-03-11 for Ballistica version 1.6.0 build 20323

+

last updated on 2021-03-19 for Ballistica version 1.6.0 build 20324

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_globals.h b/src/ballistica/app/app_globals.h index 16b817fd..62dc2a89 100644 --- a/src/ballistica/app/app_globals.h +++ b/src/ballistica/app/app_globals.h @@ -66,14 +66,15 @@ class AppGlobals { std::string user_config_dir; bool started_suicide{}; - // Netplay testing. - int buffer_time{1000 / 30}; + // Maximum time in milliseconds to buffer game input/output before sending + // it over the network. + int buffer_time{0}; - // How often we send dynamics sync packets. + // How often we send dynamics resync messages. int dynamics_sync_time{500}; // How many steps we sample for each bucket. - int delay_samples{20}; + 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). diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc index 18001bd8..a2e17cd8 100644 --- a/src/ballistica/ballistica.cc +++ b/src/ballistica/ballistica.cc @@ -21,7 +21,7 @@ namespace ballistica { // These are set automatically via script; don't change here. -const int kAppBuildNumber = 20323; +const int kAppBuildNumber = 20325; const char* kAppVersion = "1.6.0"; // Our standalone globals. diff --git a/src/ballistica/game/game.cc b/src/ballistica/game/game.cc index f5af83af..31836a57 100644 --- a/src/ballistica/game/game.cc +++ b/src/ballistica/game/game.cc @@ -1117,7 +1117,7 @@ void Game::PushToggleManualCameraCall() { } void Game::PushToggleDebugInfoDisplayCall() { - PushCall([] { g_graphics->ToggleDebugInfoDisplay(); }); + PushCall([] { g_graphics->ToggleNetworkDebugDisplay(); }); } void Game::PushToggleCollisionGeometryDisplayCall() { diff --git a/src/ballistica/game/session/client_session.h b/src/ballistica/game/session/client_session.h index 60330a47..6d01a8b3 100644 --- a/src/ballistica/game/session/client_session.h +++ b/src/ballistica/game/session/client_session.h @@ -21,20 +21,22 @@ class ClientSession : public Session { virtual auto GetActualTimeAdvance(int advance_in) -> int { return advance_in; } - void Update(int time_advance) override; - void Draw(FrameDef* f) override; - virtual void HandleSessionMessage(const std::vector& buffer); - void Reset(bool rewind); + auto Update(int time_advance) -> void override; + auto Draw(FrameDef* f) -> void override; + virtual auto HandleSessionMessage(const std::vector& buffer) -> void; + auto Reset(bool rewind) -> void; auto GetForegroundContext() -> Context override; auto DoesFillScreen() const -> bool override; - void ScreenSizeChanged() override; - void LanguageChanged() override; - auto shutting_down() const -> bool { return shutting_down_; } - void GetCorrectionMessages(bool blend, - std::vector >* messages); + auto ScreenSizeChanged() -> void override; + auto LanguageChanged() -> void override; + auto GetCorrectionMessages(bool blend, + std::vector >* messages) + -> void; - // Called when attempting to step without input data available. - virtual void OnCommandBufferUnderrun() {} + /// Called when attempting to step without input data available. + virtual auto OnCommandBufferUnderrun() -> void {} + + virtual auto OnBaseTimeStepAdded(int step) -> void {} // Returns existing objects; throws exceptions if not available. auto GetScene(int id) const -> Scene*; @@ -45,46 +47,83 @@ class ClientSession : public Session { auto GetMaterial(int id) const -> Material*; auto GetSound(int id) const -> Sound*; - protected: - virtual void OnReset(bool rewind); - virtual void FetchMessages() {} - int steps_on_list_; - std::list > commands_; // ready-to-go commands + auto base_time_buffered() const { return base_time_buffered_; } + auto consume_rate() const { return consume_rate_; } + auto set_consume_rate(float val) { consume_rate_ = val; } + auto target_base_time() const { return target_base_time_; } + auto base_time() const { return base_time_; } + auto shutting_down() const { return shutting_down_; } + + auto scenes() const -> const std::vector >& { + return scenes_; + } + auto nodes() const -> const std::vector >& { + return nodes_; + } + auto textures() const -> const std::vector >& { + return textures_; + } + auto models() const -> const std::vector >& { + return models_; + } + auto sounds() const -> const std::vector >& { + return sounds_; + } + auto collide_models() const + -> const std::vector >& { + return collide_models_; + } + auto materials() const -> const std::vector >& { + return materials_; + } + auto commands() const -> const std::list >& { + return commands_; + } + auto add_end_of_file_command() { + commands_.emplace_back(1, static_cast(SessionCommand::kEndOfFile)); + } + virtual auto OnReset(bool rewind) -> void; + virtual auto FetchMessages() -> void {} virtual void Error(const std::string& description); void End(); - millisecs_t base_time_; - double target_base_time_ = 0.0f; - bool shutting_down_; - std::vector least_buffered_count_list_; // move this to net-client?.. - std::vector most_buffered_count_list_; - int buffer_count_list_index_; - int adjust_counter_; - float correction_ = 1.0f; - float largest_spike_smoothed_ = 0.0f; - float low_pass_smoothed_ = 0.0f; + void DumpFullState(GameStream* out) override; + + /// Reset target base time to equal current. This can be used during command + /// buffer underruns to cause playback to pause momentarily instead of + /// skipping ahead to catch up. Generally desired for replays but not for + /// net-play. + auto ResetTargetBaseTime() -> void { target_base_time_ = base_time_; } private: void ClearSessionObjs(); void AddCommand(const std::vector& command); - // commands being built up for the next time step - // (we want to be able to run *everything* for a given timestep at once - // to avoid drawing things in half-changed states, etc) - std::list > commands_pending_; // commands for the next - std::vector current_cmd_; - uint8_t* current_cmd_ptr_; auto ReadByte() -> uint8_t; auto ReadInt32() -> int32_t; - void ReadInt32_2(int32_t* vals); - void ReadInt32_3(int32_t* vals); - void ReadInt32_4(int32_t* vals); + auto ReadInt32_2(int32_t* vals) -> void; + auto ReadInt32_3(int32_t* vals) -> void; + auto ReadInt32_4(int32_t* vals) -> void; auto ReadString() -> std::string; auto ReadFloat() -> float; - void ReadFloats(int count, float* vals); - void ReadInt32s(int count, int32_t* vals); - void ReadChars(int count, char* vals); + auto ReadFloats(int count, float* vals) -> void; + auto ReadInt32s(int count, int32_t* vals) -> void; + auto ReadChars(int count, char* vals) -> void; + + // Ready-to-go commands. + std::list > commands_; + + // Commands being built up for the next time step (we need to ship timesteps + // as a whole). + std::list > commands_pending_; + std::vector current_cmd_; + uint8_t* current_cmd_ptr_{}; + int base_time_buffered_{}; + bool shutting_down_{}; + + millisecs_t base_time_{}; + double target_base_time_{}; + float consume_rate_{1.0f}; - protected: std::vector > scenes_; std::vector > nodes_; std::vector > textures_; diff --git a/src/ballistica/game/session/net_client_session.h b/src/ballistica/game/session/net_client_session.h index 303d598a..32472a29 100644 --- a/src/ballistica/game/session/net_client_session.h +++ b/src/ballistica/game/session/net_client_session.h @@ -17,17 +17,44 @@ class NetClientSession : public ClientSession { auto connection_to_host() const -> ConnectionToHost* { return connection_to_host_.get(); } - void SetConnectionToHost(ConnectionToHost* c); - void HandleSessionMessage(const std::vector& buffer) override; - void OnCommandBufferUnderrun() override; - - protected: - void Update(int time_advance) override; + auto SetConnectionToHost(ConnectionToHost* c) -> void; + auto HandleSessionMessage(const std::vector& buffer) + -> void override; + auto OnCommandBufferUnderrun() -> void override; + auto Update(int time_advance) -> void override; + auto OnReset(bool rewind) -> void override; + auto OnBaseTimeStepAdded(int step) -> void override; private: - void UpdateBuffering(); - bool writing_replay_ = false; + struct SampleBucket { + // int least_buffered_count{}; + // int most_buffered_count{}; + int max_delay_from_projection{}; + }; + + auto ProjectedBaseTime(millisecs_t now) const -> millisecs_t { + return leading_base_time_received_ + + (now - leading_base_time_receive_time_); + } + auto UpdateBuffering() -> void; + auto GetBucketNum() -> int; + + bool writing_replay_{}; + millisecs_t base_time_received_{}; + millisecs_t last_base_time_receive_time_{}; + millisecs_t leading_base_time_received_{}; + millisecs_t leading_base_time_receive_time_{}; Object::WeakRef connection_to_host_; + std::vector buckets_{5}; + + // float bucket_max_smoothed_{}; + // float bucket_min_smoothed_{}; + float max_delay_smoothed_{}; + float last_bucket_max_delay_{}; + float current_delay_{}; + + int delay_sample_counter_{}; + int adjust_counter_{}; }; } // namespace ballistica diff --git a/src/ballistica/game/session/replay_client_session.h b/src/ballistica/game/session/replay_client_session.h index c6b146b6..411da3db 100644 --- a/src/ballistica/game/session/replay_client_session.h +++ b/src/ballistica/game/session/replay_client_session.h @@ -17,25 +17,24 @@ class ReplayClientSession : public ClientSession, public: explicit ReplayClientSession(std::string filename); ~ReplayClientSession() override; - void OnReset(bool rewind) override; + auto OnReset(bool rewind) -> void override; // Our ClientControllerInterface implementation. auto GetActualTimeAdvance(int advance_in) -> int override; - void OnClientConnected(ConnectionToClient* c) override; - void OnClientDisconnected(ConnectionToClient* c) override; - void DumpFullState(GameStream* out) override; + auto OnClientConnected(ConnectionToClient* c) -> void override; + auto OnClientDisconnected(ConnectionToClient* c) -> void override; + auto OnCommandBufferUnderrun() -> void override; - protected: - void Error(const std::string& description) override; - void FetchMessages() override; + auto Error(const std::string& description) -> void override; + auto FetchMessages() -> void override; private: - uint32_t message_fetch_num_; - bool have_sent_client_message_; + uint32_t message_fetch_num_{}; + bool have_sent_client_message_{}; std::vector connections_to_clients_; std::vector connections_to_clients_ignored_; std::string file_name_; - FILE* file_; + FILE* file_{}; }; } // namespace ballistica diff --git a/src/ballistica/graphics/graphics.cc b/src/ballistica/graphics/graphics.cc index 9c766e6c..ebd9b92c 100644 --- a/src/ballistica/graphics/graphics.cc +++ b/src/ballistica/graphics/graphics.cc @@ -386,16 +386,22 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) { } } - // Draw debug graphs. - if (explicit_bool(false)) { - if (!debug_graph_1_.exists()) { - debug_graph_1_ = Object::New(); + // Draw any debug graphs. + { + float debug_graph_y = 50.0; + auto now = GetRealTime(); + for (auto it = debug_graphs_.begin(); it != debug_graphs_.end();) { + assert(it->second.exists()); + if (now - it->second->LastUsedTime() > 1000) { + it = debug_graphs_.erase(it); + } else { + it->second->Draw(pass, GetRealTime(), 50.0f, debug_graph_y, 500.0f, + 100.0f); + debug_graph_y += 110.0f; + + ++it; + } } - debug_graph_1_->Draw(pass, GetRealTime(), 50.0f, 50.0f, 500.0f, 100.0f); - if (!debug_graph_2_.exists()) { - debug_graph_2_ = Object::New(); - } - debug_graph_2_->Draw(pass, GetRealTime(), 50.0f, 160.0f, 500.0f, 100.0f); } // Screen messages (bottom). @@ -736,6 +742,18 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) { } } +auto Graphics::GetDebugGraph(const std::string& name, bool smoothed) + -> NetGraph* { + auto out = debug_graphs_.find(name); + if (out == debug_graphs_.end()) { + debug_graphs_[name] = Object::New(); + debug_graphs_[name]->SetLabel(name); + debug_graphs_[name]->SetSmoothed(smoothed); + } + debug_graphs_[name]->SetLastUsedTime(GetRealTime()); + return debug_graphs_[name].get(); +} + void Graphics::GetSafeColor(float* red, float* green, float* blue, float target_intensity) { assert(red && green && blue); @@ -1462,13 +1480,13 @@ void Graphics::LocalCameraShake(float mag) { } } -void Graphics::ToggleDebugInfoDisplay() { +void Graphics::ToggleNetworkDebugDisplay() { assert(InGameThread()); - debug_info_display_ = !debug_info_display_; - if (debug_info_display_) { - ScreenMessage("debug info on\n"); + network_debug_display_enabled_ = !network_debug_display_enabled_; + if (network_debug_display_enabled_) { + ScreenMessage("Network Debug Display Enabled"); } else { - ScreenMessage("debug info off\n"); + ScreenMessage("Network Debug Display Disabled"); } } diff --git a/src/ballistica/graphics/graphics.h b/src/ballistica/graphics/graphics.h index 57a327e4..56f8d789 100644 --- a/src/ballistica/graphics/graphics.h +++ b/src/ballistica/graphics/graphics.h @@ -129,8 +129,10 @@ class Graphics { auto ToggleManualCamera() -> void; auto LocalCameraShake(float intensity) -> void; auto ToggleDebugDraw() -> void; - auto debug_info_display() const -> bool { return debug_info_display_; } - auto ToggleDebugInfoDisplay() -> void; + auto network_debug_info_display_enabled() const -> bool { + return network_debug_display_enabled_; + } + auto ToggleNetworkDebugDisplay() -> void; auto SetGyroEnabled(bool enable) -> void; auto floor_reflection() const -> bool { assert(InGameThread()); @@ -265,8 +267,7 @@ class Graphics { auto set_gyro_vals(const Vector3f& vals) -> void { gyro_vals_ = vals; } auto show_net_info() const -> bool { return show_net_info_; } auto set_show_net_info(bool val) -> void { show_net_info_ = val; } - auto debug_graph_1() const -> NetGraph* { return debug_graph_1_.get(); } - auto debug_graph_2() const -> NetGraph* { return debug_graph_2_.get(); } + auto GetDebugGraph(const std::string& name, bool smoothed) -> NetGraph*; // Used by meshes. auto AddMeshDataCreate(MeshData* d) -> void; @@ -372,12 +373,11 @@ class Graphics { bool show_net_info_{}; bool tv_border_{}; bool floor_reflection_{}; - Object::Ref debug_graph_1_; - Object::Ref debug_graph_2_; + std::map > debug_graphs_; std::mutex frame_def_delete_list_mutex_; std::vector frame_def_delete_list_; bool debug_draw_{}; - bool debug_info_display_{}; + bool network_debug_display_enabled_{}; Object::Ref camera_; millisecs_t next_stat_update_time_{}; int last_total_frames_rendered_{}; diff --git a/src/ballistica/graphics/net_graph.cc b/src/ballistica/graphics/net_graph.cc index 1a618646..977c34d3 100644 --- a/src/ballistica/graphics/net_graph.cc +++ b/src/ballistica/graphics/net_graph.cc @@ -14,16 +14,30 @@ class NetGraph::Impl { std::list> samples; double duration = 2000.0; double v_max_smoothed = 1.0; + double v_smoothed = 0.0; + bool smoothed = false; + std::string label; ImageMesh bg_mesh; MeshIndexedSimpleFull value_mesh; TextGroup max_vel_text; + millisecs_t last_used_time{}; }; NetGraph::NetGraph() : impl_(new NetGraph::Impl()) {} NetGraph::~NetGraph() = default; -void NetGraph::AddSample(double time, double value) { +auto NetGraph::SetLabel(const std::string& label) -> void { + impl_->label = label; +} +auto NetGraph::SetSmoothed(bool val) -> void { impl_->smoothed = val; } + +auto NetGraph::SetLastUsedTime(millisecs_t real_time) -> void { + impl_->last_used_time = real_time; +} +auto NetGraph::LastUsedTime() -> millisecs_t { return impl_->last_used_time; } + +auto NetGraph::AddSample(double time, double value) -> void { impl_->samples.emplace_back(time, value); double cutoffTime = time - impl_->duration; @@ -49,6 +63,8 @@ void NetGraph::Draw(RenderPass* pass, double time, double x, double y, double w, int num_samples = static_cast(impl_->samples.size()); + double val = 0.0; + // Draw values (provided we have at least 2 samples) bool draw_values = (num_samples >= 2); if (draw_values) { @@ -66,8 +82,10 @@ void NetGraph::Draw(RenderPass* pass, double time, double x, double y, double w, } } double smoothing = 0.95; + val = impl_->samples.back().second; impl_->v_max_smoothed = smoothing * impl_->v_max_smoothed + (1.0 - smoothing) * v_max * 1.1; + impl_->v_smoothed = smoothing * impl_->v_smoothed + (1.0 - smoothing) * val; double v_top = impl_->v_max_smoothed; double v_height = v_top - v_bottom; @@ -129,7 +147,14 @@ void NetGraph::Draw(RenderPass* pass, double time, double x, double y, double w, c.Submit(); char val_str[32]; - snprintf(val_str, sizeof(val_str), "%.2f", impl_->v_max_smoothed); + if (!impl_->label.empty()) { + snprintf(val_str, sizeof(val_str), "%s %.3f", impl_->label.c_str(), + impl_->smoothed ? impl_->v_smoothed : val); + + } else { + snprintf(val_str, sizeof(val_str), "%.3f", + impl_->smoothed ? impl_->v_smoothed : val); + } impl_->max_vel_text.SetText(val_str, TextMesh::HAlign::kLeft, TextMesh::VAlign::kTop); diff --git a/src/ballistica/graphics/net_graph.h b/src/ballistica/graphics/net_graph.h index 40b72227..80ca1ede 100644 --- a/src/ballistica/graphics/net_graph.h +++ b/src/ballistica/graphics/net_graph.h @@ -4,6 +4,7 @@ #define BALLISTICA_GRAPHICS_NET_GRAPH_H_ #include +#include #include "ballistica/core/object.h" @@ -13,9 +14,13 @@ class NetGraph : public Object { public: NetGraph(); ~NetGraph() override; - void AddSample(double time, double value); - void Draw(RenderPass* pass, double time, double x, double y, double w, - double h); + auto AddSample(double time, double value) -> void; + auto SetLabel(const std::string& label) -> void; + auto SetLastUsedTime(millisecs_t real_time) -> void; + auto LastUsedTime() -> millisecs_t; + auto SetSmoothed(bool smoothed) -> void; + auto Draw(RenderPass* pass, double time, double x, double y, double w, + double h) -> void; private: class Impl; diff --git a/src/ballistica/input/device/input_device.cc b/src/ballistica/input/device/input_device.cc index b36ebf76..cf790475 100644 --- a/src/ballistica/input/device/input_device.cc +++ b/src/ballistica/input/device/input_device.cc @@ -248,10 +248,11 @@ void InputDevice::ShipBufferIfFull() { // Ship the buffer once it gets big enough or once enough time has passed. millisecs_t real_time = GetRealTime(); + size_t size = remote_input_commands_buffer_.size(); if (size > 2 && (static_cast(real_time - last_remote_input_commands_send_time_) - > g_app_globals->buffer_time + >= g_app_globals->buffer_time || size > 400)) { last_remote_input_commands_send_time_ = real_time; hc->SendReliableMessage(remote_input_commands_buffer_); diff --git a/src/ballistica/python/methods/python_methods_system.cc b/src/ballistica/python/methods/python_methods_system.cc index df6c0423..6d470294 100644 --- a/src/ballistica/python/methods/python_methods_system.cc +++ b/src/ballistica/python/methods/python_methods_system.cc @@ -281,13 +281,14 @@ auto PyValueTest(PyObject* self, PyObject* args, PyObject* keywds) return_val = g_app_globals->buffer_time; } else if (!strcmp(arg, "delaySampling")) { if (have_change) { - g_app_globals->delay_samples += static_cast(change); + g_app_globals->delay_bucket_samples += static_cast(change); } if (have_absolute) { g_app_globals->buffer_time = static_cast(absolute); } - g_app_globals->delay_samples = std::max(1, g_app_globals->delay_samples); - return_val = g_app_globals->delay_samples; + g_app_globals->delay_bucket_samples = + std::max(1, g_app_globals->delay_bucket_samples); + return_val = g_app_globals->delay_bucket_samples; } else if (!strcmp(arg, "dynamicsSyncTime")) { if (have_change) { g_app_globals->dynamics_sync_time += static_cast(change);