Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
path = deps/memory
url = https://github.com/foonathan/memory
ignore = dirty
[submodule "deps/reliable"]
path = deps/reliable
url = https://github.com/mas-bandwidth/reliable
31 changes: 31 additions & 0 deletions deps/SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,36 @@ def build_memory(env):

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

def build_reliable(env):
import os

if env["dev_build"]:
env.Append(CPPDEFINES=["RELIABLE_DEBUG"])
else:
env.Append(CPPDEFINES=["RELIABLE_RELEASE"])
reliable_env = env.Clone()

include_path = "reliable"
include_dir = reliable_env.Dir(include_path)
sources = [os.path.join(include_path, "reliable.c")]
env.reliable_sources = sources
library_name = "libreliable" + env["LIBSUFFIX"]
library = reliable_env.StaticLibrary(target=os.path.join(include_path, library_name), source=sources)
Default(library)

env.reliable = {}
env.reliable["INCPATH"] = [include_dir]

env.Append(CPPPATH=env.reliable["INCPATH"])
if env.get("is_msvc", False):
env.Append(CXXFLAGS=["/external:I", include_dir, "/external:W0"])
else:
env.Append(CXXFLAGS=["-isystem", include_dir])
env.Append(LIBPATH=include_dir)
env.Prepend(LIBS=[library_name])

env.exposed_includes += env.reliable["INCPATH"]

def link_tbb(env):
import sys
if not env.get("is_msvc", False) and not env.get("use_mingw", False) and sys.platform != "darwin":
Expand All @@ -123,4 +153,5 @@ build_colony(env)
build_function2(env)
build_std_function(env)
build_memory(env)
build_reliable(env)
link_tbb(env)
1 change: 1 addition & 0 deletions deps/reliable
Submodule reliable added at 57b0c9
52 changes: 51 additions & 1 deletion src/openvic-simulation/GameManager.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "GameManager.hpp"

#include <chrono>

#include <cstddef>
#include <string_view>

#include "openvic-simulation/dataloader/Dataloader.hpp"
#include "openvic-simulation/multiplayer/ClientManager.hpp"
#include "openvic-simulation/multiplayer/HostManager.hpp"
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/utility/Logger.hpp"

using namespace OpenVic;
Expand Down Expand Up @@ -252,6 +254,54 @@ bool GameManager::update_clock() {
return instance_manager->update_clock();
}

void GameManager::create_client() {
client_manager = memory::make_unique<ClientManager>(this);
chat_manager = memory::make_unique<ChatManager>(client_manager.get());
}

void GameManager::create_host(memory::string session_name) {
host_manager = memory::make_unique<HostManager>(this);
if (!session_name.empty()) {
host_manager->get_host_session().set_game_name(session_name);
}
}

void GameManager::threaded_poll_network() {
const int MAX_POLL_WAIT_MSEC = 100;
const int SLEEP_DURATION_USEC = 1000;

if (host_manager) {
const uint64_t time = GameManager::get_elapsed_milliseconds();
while (!(host_manager->poll() > 0) && (GameManager::get_elapsed_milliseconds() - time) < MAX_POLL_WAIT_MSEC) {
std::this_thread::sleep_for(std::chrono::microseconds { SLEEP_DURATION_USEC });
}
}

if (client_manager) {
const uint64_t time = GameManager::get_elapsed_milliseconds();
while (!(client_manager->poll() > 0) && (GameManager::get_elapsed_milliseconds() - time) < MAX_POLL_WAIT_MSEC) {
std::this_thread::sleep_for(std::chrono::microseconds { SLEEP_DURATION_USEC });
}

if (host_manager) {
// TODO: create local ClientManager that doesn't send network data to HostManager
// In the case that client_manager sends something, host_manager may handle it
const uint64_t time = GameManager::get_elapsed_milliseconds();
while (!(host_manager->poll() > 0) && (GameManager::get_elapsed_milliseconds() - time) < MAX_POLL_WAIT_MSEC / 4) {
std::this_thread::sleep_for(std::chrono::microseconds { SLEEP_DURATION_USEC / 4 });
}
}
}
}

void GameManager::delete_client() {
client_manager.reset();
}

void GameManager::delete_host() {
host_manager.reset();
}

uint64_t GameManager::get_elapsed_microseconds() {
return get_elapsed_usec_time_callback();
}
Expand Down
47 changes: 47 additions & 0 deletions src/openvic-simulation/GameManager.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <optional>
#include <span>
#include <string_view>

#include "openvic-simulation/DefinitionManager.hpp"
Expand All @@ -9,11 +10,18 @@
#include "openvic-simulation/dataloader/Dataloader.hpp"
#include "openvic-simulation/misc/GameRulesManager.hpp"
#include "openvic-simulation/gen/commit_info.gen.hpp"
#include "openvic-simulation/multiplayer/ChatManager.hpp"
#include "openvic-simulation/multiplayer/ClientManager.hpp"
#include "openvic-simulation/multiplayer/HostManager.hpp"
#include "openvic-simulation/player/PlayerManager.hpp"
#include "openvic-simulation/utility/ForwardableSpan.hpp"

#include <function2/function2.hpp>

namespace OpenVic {
struct HostManager;
struct ClientManager;

struct GameManager {
using elapsed_time_getter_func_t = fu2::function_base<true, true, fu2::capacity_none, false, false, uint64_t() const>;

Expand All @@ -31,6 +39,12 @@ namespace OpenVic {
bool PROPERTY_CUSTOM_PREFIX(definitions_loaded, are);
bool PROPERTY_CUSTOM_PREFIX(mod_descriptors_loaded, are);

memory::unique_ptr<HostManager> host_manager;
memory::unique_ptr<ClientManager> client_manager;
memory::unique_ptr<ChatManager> chat_manager;

bool _get_mod_dependencies(Mod const* mod, memory::vector<Mod const*>& load_list);

public:
GameManager(
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback,
Expand All @@ -47,6 +61,30 @@ namespace OpenVic {
return instance_manager ? &*instance_manager : nullptr;
}

inline HostManager* get_host_manager() {
return host_manager.get();
}

inline HostManager const* get_host_manager() const {
return host_manager.get();
}

inline ClientManager* get_client_manager() {
return client_manager.get();
}

inline ClientManager const* get_client_manager() const {
return client_manager.get();
}

inline ChatManager* get_chat_manager() {
return chat_manager.get();
}

inline ChatManager const* get_chat_manager() const {
return chat_manager.get();
}

inline bool set_base_path(Dataloader::path_span_t base_path) {
OV_ERR_FAIL_COND_V_MSG(base_path.size() > 1, false, "Too many base paths were provided, only one should be set.");
OV_ERR_FAIL_COND_V_MSG(!dataloader.set_roots(base_path, {}), false, "Failed to set Dataloader's base path");
Expand All @@ -73,6 +111,15 @@ namespace OpenVic {

bool update_clock();

void create_client();
void create_host(memory::string session_name = "");

// DO NOT RUN ON MAIN THREAD
void threaded_poll_network();

void delete_client();
void delete_host();

static constexpr std::string_view get_commit_hash() {
return SIM_COMMIT_HASH;
}
Expand Down
20 changes: 20 additions & 0 deletions src/openvic-simulation/multiplayer/BaseMultiplayerManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "BaseMultiplayerManager.hpp"

#include "openvic-simulation/multiplayer/PacketType.hpp"
#include "openvic-simulation/utility/ErrorMacros.hpp"

using namespace OpenVic;

BaseMultiplayerManager::BaseMultiplayerManager(GameManager* game_manager) : game_manager(game_manager) {
packet_cache.reserve_power(15);
}

bool BaseMultiplayerManager::broadcast_packet(PacketType const& type, PacketType::argument_type argument) {
OV_ERR_FAIL_COND_V(!PacketType::is_valid_type(type), false);
return true;
}

bool BaseMultiplayerManager::send_packet(client_id_type client_id, PacketType const& type, PacketType::argument_type argument) {
OV_ERR_FAIL_COND_V(!PacketType::is_valid_type(type), false);
return true;
}
75 changes: 75 additions & 0 deletions src/openvic-simulation/multiplayer/BaseMultiplayerManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <cstdint>

#include "openvic-simulation/multiplayer/Constants.hpp"
#include "openvic-simulation/multiplayer/HostSession.hpp"
#include "openvic-simulation/multiplayer/PacketType.hpp"
#include "openvic-simulation/multiplayer/lowlevel/Constants.hpp"
#include "openvic-simulation/types/RingBuffer.hpp"
#include "openvic-simulation/utility/Containers.hpp"
#include "openvic-simulation/utility/Getters.hpp"

namespace OpenVic {
struct GameManager;

struct BaseMultiplayerManager {
BaseMultiplayerManager(GameManager* game_manager = nullptr);
virtual ~BaseMultiplayerManager() = default;

using client_id_type = OpenVic::client_id_type;
using sequence_type = reliable_udp_sequence_type;

static constexpr client_id_type HOST_ID = MP_HOST_ID;

virtual bool broadcast_packet(PacketType const& type, PacketType::argument_type argument);
virtual bool send_packet(client_id_type client_id, PacketType const& type, PacketType::argument_type argument);
virtual int64_t poll() = 0;
virtual void close() = 0;

enum class ConnectionType : uint8_t { HOST, CLIENT };

virtual ConnectionType get_connection_type() const = 0;

template<typename T>
T* cast_as() {
if (get_connection_type() == T::type_tag) {
return static_cast<T*>(this);
}
return nullptr;
}

template<typename T>
T const* cast_as() const {
if (get_connection_type() == T::type_tag) {
return static_cast<T const*>(this);
}
return nullptr;
}

PacketSpan get_last_raw_packet() {
return last_raw_packet;
}

protected:
bool PROPERTY_ACCESS(in_lobby, protected, false);
GameManager* PROPERTY_PTR_ACCESS(game_manager, protected);
HostSession PROPERTY_ACCESS(host_session, protected);

RingBuffer<uint8_t> packet_cache;

struct PacketCacheIndex {
decltype(packet_cache)::const_iterator begin;
decltype(packet_cache)::const_iterator end;
constexpr bool is_valid() const {
return begin != end;
}
};

memory::vector<uint8_t> last_raw_packet;

friend bool PacketTypes::send_raw_packet_process_callback( //
BaseMultiplayerManager* multiplayer_manager, PacketSpan packet
);
};
}
Loading
Loading