Skip to content

Commit b4e9bc8

Browse files
committed
Add multiplayer abstractions
Add multi-platform socket abstractions Add Udp and Tcp client/server socket handlers Add RingBuffer Add PacketReaderAdapter Add PacketBuilder Deduplicate stack_string behaviors into StackString Add `GameManager::get_elapsed_microseconds` Add `GameManager::get_elapsed_milliseconds` Add RingBuffer tests Add IpAddress tests Add UdpServer tests Add ReliableUdpServer tess Add TcpServer tests Add mas-bandwidth/reliable@57b0c90
1 parent 94d0812 commit b4e9bc8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+7311
-175
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@
2626
[submodule "tests/benchmarks/deps/nanobench"]
2727
path = tests/benchmarks/deps/nanobench
2828
url = https://github.com/Spartan322/nanobench
29+
[submodule "deps/reliable"]
30+
path = deps/reliable
31+
url = https://github.com/mas-bandwidth/reliable

deps/SCsub

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,36 @@ def build_std_function(env):
4545
env.Append(CPPPATH=env.std_function["INCPATH"])
4646
env.exposed_includes += env.std_function["INCPATH"]
4747

48+
def build_reliable(env):
49+
import os
50+
51+
if env["dev_build"]:
52+
env.Append(CPPDEFINES=["RELIABLE_DEBUG"])
53+
else:
54+
env.Append(CPPDEFINES=["RELIABLE_RELEASE"])
55+
reliable_env = env.Clone()
56+
57+
include_path = "reliable"
58+
include_dir = reliable_env.Dir(include_path)
59+
sources = [os.path.join(include_path, "reliable.c")]
60+
env.reliable_sources = sources
61+
library_name = "libreliable" + env["LIBSUFFIX"]
62+
library = reliable_env.StaticLibrary(target=os.path.join(include_path, library_name), source=sources)
63+
Default(library)
64+
65+
env.reliable = {}
66+
env.reliable["INCPATH"] = [include_dir]
67+
68+
env.Append(CPPPATH=env.reliable["INCPATH"])
69+
if env.get("is_msvc", False):
70+
env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"])
71+
else:
72+
env.Append(CXXFLAGS=["-isystem", include_dir])
73+
env.Append(LIBPATH=include_dir)
74+
env.Prepend(LIBS=[library_name])
75+
76+
env.exposed_includes += env.reliable["INCPATH"]
77+
4878
def link_tbb(env):
4979
import sys
5080
if not env.get("is_msvc", False) and not env.get("use_mingw", False) and sys.platform != "darwin":
@@ -56,4 +86,5 @@ build_ordered_map(env)
5686
build_colony(env)
5787
build_function2(env)
5888
build_std_function(env)
89+
build_reliable(env)
5990
link_tbb(env)

deps/reliable

Submodule reliable added at 57b0c90

src/headless/main.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,12 @@ static bool run_headless(fs::path const& root, std::vector<std::string>& mods, b
117117
Dataloader::path_vector_t roots = { root };
118118
Dataloader::path_vector_t replace_paths = {};
119119

120-
GameManager game_manager { []() {
121-
Logger::info("State updated");
122-
} };
120+
GameManager game_manager {
121+
[] {
122+
Logger::info("State updated");
123+
},
124+
nullptr, nullptr
125+
};
123126

124127
Logger::info("Commit hash: ", GameManager::get_commit_hash());
125128

src/openvic-simulation/GameManager.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,39 @@
11
#include "GameManager.hpp"
22

3+
#include <chrono>
4+
35
using namespace OpenVic;
46

7+
static std::chrono::time_point elapsed_time_begin = std::chrono::high_resolution_clock::now();
8+
9+
GameManager::elapsed_time_getter_func_t GameManager::get_elapsed_usec_time_callback = []() -> uint64_t {
10+
std::chrono::time_point current = std::chrono::high_resolution_clock::now();
11+
return std::chrono::duration_cast<std::chrono::microseconds>(current - elapsed_time_begin).count();
12+
};
13+
14+
GameManager::elapsed_time_getter_func_t GameManager::get_elapsed_msec_time_callback = []() -> uint64_t {
15+
std::chrono::time_point current = std::chrono::high_resolution_clock::now();
16+
return std::chrono::duration_cast<std::chrono::milliseconds>(current - elapsed_time_begin).count();
17+
};
18+
519
GameManager::GameManager(
6-
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback
20+
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback,
21+
elapsed_time_getter_func_t new_get_elapsed_usec_callback,
22+
elapsed_time_getter_func_t new_get_elapsed_msec_callback
723
) : gamestate_updated_callback {
824
new_gamestate_updated_callback ? std::move(new_gamestate_updated_callback) : []() {}
9-
}, definitions_loaded { false }, mod_descriptors_loaded { false } {}
25+
}, definitions_loaded { false }, mod_descriptors_loaded { false } {
26+
if (new_get_elapsed_usec_callback) {
27+
get_elapsed_usec_time_callback = { std::move(new_get_elapsed_usec_callback) };
28+
}
29+
if (new_get_elapsed_msec_callback) {
30+
get_elapsed_msec_time_callback = { std::move(new_get_elapsed_msec_callback) };
31+
}
32+
33+
if (bool(new_get_elapsed_usec_callback) != bool(new_get_elapsed_msec_callback)) {
34+
Logger::warning("Only one of the elapsed time callbacks was set.");
35+
}
36+
}
1037

1138
bool GameManager::load_mod_descriptors(std::span<const std::string> descriptors) {
1239
if (mod_descriptors_loaded) {
@@ -97,3 +124,11 @@ bool GameManager::update_clock() {
97124

98125
return instance_manager->update_clock();
99126
}
127+
128+
uint64_t GameManager::get_elapsed_microseconds() {
129+
return get_elapsed_usec_time_callback();
130+
}
131+
132+
uint64_t GameManager::get_elapsed_milliseconds() {
133+
return get_elapsed_msec_time_callback();
134+
}

src/openvic-simulation/GameManager.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@
1010
#include "openvic-simulation/misc/GameRulesManager.hpp"
1111
#include "openvic-simulation/gen/commit_info.gen.hpp"
1212

13+
#include <function2/function2.hpp>
14+
1315
namespace OpenVic {
1416
struct GameManager {
17+
using elapsed_time_getter_func_t = fu2::function_base<true, true, fu2::capacity_none, false, false, uint64_t() const>;
18+
1519
private:
20+
static elapsed_time_getter_func_t get_elapsed_usec_time_callback;
21+
static elapsed_time_getter_func_t get_elapsed_msec_time_callback;
22+
1623
GameRulesManager PROPERTY(game_rules_manager);
1724
Dataloader PROPERTY(dataloader);
1825
DefinitionManager PROPERTY(definition_manager);
@@ -25,7 +32,9 @@ namespace OpenVic {
2532

2633
public:
2734
GameManager(
28-
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback
35+
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback,
36+
elapsed_time_getter_func_t new_get_elapsed_usec_callback,
37+
elapsed_time_getter_func_t new_get_elapsed_msec_callback
2938
);
3039

3140
inline constexpr InstanceManager* get_instance_manager() {
@@ -55,5 +64,8 @@ namespace OpenVic {
5564
static constexpr uint64_t get_commit_timestamp() {
5665
return SIM_COMMIT_TIMESTAMP;
5766
}
67+
68+
static uint64_t get_elapsed_microseconds();
69+
static uint64_t get_elapsed_milliseconds();
5870
};
5971
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
#include "HostnameAddress.hpp"
3+
4+
#include <charconv>
5+
#include <system_error>
6+
7+
#include "openvic-simulation/multiplayer/lowlevel/IpAddress.hpp"
8+
#include "openvic-simulation/multiplayer/lowlevel/NetworkResolver.hpp"
9+
10+
using namespace OpenVic;
11+
12+
HostnameAddress::HostnameAddress() = default;
13+
14+
HostnameAddress::HostnameAddress(IpAddress const& address) : _resolved_address(address) {}
15+
16+
HostnameAddress::HostnameAddress(std::string_view name_or_address) : HostnameAddress() {
17+
std::from_chars_result result =
18+
_resolved_address.from_chars(name_or_address.data(), name_or_address.data() + name_or_address.size());
19+
if (result.ec != std::errc {}) {
20+
_resolved_address = NetworkResolver::singleton().resolve_hostname(name_or_address);
21+
}
22+
}
23+
24+
IpAddress const& HostnameAddress::resolved_address() const {
25+
return _resolved_address;
26+
}
27+
28+
void HostnameAddress::set_resolved_address(IpAddress const& address) {
29+
_resolved_address = address;
30+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include <string_view>
4+
5+
#include "openvic-simulation/multiplayer/lowlevel/IpAddress.hpp"
6+
7+
namespace OpenVic {
8+
struct HostnameAddress {
9+
HostnameAddress();
10+
HostnameAddress(IpAddress const& address);
11+
HostnameAddress(std::string_view name_or_address);
12+
13+
IpAddress const& resolved_address() const;
14+
void set_resolved_address(IpAddress const& address);
15+
16+
private:
17+
IpAddress _resolved_address;
18+
};
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "IpAddress.hpp"
2+
3+
#include <string>
4+
5+
using namespace OpenVic;
6+
7+
std::string IpAddress::to_string(bool prefer_ipv4, to_chars_option option) const {
8+
stack_string result = to_array(prefer_ipv4, option);
9+
if (OV_unlikely(result.empty())) {
10+
return {};
11+
}
12+
13+
return result;
14+
}
15+
16+
IpAddress::operator std::string() const {
17+
return to_string();
18+
}

0 commit comments

Comments
 (0)