Started work on network object system

This commit is contained in:
Yousef Khadadeh 2025-12-06 14:16:50 +03:00
parent a2ce579b8b
commit ed4810e6ee
12 changed files with 394 additions and 74 deletions

View file

@ -93,6 +93,27 @@ void NetClient::parse_received_messages() {
}
}
void NetClient::send_string_stream_to_server(const std::string& channel, const std::shared_ptr<std::stringstream>& ss) {
if(isDisconnected)
return;
auto& messageQueue = messageQueues[channel];
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss);
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss2);
}
}
}
NetLibrary::DownloadProgress NetClient::get_progress_into_fragmented_message(const std::string& channel) const {
auto it = pfm.find(channel);
if(it == pfm.end())

View file

@ -25,23 +25,9 @@ class NetClient : public std::enable_shared_from_this<NetClient> {
cereal::PortableBinaryOutputArchive m(*ss);
(m(items), ...);
}
auto& messageQueue = messageQueues[channel];
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss);
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, nextMessageOrderToSend), ss2);
}
}
send_string_stream_to_server(channel, ss);
}
void send_string_stream_to_server(const std::string& channel, const std::shared_ptr<std::stringstream>& ss);
void update();
void add_recv_callback(MessageCommandType commandID, const NetClientRecvCallback& callback);
bool is_disconnected() const;

View file

@ -17,6 +17,7 @@ template <class T> std::weak_ptr<T> make_weak_ptr(std::shared_ptr<T> ptr) { retu
#define MAIN_NETLIBRARY_CHANNEL "main00005" // NOTE: Change this value whenever netcode is incompatible with the previous version
typedef uint8_t MessageCommandType;
typedef uint8_t NetTypeIDType;
class NetLibrary {
public:

View file

@ -93,6 +93,66 @@ void NetServer::client_connected(std::shared_ptr<rtc::PeerConnection> connection
});
}
void NetServer::send_string_stream_to_client(const std::shared_ptr<ClientData>& client, const std::string& channel, const std::shared_ptr<std::stringstream>& ss) {
if(!client)
return;
auto& messageQueue = client->messageQueues[channel];
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss2);
}
}
}
void NetServer::send_string_stream_to_all_clients(const std::string& channel, const std::shared_ptr<std::stringstream>& ss) {
send_string_stream_to_client_if([&](const std::shared_ptr<ClientData>& c) {
return true;
}, channel, ss);
}
void NetServer::send_string_stream_to_all_clients_except(const std::shared_ptr<ClientData>& client, const std::string& channel, const std::shared_ptr<std::stringstream>& ss) {
send_string_stream_to_client_if([&](const std::shared_ptr<ClientData>& c) {
return c != client;
}, channel, ss);
}
void NetServer::send_string_stream_to_client_if(std::function<bool(const std::shared_ptr<ClientData>&)> clientChecker, const std::string& channel, const std::shared_ptr<std::stringstream>& ss) {
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) { // Drop unreliable messages that are too big
for(auto& client : clients) {
if(client && clientChecker(client)) {
auto& messageQueue = client->messageQueues[channel];
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
}
}
}
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
for(auto& client : clients) {
if(client && clientChecker(client)) {
auto& messageQueue = client->messageQueues[channel];
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss2);
}
}
}
}
}
void NetServer::ClientData::send_queued_messages(NetServer& server) {
for(auto& [channelName, messageQueue] : messageQueues) {
bool addMessageOrder = NetLibrary::is_ordered_channel(channelName);

View file

@ -54,75 +54,32 @@ class NetServer : public std::enable_shared_from_this<NetServer> {
NetServer(const std::string& serverLocalID);
~NetServer();
void update();
template <typename... Args> void send_items_to_client(std::shared_ptr<ClientData> client, const std::string& channel, Args&&... items) {
if(!client)
return;
auto ss(std::make_shared<std::stringstream>());
{
cereal::PortableBinaryOutputArchive m(*ss);
(m(items), ...);
}
auto& messageQueue = client->messageQueues[channel];
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) // Drop unreliable messages that are too big
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss2);
}
}
template <typename... Args> void send_items_to_client(const std::shared_ptr<ClientData>& client, const std::string& channel, Args&&... items) {
send_string_stream_to_client(client, channel, get_string_stream_from_items(items...));
}
template <typename... Args> void send_items_to_all_clients(const std::string& channel, Args&&... items) {
send_items_to_client_if([&](std::shared_ptr<ClientData> c) {
return true;
}, channel, items...);
send_string_stream_to_all_clients(channel, get_string_stream_from_items(items...));
}
template <typename... Args> void send_items_to_all_clients_except(std::shared_ptr<ClientData> client, const std::string& channel, Args&&... items) {
send_items_to_client_if([&](std::shared_ptr<ClientData> c) {
return c != client;
}, channel, items...);
template <typename... Args> void send_items_to_all_clients_except(const std::shared_ptr<ClientData>& client, const std::string& channel, Args&&... items) {
send_string_stream_to_all_clients_except(client, channel, get_string_stream_from_items(items...));
}
template <typename... Args> void send_items_to_client_if(std::function<bool(std::shared_ptr<ClientData>)> clientChecker, const std::string& channel, Args&&... items) {
template <typename... Args> void send_items_to_client_if(std::function<bool(const std::shared_ptr<ClientData>&)> clientChecker, const std::string& channel, Args&&... items) {
send_string_stream_to_client_if(clientChecker, channel, get_string_stream_from_items(items...));
}
template <typename... Args> std::shared_ptr<std::stringstream> get_string_stream_from_items(Args&&... items) {
auto ss(std::make_shared<std::stringstream>());
{
cereal::PortableBinaryOutputArchive m(*ss);
(m(items), ...);
}
if(channel == UNRELIABLE_COMMAND_CHANNEL) {
if(ss->view().length() <= NetLibrary::MAX_UNRELIABLE_MESSAGE_SIZE) { // Drop unreliable messages that are too big
for(auto& client : clients) {
if(client && clientChecker(client)) {
auto& messageQueue = client->messageQueues[channel];
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
}
}
}
}
else {
std::vector<std::shared_ptr<std::stringstream>> fragmentedMessage = fragment_message(ss->view(), NetLibrary::FRAGMENT_MESSAGE_STRIDE);
for(auto& client : clients) {
if(client && clientChecker(client)) {
auto& messageQueue = client->messageQueues[channel];
if(fragmentedMessage.empty())
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss);
else {
for(auto& ss2 : fragmentedMessage)
messageQueue.emplace(NetLibrary::calc_order_for_queued_message(channel, client->nextMessageOrderToSend), ss2);
}
}
}
}
return ss;
}
void send_string_stream_to_client(const std::shared_ptr<ClientData>& client, const std::string& channel, const std::shared_ptr<std::stringstream>& ss);
void send_string_stream_to_all_clients(const std::string& channel, const std::shared_ptr<std::stringstream>& ss);
void send_string_stream_to_all_clients_except(const std::shared_ptr<ClientData>& client, const std::string& channel, const std::shared_ptr<std::stringstream>& ss);
void send_string_stream_to_client_if(std::function<bool(const std::shared_ptr<ClientData>&)> clientChecker, const std::string& channel, const std::shared_ptr<std::stringstream>& ss);
bool is_disconnected() const;
void add_recv_callback(MessageCommandType commandID, const NetServerRecvCallback& callback);