netplay work

This commit is contained in:
Eric Froemling 2021-03-19 17:18:37 -05:00
parent 205635d51f
commit 9192b4f50e
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
17 changed files with 250 additions and 130 deletions

View File

@ -3932,40 +3932,40 @@
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450", "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/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", "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/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/41/a1ef000678c7cb89f87133a8f570",
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/eb/0e/9ce47318a17ce9ae48c91c2da8d0", "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/6c/e6/7446860570852b068f72af2fb9fe", "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/85/61/ce38df8bbb8ea1472a9669e4b6d7", "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/61/83/1111ea2ea7fc3761acde2dc06292", "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/88/9c/931d1c5f404fc66a5e458bb2f428", "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/dc/52/6ad3df68aeaa90e9a43093f5b4d9", "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/6d/b8/1ecbd98f66ec260fcffeb64a9b37", "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/67/78/2af711de47c5239ef26017aa30c5", "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/13/94/db30b2bc3e2c1106a8fe83a079c6", "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/b5/88/4cf938c5876c74060ae87be8739f", "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/fd/0e/c35f6920f03ef6b762948133b316", "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/47/08/9bf4c023631178c59ae1bd272ca4", "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/71/19/42f7719d481349cc1f5fe9a7d99d", "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/f5/57/af559c12b01375b3fcaf33481655", "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/5a/9d/870578d93d2b3b2c1bcc784f55e7", "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/f5/14/a1ccbdf25ba24d1d46bcde6ae015", "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/4a/ea/967d2fe1adab321afadc6144c56c", "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/cb/d1/c43570bda2cbb6e6f8e767c054b9", "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/cc/15/803086f664162eb61aae4363ee76", "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/4c/bf/393694ea67f3d590dd2706c9955e", "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/78/cb/bb9ae4f896f862074057c8e36e1d", "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/ae/bd/39d7b885f7f01e81d0e96f0f85ce", "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/30/da/709e6b36f4f3158843d3a39032c6", "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/c0/9b/5d60f10dbe2e6f670b9e177bce16", "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/52/d9/563a6949d2c4db5a915c54460fbc", "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/d0/6a/42fe8d2e34f95e1b3282e8422344", "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/50/cf/bad44b07a4022aee3001002086b5", "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/30/e6/1f20540e32ee690d548bbe78e038", "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/8f/e8/4153e97345a2405df151702b8fc9", "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/ef/d5/76b650d50e50a839fda4e499c270", "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/b3/3d/38218c0f9a876513c854ed75e960", "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/7c/58/c16677ab8794b977e95671e007e1", "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/2e/e5/d6af87158a6209d96b5c0ef797c0", "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/c4/11/2082e99d03f4454f10dda7e56e6d", "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/7f/0a/fe4b2c683075cf837b9f0c37fe87" "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/22/1e/7178ea47b9331addd638c8e81b55"
} }

View File

@ -871,6 +871,7 @@
<w>getcurrency</w> <w>getcurrency</w>
<w>getcwd</w> <w>getcwd</w>
<w>getdata</w> <w>getdata</w>
<w>gethostbyname</w>
<w>getinputdevice</w> <w>getinputdevice</w>
<w>getkillerplayer</w> <w>getkillerplayer</w>
<w>getlevel</w> <w>getlevel</w>

View File

@ -1,4 +1,6 @@
### 1.6.0 (20308) ### 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) - 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. - The meta subsystem now enables new plugins by default in headless builds.
- Added option to save party in Manual tab - Added option to save party in Manual tab

View File

@ -372,6 +372,7 @@
<w>getbitshigh</w> <w>getbitshigh</w>
<w>getcollidemodel</w> <w>getcollidemodel</w>
<w>getdata</w> <w>getdata</w>
<w>gethostbyname</w>
<w>getifaddrs</w> <w>getifaddrs</w>
<w>getinputdevice</w> <w>getinputdevice</w>
<w>getline</w> <w>getline</w>

View File

@ -1,5 +1,5 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND --> <!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
<h4><em>last updated on 2021-03-11 for Ballistica version 1.6.0 build 20323</em></h4> <h4><em>last updated on 2021-03-19 for Ballistica version 1.6.0 build 20324</em></h4>
<p>This page documents the Python classes and functions in the 'ba' module, <p>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 <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p> 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 <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
<hr> <hr>

View File

@ -66,14 +66,15 @@ class AppGlobals {
std::string user_config_dir; std::string user_config_dir;
bool started_suicide{}; bool started_suicide{};
// Netplay testing. // Maximum time in milliseconds to buffer game input/output before sending
int buffer_time{1000 / 30}; // 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}; int dynamics_sync_time{500};
// How many steps we sample for each bucket. // How many steps we sample for each bucket.
int delay_samples{20}; int delay_bucket_samples{60};
bool vr_mode{g_buildconfig.vr_build()}; bool vr_mode{g_buildconfig.vr_build()};
// Temp dirty way to do some shutdown stuff (FIXME: move to an App method). // Temp dirty way to do some shutdown stuff (FIXME: move to an App method).

View File

@ -21,7 +21,7 @@
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't change here. // These are set automatically via script; don't change here.
const int kAppBuildNumber = 20323; const int kAppBuildNumber = 20325;
const char* kAppVersion = "1.6.0"; const char* kAppVersion = "1.6.0";
// Our standalone globals. // Our standalone globals.

View File

@ -1117,7 +1117,7 @@ void Game::PushToggleManualCameraCall() {
} }
void Game::PushToggleDebugInfoDisplayCall() { void Game::PushToggleDebugInfoDisplayCall() {
PushCall([] { g_graphics->ToggleDebugInfoDisplay(); }); PushCall([] { g_graphics->ToggleNetworkDebugDisplay(); });
} }
void Game::PushToggleCollisionGeometryDisplayCall() { void Game::PushToggleCollisionGeometryDisplayCall() {

View File

@ -21,20 +21,22 @@ class ClientSession : public Session {
virtual auto GetActualTimeAdvance(int advance_in) -> int { virtual auto GetActualTimeAdvance(int advance_in) -> int {
return advance_in; return advance_in;
} }
void Update(int time_advance) override; auto Update(int time_advance) -> void override;
void Draw(FrameDef* f) override; auto Draw(FrameDef* f) -> void override;
virtual void HandleSessionMessage(const std::vector<uint8_t>& buffer); virtual auto HandleSessionMessage(const std::vector<uint8_t>& buffer) -> void;
void Reset(bool rewind); auto Reset(bool rewind) -> void;
auto GetForegroundContext() -> Context override; auto GetForegroundContext() -> Context override;
auto DoesFillScreen() const -> bool override; auto DoesFillScreen() const -> bool override;
void ScreenSizeChanged() override; auto ScreenSizeChanged() -> void override;
void LanguageChanged() override; auto LanguageChanged() -> void override;
auto shutting_down() const -> bool { return shutting_down_; } auto GetCorrectionMessages(bool blend,
void GetCorrectionMessages(bool blend, std::vector<std::vector<uint8_t> >* messages)
std::vector<std::vector<uint8_t> >* messages); -> void;
// Called when attempting to step without input data available. /// Called when attempting to step without input data available.
virtual void OnCommandBufferUnderrun() {} virtual auto OnCommandBufferUnderrun() -> void {}
virtual auto OnBaseTimeStepAdded(int step) -> void {}
// Returns existing objects; throws exceptions if not available. // Returns existing objects; throws exceptions if not available.
auto GetScene(int id) const -> Scene*; auto GetScene(int id) const -> Scene*;
@ -45,46 +47,83 @@ class ClientSession : public Session {
auto GetMaterial(int id) const -> Material*; auto GetMaterial(int id) const -> Material*;
auto GetSound(int id) const -> Sound*; auto GetSound(int id) const -> Sound*;
protected: auto base_time_buffered() const { return base_time_buffered_; }
virtual void OnReset(bool rewind); auto consume_rate() const { return consume_rate_; }
virtual void FetchMessages() {} auto set_consume_rate(float val) { consume_rate_ = val; }
int steps_on_list_; auto target_base_time() const { return target_base_time_; }
std::list<std::vector<uint8_t> > commands_; // ready-to-go commands auto base_time() const { return base_time_; }
auto shutting_down() const { return shutting_down_; }
auto scenes() const -> const std::vector<Object::Ref<Scene> >& {
return scenes_;
}
auto nodes() const -> const std::vector<Object::WeakRef<Node> >& {
return nodes_;
}
auto textures() const -> const std::vector<Object::Ref<Texture> >& {
return textures_;
}
auto models() const -> const std::vector<Object::Ref<Model> >& {
return models_;
}
auto sounds() const -> const std::vector<Object::Ref<Sound> >& {
return sounds_;
}
auto collide_models() const
-> const std::vector<Object::Ref<CollideModel> >& {
return collide_models_;
}
auto materials() const -> const std::vector<Object::Ref<Material> >& {
return materials_;
}
auto commands() const -> const std::list<std::vector<uint8_t> >& {
return commands_;
}
auto add_end_of_file_command() {
commands_.emplace_back(1, static_cast<uint8_t>(SessionCommand::kEndOfFile));
}
virtual auto OnReset(bool rewind) -> void;
virtual auto FetchMessages() -> void {}
virtual void Error(const std::string& description); virtual void Error(const std::string& description);
void End(); void End();
millisecs_t base_time_; void DumpFullState(GameStream* out) override;
double target_base_time_ = 0.0f;
bool shutting_down_; /// Reset target base time to equal current. This can be used during command
std::vector<int> least_buffered_count_list_; // move this to net-client?.. /// buffer underruns to cause playback to pause momentarily instead of
std::vector<int> most_buffered_count_list_; /// skipping ahead to catch up. Generally desired for replays but not for
int buffer_count_list_index_; /// net-play.
int adjust_counter_; auto ResetTargetBaseTime() -> void { target_base_time_ = base_time_; }
float correction_ = 1.0f;
float largest_spike_smoothed_ = 0.0f;
float low_pass_smoothed_ = 0.0f;
private: private:
void ClearSessionObjs(); void ClearSessionObjs();
void AddCommand(const std::vector<uint8_t>& command); void AddCommand(const std::vector<uint8_t>& 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<std::vector<uint8_t> > commands_pending_; // commands for the next
std::vector<uint8_t> current_cmd_;
uint8_t* current_cmd_ptr_;
auto ReadByte() -> uint8_t; auto ReadByte() -> uint8_t;
auto ReadInt32() -> int32_t; auto ReadInt32() -> int32_t;
void ReadInt32_2(int32_t* vals); auto ReadInt32_2(int32_t* vals) -> void;
void ReadInt32_3(int32_t* vals); auto ReadInt32_3(int32_t* vals) -> void;
void ReadInt32_4(int32_t* vals); auto ReadInt32_4(int32_t* vals) -> void;
auto ReadString() -> std::string; auto ReadString() -> std::string;
auto ReadFloat() -> float; auto ReadFloat() -> float;
void ReadFloats(int count, float* vals); auto ReadFloats(int count, float* vals) -> void;
void ReadInt32s(int count, int32_t* vals); auto ReadInt32s(int count, int32_t* vals) -> void;
void ReadChars(int count, char* vals); auto ReadChars(int count, char* vals) -> void;
// Ready-to-go commands.
std::list<std::vector<uint8_t> > commands_;
// Commands being built up for the next time step (we need to ship timesteps
// as a whole).
std::list<std::vector<uint8_t> > commands_pending_;
std::vector<uint8_t> 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<Object::Ref<Scene> > scenes_; std::vector<Object::Ref<Scene> > scenes_;
std::vector<Object::WeakRef<Node> > nodes_; std::vector<Object::WeakRef<Node> > nodes_;
std::vector<Object::Ref<Texture> > textures_; std::vector<Object::Ref<Texture> > textures_;

View File

@ -17,17 +17,44 @@ class NetClientSession : public ClientSession {
auto connection_to_host() const -> ConnectionToHost* { auto connection_to_host() const -> ConnectionToHost* {
return connection_to_host_.get(); return connection_to_host_.get();
} }
void SetConnectionToHost(ConnectionToHost* c); auto SetConnectionToHost(ConnectionToHost* c) -> void;
void HandleSessionMessage(const std::vector<uint8_t>& buffer) override; auto HandleSessionMessage(const std::vector<uint8_t>& buffer)
void OnCommandBufferUnderrun() override; -> void override;
auto OnCommandBufferUnderrun() -> void override;
protected: auto Update(int time_advance) -> void override;
void Update(int time_advance) override; auto OnReset(bool rewind) -> void override;
auto OnBaseTimeStepAdded(int step) -> void override;
private: private:
void UpdateBuffering(); struct SampleBucket {
bool writing_replay_ = false; // 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<ConnectionToHost> connection_to_host_; Object::WeakRef<ConnectionToHost> connection_to_host_;
std::vector<SampleBucket> buckets_{5};
// float bucket_max_smoothed_{};
// float bucket_min_smoothed_{};
float max_delay_smoothed_{};
float last_bucket_max_delay_{};
float current_delay_{};
int delay_sample_counter_{};
int adjust_counter_{};
}; };
} // namespace ballistica } // namespace ballistica

View File

@ -17,25 +17,24 @@ class ReplayClientSession : public ClientSession,
public: public:
explicit ReplayClientSession(std::string filename); explicit ReplayClientSession(std::string filename);
~ReplayClientSession() override; ~ReplayClientSession() override;
void OnReset(bool rewind) override; auto OnReset(bool rewind) -> void override;
// Our ClientControllerInterface implementation. // Our ClientControllerInterface implementation.
auto GetActualTimeAdvance(int advance_in) -> int override; auto GetActualTimeAdvance(int advance_in) -> int override;
void OnClientConnected(ConnectionToClient* c) override; auto OnClientConnected(ConnectionToClient* c) -> void override;
void OnClientDisconnected(ConnectionToClient* c) override; auto OnClientDisconnected(ConnectionToClient* c) -> void override;
void DumpFullState(GameStream* out) override; auto OnCommandBufferUnderrun() -> void override;
protected: auto Error(const std::string& description) -> void override;
void Error(const std::string& description) override; auto FetchMessages() -> void override;
void FetchMessages() override;
private: private:
uint32_t message_fetch_num_; uint32_t message_fetch_num_{};
bool have_sent_client_message_; bool have_sent_client_message_{};
std::vector<ConnectionToClient*> connections_to_clients_; std::vector<ConnectionToClient*> connections_to_clients_;
std::vector<ConnectionToClient*> connections_to_clients_ignored_; std::vector<ConnectionToClient*> connections_to_clients_ignored_;
std::string file_name_; std::string file_name_;
FILE* file_; FILE* file_{};
}; };
} // namespace ballistica } // namespace ballistica

View File

@ -386,16 +386,22 @@ void Graphics::DrawMiscOverlays(RenderPass* pass) {
} }
} }
// Draw debug graphs. // Draw any debug graphs.
if (explicit_bool(false)) { {
if (!debug_graph_1_.exists()) { float debug_graph_y = 50.0;
debug_graph_1_ = Object::New<NetGraph>(); 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<NetGraph>();
}
debug_graph_2_->Draw(pass, GetRealTime(), 50.0f, 160.0f, 500.0f, 100.0f);
} }
// Screen messages (bottom). // 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<NetGraph>();
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, void Graphics::GetSafeColor(float* red, float* green, float* blue,
float target_intensity) { float target_intensity) {
assert(red && green && blue); assert(red && green && blue);
@ -1462,13 +1480,13 @@ void Graphics::LocalCameraShake(float mag) {
} }
} }
void Graphics::ToggleDebugInfoDisplay() { void Graphics::ToggleNetworkDebugDisplay() {
assert(InGameThread()); assert(InGameThread());
debug_info_display_ = !debug_info_display_; network_debug_display_enabled_ = !network_debug_display_enabled_;
if (debug_info_display_) { if (network_debug_display_enabled_) {
ScreenMessage("debug info on\n"); ScreenMessage("Network Debug Display Enabled");
} else { } else {
ScreenMessage("debug info off\n"); ScreenMessage("Network Debug Display Disabled");
} }
} }

View File

@ -129,8 +129,10 @@ class Graphics {
auto ToggleManualCamera() -> void; auto ToggleManualCamera() -> void;
auto LocalCameraShake(float intensity) -> void; auto LocalCameraShake(float intensity) -> void;
auto ToggleDebugDraw() -> void; auto ToggleDebugDraw() -> void;
auto debug_info_display() const -> bool { return debug_info_display_; } auto network_debug_info_display_enabled() const -> bool {
auto ToggleDebugInfoDisplay() -> void; return network_debug_display_enabled_;
}
auto ToggleNetworkDebugDisplay() -> void;
auto SetGyroEnabled(bool enable) -> void; auto SetGyroEnabled(bool enable) -> void;
auto floor_reflection() const -> bool { auto floor_reflection() const -> bool {
assert(InGameThread()); assert(InGameThread());
@ -265,8 +267,7 @@ class Graphics {
auto set_gyro_vals(const Vector3f& vals) -> void { gyro_vals_ = vals; } auto set_gyro_vals(const Vector3f& vals) -> void { gyro_vals_ = vals; }
auto show_net_info() const -> bool { return show_net_info_; } auto show_net_info() const -> bool { return show_net_info_; }
auto set_show_net_info(bool val) -> void { show_net_info_ = val; } auto set_show_net_info(bool val) -> void { show_net_info_ = val; }
auto debug_graph_1() const -> NetGraph* { return debug_graph_1_.get(); } auto GetDebugGraph(const std::string& name, bool smoothed) -> NetGraph*;
auto debug_graph_2() const -> NetGraph* { return debug_graph_2_.get(); }
// Used by meshes. // Used by meshes.
auto AddMeshDataCreate(MeshData* d) -> void; auto AddMeshDataCreate(MeshData* d) -> void;
@ -372,12 +373,11 @@ class Graphics {
bool show_net_info_{}; bool show_net_info_{};
bool tv_border_{}; bool tv_border_{};
bool floor_reflection_{}; bool floor_reflection_{};
Object::Ref<NetGraph> debug_graph_1_; std::map<std::string, Object::Ref<NetGraph> > debug_graphs_;
Object::Ref<NetGraph> debug_graph_2_;
std::mutex frame_def_delete_list_mutex_; std::mutex frame_def_delete_list_mutex_;
std::vector<FrameDef*> frame_def_delete_list_; std::vector<FrameDef*> frame_def_delete_list_;
bool debug_draw_{}; bool debug_draw_{};
bool debug_info_display_{}; bool network_debug_display_enabled_{};
Object::Ref<Camera> camera_; Object::Ref<Camera> camera_;
millisecs_t next_stat_update_time_{}; millisecs_t next_stat_update_time_{};
int last_total_frames_rendered_{}; int last_total_frames_rendered_{};

View File

@ -14,16 +14,30 @@ class NetGraph::Impl {
std::list<std::pair<double, float>> samples; std::list<std::pair<double, float>> samples;
double duration = 2000.0; double duration = 2000.0;
double v_max_smoothed = 1.0; double v_max_smoothed = 1.0;
double v_smoothed = 0.0;
bool smoothed = false;
std::string label;
ImageMesh bg_mesh; ImageMesh bg_mesh;
MeshIndexedSimpleFull value_mesh; MeshIndexedSimpleFull value_mesh;
TextGroup max_vel_text; TextGroup max_vel_text;
millisecs_t last_used_time{};
}; };
NetGraph::NetGraph() : impl_(new NetGraph::Impl()) {} NetGraph::NetGraph() : impl_(new NetGraph::Impl()) {}
NetGraph::~NetGraph() = default; 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); impl_->samples.emplace_back(time, value);
double cutoffTime = time - impl_->duration; 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<int>(impl_->samples.size()); int num_samples = static_cast<int>(impl_->samples.size());
double val = 0.0;
// Draw values (provided we have at least 2 samples) // Draw values (provided we have at least 2 samples)
bool draw_values = (num_samples >= 2); bool draw_values = (num_samples >= 2);
if (draw_values) { if (draw_values) {
@ -66,8 +82,10 @@ void NetGraph::Draw(RenderPass* pass, double time, double x, double y, double w,
} }
} }
double smoothing = 0.95; double smoothing = 0.95;
val = impl_->samples.back().second;
impl_->v_max_smoothed = impl_->v_max_smoothed =
smoothing * impl_->v_max_smoothed + (1.0 - smoothing) * v_max * 1.1; 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_top = impl_->v_max_smoothed;
double v_height = v_top - v_bottom; 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(); c.Submit();
char val_str[32]; 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, impl_->max_vel_text.SetText(val_str, TextMesh::HAlign::kLeft,
TextMesh::VAlign::kTop); TextMesh::VAlign::kTop);

View File

@ -4,6 +4,7 @@
#define BALLISTICA_GRAPHICS_NET_GRAPH_H_ #define BALLISTICA_GRAPHICS_NET_GRAPH_H_
#include <memory> #include <memory>
#include <string>
#include "ballistica/core/object.h" #include "ballistica/core/object.h"
@ -13,9 +14,13 @@ class NetGraph : public Object {
public: public:
NetGraph(); NetGraph();
~NetGraph() override; ~NetGraph() override;
void AddSample(double time, double value); auto AddSample(double time, double value) -> void;
void Draw(RenderPass* pass, double time, double x, double y, double w, auto SetLabel(const std::string& label) -> void;
double h); 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: private:
class Impl; class Impl;

View File

@ -248,10 +248,11 @@ void InputDevice::ShipBufferIfFull() {
// Ship the buffer once it gets big enough or once enough time has passed. // Ship the buffer once it gets big enough or once enough time has passed.
millisecs_t real_time = GetRealTime(); millisecs_t real_time = GetRealTime();
size_t size = remote_input_commands_buffer_.size(); size_t size = remote_input_commands_buffer_.size();
if (size > 2 if (size > 2
&& (static_cast<int>(real_time - last_remote_input_commands_send_time_) && (static_cast<int>(real_time - last_remote_input_commands_send_time_)
> g_app_globals->buffer_time >= g_app_globals->buffer_time
|| size > 400)) { || size > 400)) {
last_remote_input_commands_send_time_ = real_time; last_remote_input_commands_send_time_ = real_time;
hc->SendReliableMessage(remote_input_commands_buffer_); hc->SendReliableMessage(remote_input_commands_buffer_);

View File

@ -281,13 +281,14 @@ auto PyValueTest(PyObject* self, PyObject* args, PyObject* keywds)
return_val = g_app_globals->buffer_time; return_val = g_app_globals->buffer_time;
} else if (!strcmp(arg, "delaySampling")) { } else if (!strcmp(arg, "delaySampling")) {
if (have_change) { if (have_change) {
g_app_globals->delay_samples += static_cast<int>(change); g_app_globals->delay_bucket_samples += static_cast<int>(change);
} }
if (have_absolute) { if (have_absolute) {
g_app_globals->buffer_time = static_cast<int>(absolute); g_app_globals->buffer_time = static_cast<int>(absolute);
} }
g_app_globals->delay_samples = std::max(1, g_app_globals->delay_samples); g_app_globals->delay_bucket_samples =
return_val = g_app_globals->delay_samples; std::max(1, g_app_globals->delay_bucket_samples);
return_val = g_app_globals->delay_bucket_samples;
} else if (!strcmp(arg, "dynamicsSyncTime")) { } else if (!strcmp(arg, "dynamicsSyncTime")) {
if (have_change) { if (have_change) {
g_app_globals->dynamics_sync_time += static_cast<int>(change); g_app_globals->dynamics_sync_time += static_cast<int>(change);