Skip to content

Commit a3235c8

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 Add byte Marshal encode and decode 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 Marshal tests Add mas-bandwidth/reliable@57b0c90
1 parent 2b741a6 commit a3235c8

Some content is hidden

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

68 files changed

+8002
-183
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@
3030
path = deps/memory
3131
url = https://github.com/foonathan/memory
3232
ignore = dirty
33+
[submodule "deps/reliable"]
34+
path = deps/reliable
35+
url = https://github.com/mas-bandwidth/reliable

deps/SCsub

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,36 @@ def build_memory(env):
111111

112112
env.exposed_includes += env.memory["INCPATH"]
113113

114+
def build_reliable(env):
115+
import os
116+
117+
if env["dev_build"]:
118+
env.Append(CPPDEFINES=["RELIABLE_DEBUG"])
119+
else:
120+
env.Append(CPPDEFINES=["RELIABLE_RELEASE"])
121+
reliable_env = env.Clone()
122+
123+
include_path = "reliable"
124+
include_dir = reliable_env.Dir(include_path)
125+
sources = [os.path.join(include_path, "reliable.c")]
126+
env.reliable_sources = sources
127+
library_name = "libreliable" + env["LIBSUFFIX"]
128+
library = reliable_env.StaticLibrary(target=os.path.join(include_path, library_name), source=sources)
129+
Default(library)
130+
131+
env.reliable = {}
132+
env.reliable["INCPATH"] = [include_dir]
133+
134+
env.Append(CPPPATH=env.reliable["INCPATH"])
135+
if env.get("is_msvc", False):
136+
env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"])
137+
else:
138+
env.Append(CXXFLAGS=["-isystem", include_dir])
139+
env.Append(LIBPATH=include_dir)
140+
env.Prepend(LIBS=[library_name])
141+
142+
env.exposed_includes += env.reliable["INCPATH"]
143+
114144
def link_tbb(env):
115145
import sys
116146
if not env.get("is_msvc", False) and not env.get("use_mingw", False) and sys.platform != "darwin":
@@ -123,4 +153,5 @@ build_colony(env)
123153
build_function2(env)
124154
build_std_function(env)
125155
build_memory(env)
156+
build_reliable(env)
126157
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
@@ -127,9 +127,12 @@ static bool run_headless(fs::path const& root, memory::vector<memory::string>& m
127127
Dataloader::path_vector_t roots = { root };
128128
Dataloader::path_vector_t replace_paths = {};
129129

130-
GameManager game_manager { []() {
131-
Logger::info("State updated");
132-
} };
130+
GameManager game_manager {
131+
[] {
132+
Logger::info("State updated");
133+
},
134+
nullptr, nullptr
135+
};
133136

134137
Logger::info("Commit hash: ", GameManager::get_commit_hash());
135138

src/openvic-simulation/GameManager.cpp

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

3+
#include <chrono>
4+
35
#include <cstddef>
46
#include <string_view>
57

@@ -8,11 +10,36 @@
810

911
using namespace OpenVic;
1012

13+
static std::chrono::time_point elapsed_time_begin = std::chrono::high_resolution_clock::now();
14+
15+
GameManager::elapsed_time_getter_func_t GameManager::get_elapsed_usec_time_callback = []() -> uint64_t {
16+
std::chrono::time_point current = std::chrono::high_resolution_clock::now();
17+
return std::chrono::duration_cast<std::chrono::microseconds>(current - elapsed_time_begin).count();
18+
};
19+
20+
GameManager::elapsed_time_getter_func_t GameManager::get_elapsed_msec_time_callback = []() -> uint64_t {
21+
std::chrono::time_point current = std::chrono::high_resolution_clock::now();
22+
return std::chrono::duration_cast<std::chrono::milliseconds>(current - elapsed_time_begin).count();
23+
};
24+
1125
GameManager::GameManager(
12-
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback
26+
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback,
27+
elapsed_time_getter_func_t new_get_elapsed_usec_callback,
28+
elapsed_time_getter_func_t new_get_elapsed_msec_callback
1329
) : gamestate_updated_callback {
1430
new_gamestate_updated_callback ? std::move(new_gamestate_updated_callback) : []() {}
15-
}, definitions_loaded { false }, mod_descriptors_loaded { false } {}
31+
}, definitions_loaded { false }, mod_descriptors_loaded { false } {
32+
if (new_get_elapsed_usec_callback) {
33+
get_elapsed_usec_time_callback = { std::move(new_get_elapsed_usec_callback) };
34+
}
35+
if (new_get_elapsed_msec_callback) {
36+
get_elapsed_msec_time_callback = { std::move(new_get_elapsed_msec_callback) };
37+
}
38+
39+
if (bool(new_get_elapsed_usec_callback) != bool(new_get_elapsed_msec_callback)) {
40+
Logger::warning("Only one of the elapsed time callbacks was set.");
41+
}
42+
}
1643

1744
bool GameManager::load_mod_descriptors() {
1845
if (mod_descriptors_loaded) {
@@ -202,3 +229,11 @@ bool GameManager::update_clock() {
202229

203230
return instance_manager->update_clock();
204231
}
232+
233+
uint64_t GameManager::get_elapsed_microseconds() {
234+
return get_elapsed_usec_time_callback();
235+
}
236+
237+
uint64_t GameManager::get_elapsed_milliseconds() {
238+
return get_elapsed_msec_time_callback();
239+
}

src/openvic-simulation/GameManager.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@
1111
#include "openvic-simulation/gen/commit_info.gen.hpp"
1212
#include "openvic-simulation/utility/ForwardableSpan.hpp"
1313

14+
#include <function2/function2.hpp>
15+
1416
namespace OpenVic {
1517
struct GameManager {
18+
using elapsed_time_getter_func_t = fu2::function_base<true, true, fu2::capacity_none, false, false, uint64_t() const>;
19+
1620
private:
21+
static elapsed_time_getter_func_t get_elapsed_usec_time_callback;
22+
static elapsed_time_getter_func_t get_elapsed_msec_time_callback;
23+
1724
GameRulesManager PROPERTY(game_rules_manager);
1825
Dataloader PROPERTY(dataloader);
1926
DefinitionManager PROPERTY(definition_manager);
@@ -28,7 +35,9 @@ namespace OpenVic {
2835

2936
public:
3037
GameManager(
31-
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback
38+
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback,
39+
elapsed_time_getter_func_t new_get_elapsed_usec_callback,
40+
elapsed_time_getter_func_t new_get_elapsed_msec_callback
3241
);
3342

3443
inline constexpr InstanceManager* get_instance_manager() {
@@ -68,5 +77,8 @@ namespace OpenVic {
6877
static constexpr uint64_t get_commit_timestamp() {
6978
return SIM_COMMIT_TIMESTAMP;
7079
}
80+
81+
static uint64_t get_elapsed_microseconds();
82+
static uint64_t get_elapsed_milliseconds();
7183
};
7284
}
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 "openvic-simulation/utility/Containers.hpp"
4+
5+
using namespace OpenVic;
6+
7+
memory::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 memory::string() const {
17+
return to_string();
18+
}

0 commit comments

Comments
 (0)