Completely removed MainServer code. All server code is now part of the program
This commit is contained in:
parent
0b67c9cc46
commit
26d807ce87
31 changed files with 459 additions and 512 deletions
|
|
@ -32,6 +32,7 @@ set(sources "src/main.cpp"
|
|||
"src/MainProgram.cpp"
|
||||
"src/DrawData.cpp"
|
||||
"src/FontData.cpp"
|
||||
"src/ClientData.cpp"
|
||||
"src/GridManager.cpp"
|
||||
"src/WorldGrid.cpp"
|
||||
"src/TimePoint.cpp"
|
||||
|
|
@ -53,8 +54,6 @@ set(sources "src/main.cpp"
|
|||
"src/ResourceDisplay/SvgResourceDisplay.cpp"
|
||||
"src/ResourceDisplay/ImageResourceDisplay.cpp"
|
||||
"src/ResourceDisplay/FileResourceDisplay.cpp"
|
||||
"src/Server/MainServer.cpp"
|
||||
"src/Server/ServerData.cpp"
|
||||
"src/RichText/TextBox.cpp"
|
||||
"src/RichText/TextStyleModifier.cpp"
|
||||
"src/RichText/ParagraphStyleData.cpp"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class NetServer : public std::enable_shared_from_this<NetServer> {
|
|||
};
|
||||
std::unordered_map<std::string, std::queue<OutgoingMessage>> messageQueues;
|
||||
|
||||
uint64_t customID;
|
||||
std::array<uint64_t, 2> customID;
|
||||
|
||||
void send_queued_messages(NetServer& server);
|
||||
void parse_received_messages(NetServer& server);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
template <typename T> static void send_client_update(const NetObjTemporaryPtr<T>& ptr, const std::string& channel, std::function<void(const NetObjTemporaryPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) {
|
||||
assert(!isServer);
|
||||
if(ptr.get_obj_man()->client && !ptr.get_obj_man()->client->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
|
|
@ -104,7 +103,6 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
template <typename T> static void send_server_update_to_client(const NetObjTemporaryPtr<T>& ptr, const std::shared_ptr<NetServer::ClientData>& clientToSendTo, const std::string& channel, std::function<void(const NetObjTemporaryPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) {
|
||||
assert(isServer);
|
||||
if(ptr.get_obj_man()->server && !ptr.get_obj_man()->server->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
|
|
@ -117,7 +115,6 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
template <typename T> static void send_server_update_to_all_clients_except(const NetObjTemporaryPtr<T>& ptr, const std::shared_ptr<NetServer::ClientData>& clientToNotSendTo, const std::string& channel, std::function<void(const NetObjTemporaryPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) {
|
||||
assert(isServer);
|
||||
if(ptr.get_obj_man()->server && !ptr.get_obj_man()->server->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
|
|
@ -130,7 +127,6 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
template <typename T> static void send_server_update_to_all_clients(const NetObjTemporaryPtr<T>& ptr, const std::string& channel, std::function<void(const NetObjTemporaryPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) {
|
||||
assert(isServer);
|
||||
if(ptr.get_obj_man()->server && !ptr.get_obj_man()->server->is_disconnected()) {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
bool contains(const NetObjID& p) const {
|
||||
return std::find_if(data.begin(), data.end(), [&p](const NetObjOwnerPtr<T>& o){ o.get_net_id() == p; }) != data.end();
|
||||
return std::find_if(data.begin(), data.end(), [&p](const NetObjOwnerPtr<T>& o){ return o.get_net_id() == p; }) != data.end();
|
||||
}
|
||||
const std::vector<NetObjOwnerPtr<T>>& get_data() const {
|
||||
return data;
|
||||
|
|
@ -68,7 +68,7 @@ namespace NetworkingObjects {
|
|||
}
|
||||
|
||||
bool erase_by_id(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const NetObjID& id) {
|
||||
auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr<T>& o){ o.get_net_id() == id; });
|
||||
auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr<T>& o){ return o.get_net_id() == id; });
|
||||
if(it == this->data.end())
|
||||
return false;
|
||||
call_erase_callback(*it);
|
||||
|
|
@ -77,14 +77,14 @@ namespace NetworkingObjects {
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>& clientInserting, NetObjOwnerPtr<T> newObj) const = 0;
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>& clientInserting, const NetObjOwnerPtr<T>& newObj) const = 0;
|
||||
virtual void erase_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const NetObjID& id) const = 0;
|
||||
virtual void read_update(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) = 0;
|
||||
|
||||
void write_constructor(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(static_cast<uint32_t>(data.size()));
|
||||
for(size_t i = 0; i < data.size(); i++)
|
||||
data[i]->obj.write_create_message(a);
|
||||
data[i].write_create_message(a);
|
||||
|
||||
}
|
||||
void read_constructor(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
|
|
@ -128,7 +128,7 @@ namespace NetworkingObjects {
|
|||
public:
|
||||
NetObjUnorderedSetServer() {}
|
||||
protected:
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>& clientInserting, NetObjOwnerPtr<T> newObj) const override {
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>& clientInserting, const NetObjOwnerPtr<T>& newObj) const override {
|
||||
l.send_server_update_to_all_clients_except(clientInserting, RELIABLE_COMMAND_CHANNEL, [&newObj](const NetObjTemporaryPtr<NetObjUnorderedSet<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrUnorderedSetCommand_StoC::INSERT_SINGLE_CONSTRUCT);
|
||||
newObj.write_create_message(a);
|
||||
|
|
@ -144,13 +144,13 @@ namespace NetworkingObjects {
|
|||
a(command);
|
||||
switch(command) {
|
||||
case ObjPtrUnorderedSetCommand_CtoS::INSERT_SINGLE: {
|
||||
insert(l, c, l.get_obj_man()->template read_create_message<T>(a, c));
|
||||
NetObjUnorderedSet<T>::insert(l, c, l.get_obj_man()->template read_create_message<T>(a, c));
|
||||
break;
|
||||
}
|
||||
case ObjPtrUnorderedSetCommand_CtoS::ERASE_SINGLE: {
|
||||
NetObjID idToErase;
|
||||
a(idToErase);
|
||||
erase_by_id(l, idToErase);
|
||||
NetObjUnorderedSet<T>::erase_by_id(l, idToErase);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ namespace NetworkingObjects {
|
|||
public:
|
||||
NetObjUnorderedSetClient() {}
|
||||
protected:
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>&, NetObjOwnerPtr<T> newObj) const override {
|
||||
virtual void insert_network(const NetObjTemporaryPtr<NetObjUnorderedSet<T>>& l, const std::shared_ptr<NetServer::ClientData>&, const NetObjOwnerPtr<T>& newObj) const override {
|
||||
l.send_client_update(RELIABLE_COMMAND_CHANNEL, [&newObj](const NetObjTemporaryPtr<NetObjUnorderedSet<T>>&, cereal::PortableBinaryOutputArchive& a) {
|
||||
a(ObjPtrUnorderedSetCommand_CtoS::INSERT_SINGLE);
|
||||
newObj.write_create_message(a);
|
||||
|
|
@ -183,7 +183,7 @@ namespace NetworkingObjects {
|
|||
case ObjPtrUnorderedSetCommand_StoC::ERASE_SINGLE: {
|
||||
NetObjID id;
|
||||
a(id);
|
||||
auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr<T>& o){ o.get_net_id() == id; });
|
||||
auto it = std::find_if(this->data.begin(), this->data.end(), [&id](const NetObjOwnerPtr<T>& o){ return o.get_net_id() == id; });
|
||||
if(it != this->data.end())
|
||||
this->data.erase(it);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp"
|
||||
#include "World.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "MainProgram.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
182
src/ClientData.cpp
Normal file
182
src/ClientData.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#include "ClientData.hpp"
|
||||
#include "World.hpp"
|
||||
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
|
||||
#include "MainProgram.hpp"
|
||||
|
||||
using namespace NetworkingObjects;
|
||||
|
||||
enum class ClientDataCommand : uint8_t {
|
||||
SET_CURSOR_POS = 0,
|
||||
SET_WINDOW_SIZE,
|
||||
SET_CAM_COORDS,
|
||||
SEND_CHAT_MESSAGE
|
||||
};
|
||||
|
||||
ClientData::ClientData() {
|
||||
set_from_init_struct(InitStruct());
|
||||
}
|
||||
|
||||
ClientData::ClientData(const InitStruct& initStruct) {
|
||||
set_from_init_struct(initStruct);
|
||||
}
|
||||
|
||||
void ClientData::set_from_init_struct(const InitStruct& initStruct) {
|
||||
camCoords = initStruct.camCoords;
|
||||
windowSize = initStruct.windowSize;
|
||||
cursorPos = initStruct.cursorPos;
|
||||
cursorColor = initStruct.cursorColor;
|
||||
displayName = initStruct.displayName;
|
||||
}
|
||||
|
||||
void ClientData::register_class(World& world) {
|
||||
world.netObjMan.register_class<ClientData, ClientData, ClientData, ClientData>({
|
||||
.writeConstructorFuncClient = default_serialize_write_func<ClientData>,
|
||||
.readConstructorFuncClient = default_serialize_read_constructor_func<ClientData>,
|
||||
.readUpdateFuncClient = [&world](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) {
|
||||
ClientDataCommand command;
|
||||
a(command);
|
||||
switch(command) {
|
||||
case ClientDataCommand::SET_CURSOR_POS:
|
||||
a(o->cursorPos);
|
||||
break;
|
||||
case ClientDataCommand::SET_WINDOW_SIZE:
|
||||
a(o->windowSize);
|
||||
break;
|
||||
case ClientDataCommand::SET_CAM_COORDS:
|
||||
a(o->camCoords);
|
||||
break;
|
||||
case ClientDataCommand::SEND_CHAT_MESSAGE: {
|
||||
std::string chatMessage;
|
||||
a(chatMessage);
|
||||
world.add_chat_message(o->displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
|
||||
}
|
||||
}
|
||||
},
|
||||
.writeConstructorFuncServer = default_serialize_write_func<ClientData>,
|
||||
.readConstructorFuncServer = default_serialize_read_constructor_func<ClientData>,
|
||||
.readUpdateFuncServer = [&world](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>& c) {
|
||||
ClientDataCommand command;
|
||||
a(command);
|
||||
switch(command) {
|
||||
case ClientDataCommand::SET_CURSOR_POS:
|
||||
a(o->cursorPos);
|
||||
o.send_server_update_to_all_clients_except(c, UNRELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_CURSOR_POS, o->cursorPos);
|
||||
});
|
||||
break;
|
||||
case ClientDataCommand::SET_WINDOW_SIZE:
|
||||
a(o->windowSize);
|
||||
o.send_server_update_to_all_clients_except(c, RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_WINDOW_SIZE, o->windowSize);
|
||||
});
|
||||
break;
|
||||
case ClientDataCommand::SET_CAM_COORDS:
|
||||
a(o->camCoords);
|
||||
o.send_server_update_to_all_clients_except(c, RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_CAM_COORDS, o->camCoords);
|
||||
});
|
||||
break;
|
||||
case ClientDataCommand::SEND_CHAT_MESSAGE: {
|
||||
std::string chatMessage;
|
||||
a(chatMessage);
|
||||
world.add_chat_message(o->displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
|
||||
o.send_server_update_to_all_clients_except(c, RELIABLE_COMMAND_CHANNEL, [&chatMessage](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SEND_CHAT_MESSAGE, chatMessage);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
void ClientData::set_cursor_pos(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, Vector2f newPos) {
|
||||
o->cursorPos = newPos;
|
||||
o.send_update_to_all(UNRELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_CURSOR_POS, o->cursorPos);
|
||||
});
|
||||
}
|
||||
|
||||
void ClientData::set_window_size(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, Vector2f newWindowSize) {
|
||||
if(o->windowSize != newWindowSize) {
|
||||
o->windowSize = newWindowSize;
|
||||
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_WINDOW_SIZE, o->windowSize);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ClientData::set_camera_coords(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, const CoordSpaceHelper& newCoords) {
|
||||
if(o->camCoords != newCoords) {
|
||||
o->camCoords = newCoords;
|
||||
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SET_CAM_COORDS, o->camCoords);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ClientData::send_chat_message(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, World& world, const std::string& chatMessage) {
|
||||
world.add_chat_message(o->displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
|
||||
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [&chatMessage](const NetObjTemporaryPtr<ClientData>& o, cereal::PortableBinaryOutputArchive & a) {
|
||||
a(ClientDataCommand::SEND_CHAT_MESSAGE, chatMessage);
|
||||
});
|
||||
}
|
||||
|
||||
void ClientData::set_display_name(const std::string& newDisplayName) {
|
||||
displayName = newDisplayName;
|
||||
}
|
||||
|
||||
void ClientData::set_cursor_color(const Vector3f& newCursorColor) {
|
||||
cursorColor = newCursorColor;
|
||||
}
|
||||
|
||||
const CoordSpaceHelper& ClientData::get_cam_coords() const {
|
||||
return camCoords;
|
||||
}
|
||||
|
||||
const Vector2f& ClientData::get_window_size() const {
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
const Vector2f& ClientData::get_cursor_pos() const {
|
||||
return cursorPos;
|
||||
}
|
||||
|
||||
const std::string& ClientData::get_display_name() const {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
const Vector3f& ClientData::get_cursor_color() const {
|
||||
return cursorColor;
|
||||
}
|
||||
|
||||
void ClientData::draw_cursor(SkCanvas* canvas, const DrawData& drawData) const {
|
||||
if((drawData.cam.c.inverseScale << 10) > camCoords.inverseScale && drawData.clampDrawMinimum < camCoords.inverseScale) {
|
||||
canvas->save();
|
||||
camCoords.transform_sk_canvas(canvas, drawData);
|
||||
|
||||
canvas->translate(cursorPos.x(), cursorPos.y());
|
||||
|
||||
SkPaint p(SkColor4f{cursorColor.x(), cursorColor.y(), cursorColor.z(), 0.2f});
|
||||
canvas->drawCircle(0.0f, 0.0f, 4.5f, p);
|
||||
p.setStroke(true);
|
||||
p.setStrokeWidth(1.0f);
|
||||
p.setColor4f({cursorColor.x(), cursorColor.y(), cursorColor.z(), 0.7f});
|
||||
canvas->drawCircle(0.0f, 0.0f, 5.0f, p);
|
||||
|
||||
SkFont f = drawData.main->toolbar.io->get_font(18.0f);
|
||||
SkFontMetrics metrics;
|
||||
f.getMetrics(&metrics);
|
||||
|
||||
float nextText = f.measureText(displayName.c_str(), displayName.length(), SkTextEncoding::kUTF8, nullptr);
|
||||
Vector2f bounds{nextText, - metrics.fAscent + metrics.fDescent};
|
||||
|
||||
SkPaint p2(SkColor4f{cursorColor.x(), cursorColor.y(), cursorColor.z(), 0.5f});
|
||||
canvas->drawSimpleText(displayName.c_str(), displayName.length(), SkTextEncoding::kUTF8, 6.0f, -metrics.fDescent, f, p2);
|
||||
|
||||
SkPaint p3(color_mul_alpha(drawData.main->toolbar.io->theme->backColor1, 0.5f));
|
||||
canvas->drawRoundRect(SkRect::MakeXYWH(6.0f, -bounds.y(), bounds.x(), bounds.y()), 3.0f, 3.0f, p3);
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
48
src/ClientData.hpp
Normal file
48
src/ClientData.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
#include <Helpers/Serializers.hpp>
|
||||
#include "CoordSpaceHelper.hpp"
|
||||
#include <Helpers/NetworkingObjects/NetObjTemporaryPtr.hpp>
|
||||
#include <Helpers/NetworkingObjects/NetObjManager.hpp>
|
||||
|
||||
class ClientData {
|
||||
public:
|
||||
struct InitStruct {
|
||||
CoordSpaceHelper camCoords;
|
||||
Vector2f windowSize = {1000.0f, 1000.0f};
|
||||
Vector2f cursorPos = {1.0f, 1.0f};
|
||||
|
||||
Vector3f cursorColor = {1.0f, 1.0f, 1.0f};
|
||||
std::string displayName;
|
||||
};
|
||||
|
||||
ClientData();
|
||||
ClientData(const InitStruct& initStruct);
|
||||
static void register_class(World& world);
|
||||
static void set_cursor_pos(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, Vector2f newPos);
|
||||
static void set_window_size(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, Vector2f newWindowSize);
|
||||
static void set_camera_coords(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, const CoordSpaceHelper& newCoords);
|
||||
static void send_chat_message(const NetworkingObjects::NetObjTemporaryPtr<ClientData>& o, World& world, const std::string& chatMessage);
|
||||
void set_display_name(const std::string& newDisplayName);
|
||||
void set_cursor_color(const Vector3f& newCursorColor);
|
||||
|
||||
const CoordSpaceHelper& get_cam_coords() const;
|
||||
const Vector2f& get_window_size() const;
|
||||
const Vector2f& get_cursor_pos() const;
|
||||
const std::string& get_display_name() const;
|
||||
const Vector3f& get_cursor_color() const;
|
||||
|
||||
void draw_cursor(SkCanvas* canvas, const DrawData& drawData) const;
|
||||
|
||||
template <typename Archive> void serialize(Archive& a) {
|
||||
a(camCoords, windowSize, cursorPos, cursorColor, displayName);
|
||||
}
|
||||
private:
|
||||
void set_from_init_struct(const InitStruct& initStruct);
|
||||
CoordSpaceHelper camCoords;
|
||||
Vector2f windowSize;
|
||||
Vector2f cursorPos;
|
||||
|
||||
Vector3f cursorColor;
|
||||
std::string displayName;
|
||||
};
|
||||
|
||||
|
|
@ -7,11 +7,8 @@ enum ServerCommands : MessageCommandType {
|
|||
SERVER_KEEP_ALIVE,
|
||||
SERVER_INITIAL_DATA,
|
||||
SERVER_UPDATE_NETWORK_OBJECT,
|
||||
SERVER_MOVE_CAMERA,
|
||||
SERVER_MOVE_SCREEN_MOUSE,
|
||||
SERVER_NEW_RESOURCE_ID,
|
||||
SERVER_NEW_RESOURCE_DATA,
|
||||
SERVER_CHAT_MESSAGE
|
||||
SERVER_NEW_RESOURCE_DATA
|
||||
};
|
||||
|
||||
enum ClientCommands : MessageCommandType {
|
||||
|
|
@ -19,13 +16,8 @@ enum ClientCommands : MessageCommandType {
|
|||
CLIENT_KEEP_ALIVE,
|
||||
CLIENT_INITIAL_DATA,
|
||||
CLIENT_UPDATE_NETWORK_OBJECT,
|
||||
CLIENT_USER_CONNECT,
|
||||
CLIENT_USER_DISCONNECT,
|
||||
CLIENT_MOVE_CAMERA,
|
||||
CLIENT_MOVE_SCREEN_MOUSE,
|
||||
CLIENT_NEW_RESOURCE_ID,
|
||||
CLIENT_NEW_RESOURCE_DATA,
|
||||
CLIENT_CHAT_MESSAGE
|
||||
CLIENT_NEW_RESOURCE_DATA
|
||||
};
|
||||
|
||||
// Arbitrary value. Higher scale up values lead to less scale up events (which can cause stuttering), but leads to larger numbers overall, which can cause a tiny bit of lag and increased memory usage
|
||||
|
|
@ -1,16 +1,10 @@
|
|||
#include "ConnectionManager.hpp"
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "CommandList.hpp"
|
||||
#include <chrono>
|
||||
#include "World.hpp"
|
||||
#include <Helpers/Logger.hpp>
|
||||
|
||||
void ConnectionManager::init_local_p2p(World& initWorld, const std::string& serverLocalID) {
|
||||
localServer = std::make_unique<MainServer>(initWorld, serverLocalID);
|
||||
client = std::make_shared<NetClient>(*localServer->netServer);
|
||||
lastKeepAliveTime = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void ConnectionManager::connect_p2p(World& initWorld, const std::string& serverFullID) {
|
||||
client = std::make_shared<NetClient>(serverFullID);
|
||||
lastKeepAliveTime = std::chrono::steady_clock::now();
|
||||
|
|
@ -19,9 +13,6 @@ void ConnectionManager::connect_p2p(World& initWorld, const std::string& serverF
|
|||
}
|
||||
|
||||
void ConnectionManager::update() {
|
||||
if(localServer) {
|
||||
localServer->update();
|
||||
}
|
||||
if(client) {
|
||||
client->update();
|
||||
if(std::chrono::steady_clock::now() - lastKeepAliveTime > std::chrono::seconds(2)) {
|
||||
|
|
@ -40,14 +31,6 @@ bool ConnectionManager::is_client_disconnected() {
|
|||
return client && client->is_disconnected();
|
||||
}
|
||||
|
||||
bool ConnectionManager::is_host_disconnected() {
|
||||
return localServer && localServer->netServer->is_disconnected();
|
||||
}
|
||||
|
||||
bool ConnectionManager::host_exists() {
|
||||
return localServer != nullptr;
|
||||
}
|
||||
|
||||
bool ConnectionManager::client_exists() {
|
||||
return client != nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
#include "Server/MainServer.hpp"
|
||||
#include <Helpers/Networking/NetClient.hpp>
|
||||
|
||||
class World;
|
||||
|
||||
class ConnectionManager {
|
||||
public:
|
||||
void init_local_p2p(World& initWorld, const std::string& serverLocalID);
|
||||
void connect_p2p(World& initWorld, const std::string& serverFullID);
|
||||
void update();
|
||||
void client_add_recv_callback(uint32_t commandID, const NetClientRecvCallback &callback);
|
||||
|
|
@ -13,11 +13,9 @@ class ConnectionManager {
|
|||
client->send_items_to_server(channel, items...);
|
||||
}
|
||||
bool is_client_disconnected();
|
||||
bool is_host_disconnected();
|
||||
bool host_exists();
|
||||
bool client_exists();
|
||||
NetLibrary::DownloadProgress client_get_resource_retrieval_progress();
|
||||
std::unique_ptr<MainServer> localServer;
|
||||
private:
|
||||
std::shared_ptr<NetClient> client;
|
||||
std::chrono::steady_clock::time_point lastKeepAliveTime;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
#include "DrawCamera.hpp"
|
||||
#include "DrawingProgram/DrawingProgramToolBase.hpp"
|
||||
#include "Helpers/FixedPoint.hpp"
|
||||
#include "Helpers/MathExtras.hpp"
|
||||
#include "MainProgram.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "World.hpp"
|
||||
#include "InputManager.hpp"
|
||||
#include <iostream>
|
||||
|
||||
DrawCamera::DrawCamera():
|
||||
c({0, 0}, WorldScalar(1000000), 0.0)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include "GridModifyTool.hpp"
|
||||
#include "../InputManager.hpp"
|
||||
#include "../SharedTypes.hpp"
|
||||
#include "../Server/CommandList.hpp"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <Helpers/ConvertVec.hpp>
|
||||
|
|
@ -80,13 +79,6 @@ void DrawingProgram::parallel_loop_all_components(std::function<void(const Canva
|
|||
parallel_loop_container(components->get_data(), func);
|
||||
}
|
||||
|
||||
std::unordered_set<ServerClientID> DrawingProgram::get_used_resources() const {
|
||||
std::unordered_set<ServerClientID> toRet;
|
||||
//for(auto& c : components->get_data())
|
||||
// c->obj->get_used_resources(toRet);
|
||||
return toRet;
|
||||
}
|
||||
|
||||
void DrawingProgram::erase_component_set(const std::unordered_set<CanvasComponentContainer::ObjInfoSharedPtr>& compsToErase) {
|
||||
std::unordered_set<NetworkingObjects::NetObjID> idsToErase;
|
||||
for(auto& c : compsToErase)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ class DrawingProgram {
|
|||
void add_file_to_canvas_by_path(const std::filesystem::path& filePath, Vector2f dropPos, bool addInSameThread);
|
||||
void add_file_to_canvas_by_data(const std::string& fileName, std::string_view fileBuffer, Vector2f dropPos);
|
||||
|
||||
std::unordered_set<ServerClientID> get_used_resources() const;
|
||||
void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version);
|
||||
void save_file(cereal::PortableBinaryOutputArchive& a) const;
|
||||
World& world;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "EyeDropperTool.hpp"
|
||||
#include "DrawingProgram.hpp"
|
||||
#include "../Server/CommandList.hpp"
|
||||
#include "../MainProgram.hpp"
|
||||
#include "../DrawData.hpp"
|
||||
#include "DrawingProgramToolBase.hpp"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#include "ScreenshotTool.hpp"
|
||||
#include "DrawingProgram.hpp"
|
||||
#include "../Server/CommandList.hpp"
|
||||
#include "../MainProgram.hpp"
|
||||
#include "../DrawData.hpp"
|
||||
#include "DrawingProgramToolBase.hpp"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
#include "GridManager.hpp"
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "SharedTypes.hpp"
|
||||
#include "World.hpp"
|
||||
#include "MainProgram.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
GridManager::GridManager(World& w):
|
||||
world(w) {}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
#include <optional>
|
||||
|
||||
#include "Server/CommandList.hpp"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <EmscriptenHelpers/emscripten_browser_clipboard.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include <include/core/SkData.h>
|
||||
#include <include/core/SkSurfaceProps.h>
|
||||
#include "InputManager.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include <cereal/types/vector.hpp>
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include <Eigen/Core>
|
||||
|
|
@ -137,7 +136,7 @@ void MainProgram::update() {
|
|||
void MainProgram::update_display_names() {
|
||||
for(auto& w : worlds) {
|
||||
if(!w->network_being_used())
|
||||
w->displayName = displayName;
|
||||
w->ownClientData->set_display_name(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,13 +62,6 @@ class MainProgram {
|
|||
SDL_Window* sdlWindow;
|
||||
} window;
|
||||
|
||||
struct Clipboard {
|
||||
std::vector<std::shared_ptr<DrawComponent>> components;
|
||||
std::unordered_map<ServerClientID, ResourceData> resources;
|
||||
WorldVec pos;
|
||||
WorldScalar inverseScale;
|
||||
} clipboard;
|
||||
|
||||
std::shared_ptr<FontData> fonts;
|
||||
TimePoint deltaTime;
|
||||
Toolbar toolbar;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <include/core/SkImage.h>
|
||||
#include <Helpers/NetworkingObjects/NetObjID.hpp>
|
||||
#include "ResourceDisplay/SvgResourceDisplay.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "CommandList.hpp"
|
||||
#include "ResourceDisplay/ImageResourceDisplay.hpp"
|
||||
#include "ResourceDisplay/FileResourceDisplay.hpp"
|
||||
#include <cereal/types/string.hpp>
|
||||
|
|
@ -19,16 +19,14 @@ ResourceManager::ResourceManager(World& initWorld):
|
|||
|
||||
void ResourceManager::init_client_callbacks() {
|
||||
world.con.client_add_recv_callback(SERVER_NEW_RESOURCE_ID, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
if(!world.con.host_exists()) {
|
||||
NetworkingObjects::NetObjID idBeingRetrieved;
|
||||
message(idBeingRetrieved);
|
||||
// There is a scenario where the resource id and data messages can be sent twice for the same resource (a resource can be sent early before CLIENT_INITIAL_DATA is sent, and then resent with CLIENT_INITIAL_DATA), so check if resource already exists, and only keep track of the ID if the resource doesn't exist yet
|
||||
if(!world.netObjMan.get_obj_temporary_ref_from_id<ResourceData>(idBeingRetrieved))
|
||||
resourcesBeingRetrieved.emplace(idBeingRetrieved, 0);
|
||||
}
|
||||
NetworkingObjects::NetObjID idBeingRetrieved;
|
||||
message(idBeingRetrieved);
|
||||
// There is a scenario where the resource id and data messages can be sent twice for the same resource (a resource can be sent early before CLIENT_INITIAL_DATA is sent, and then resent with CLIENT_INITIAL_DATA), so check if resource already exists, and only keep track of the ID if the resource doesn't exist yet
|
||||
if(!world.netObjMan.get_obj_temporary_ref_from_id<ResourceData>(idBeingRetrieved))
|
||||
resourcesBeingRetrieved.emplace(idBeingRetrieved, std::weak_ptr<NetServer::ClientData>());
|
||||
});
|
||||
world.con.client_add_recv_callback(SERVER_NEW_RESOURCE_DATA, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
if(!world.con.host_exists() && !resourcesBeingRetrieved.empty()) { // If the resource was sent for the second time, this will be empty, so we can ignore the message
|
||||
if(!resourcesBeingRetrieved.empty()) { // If the resource was sent for the second time, this will be empty, so we can ignore the message
|
||||
ResourceData newResource;
|
||||
message(newResource);
|
||||
resourceList.emplace_back(world.netObjMan.make_obj_direct_with_specific_id<ResourceData>(resourcesBeingRetrieved.begin()->first, newResource));
|
||||
|
|
@ -38,21 +36,21 @@ void ResourceManager::init_client_callbacks() {
|
|||
}
|
||||
|
||||
void ResourceManager::init_server_callbacks() {
|
||||
world.con.localServer->netServer->add_recv_callback(CLIENT_NEW_RESOURCE_ID, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
world.netServer->add_recv_callback(CLIENT_NEW_RESOURCE_ID, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
NetworkingObjects::NetObjID idBeingRetrieved;
|
||||
message(idBeingRetrieved);
|
||||
resourcesBeingRetrieved.emplace(idBeingRetrieved, client->customID);
|
||||
resourcesBeingRetrieved.emplace(idBeingRetrieved, client);
|
||||
});
|
||||
world.con.localServer->netServer->add_recv_callback(CLIENT_NEW_RESOURCE_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
world.netServer->add_recv_callback(CLIENT_NEW_RESOURCE_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
ResourceData newResource;
|
||||
message(newResource);
|
||||
auto it = std::find_if(resourcesBeingRetrieved.begin(), resourcesBeingRetrieved.end(), [&client](auto& p) {
|
||||
return p.second == client->customID;
|
||||
return (!p.second.expired() && p.second.lock() == client);
|
||||
});
|
||||
resourceList.emplace_back(world.netObjMan.make_obj_direct_with_specific_id<ResourceData>(it->first, newResource));
|
||||
world.con.localServer->netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceList.back().get_net_id());
|
||||
world.con.localServer->netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, newResource);
|
||||
resourcesBeingRetrieved.erase(resourceList.back().get_net_id());
|
||||
world.netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceList.back().get_net_id());
|
||||
world.netServer->send_items_to_all_clients_except(client, RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, newResource);
|
||||
resourcesBeingRetrieved.erase(it);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -60,18 +58,13 @@ float ResourceManager::get_resource_retrieval_progress(const NetworkingObjects::
|
|||
auto resourceClientID = resourcesBeingRetrieved.find(id);
|
||||
if(resourceClientID == resourcesBeingRetrieved.end())
|
||||
return 0.0f;
|
||||
if(world.con.localServer) {
|
||||
uint64_t clientIDToLookFor = resourceClientID->second;
|
||||
|
||||
const std::vector<std::shared_ptr<NetServer::ClientData>>& clientListInNetServer = world.con.localServer->netServer->get_client_list();
|
||||
auto netClientIt = std::find_if(clientListInNetServer.begin(), clientListInNetServer.end(), [&clientIDToLookFor](auto& nC) {
|
||||
return nC->customID == clientIDToLookFor;
|
||||
});
|
||||
if(netClientIt == clientListInNetServer.end()) {
|
||||
resourcesBeingRetrieved.erase(resourceClientID); // Client disconnected, remove it from the list
|
||||
if(world.netServer) {
|
||||
std::weak_ptr<NetServer::ClientData> clientIDToLookFor = resourceClientID->second;
|
||||
if(clientIDToLookFor.expired()) {
|
||||
resourcesBeingRetrieved.erase(resourceClientID);
|
||||
return 0.0f;
|
||||
}
|
||||
auto progressBytes = (*netClientIt)->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL);
|
||||
auto progressBytes = clientIDToLookFor.lock()->get_progress_into_fragmented_message(RESOURCE_COMMAND_CHANNEL);
|
||||
if(progressBytes.totalBytes == 0)
|
||||
return 0.0f;
|
||||
return static_cast<float>(progressBytes.downloadedBytes) / static_cast<float>(progressBytes.totalBytes);
|
||||
|
|
@ -136,9 +129,9 @@ const NetworkingObjects::NetObjOwnerPtr<ResourceData>& ResourceManager::add_reso
|
|||
return *it;
|
||||
}
|
||||
auto& resourceInsert = resourceList.emplace_back(world.netObjMan.make_obj_direct<ResourceData>(resource));
|
||||
if(world.con.localServer) {
|
||||
world.con.localServer->netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id());
|
||||
world.con.localServer->netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource);
|
||||
if(world.netServer) {
|
||||
world.netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id());
|
||||
world.netServer->send_items_to_all_clients(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_DATA, resource);
|
||||
}
|
||||
else {
|
||||
world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_NEW_RESOURCE_ID, resourceInsert.get_net_id());
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class ResourceManager {
|
|||
private:
|
||||
std::unordered_map<NetworkingObjects::NetObjID, std::unique_ptr<ResourceDisplay>> displays;
|
||||
|
||||
std::unordered_map<NetworkingObjects::NetObjID, uint64_t> resourcesBeingRetrieved;
|
||||
std::unordered_map<NetworkingObjects::NetObjID, std::weak_ptr<NetServer::ClientData>> resourcesBeingRetrieved;
|
||||
std::vector<NetworkingObjects::NetObjOwnerPtr<ResourceData>> resourceList;
|
||||
|
||||
static std::array<const SkCodecs::Decoder, 5> decoders;
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
#pragma once
|
||||
#include "../SharedTypes.hpp"
|
||||
#include <Helpers/Serializers.hpp>
|
||||
#include "../CoordSpaceHelper.hpp"
|
||||
#include "../ResourceManager.hpp"
|
||||
#include <Helpers/Networking/NetServer.hpp>
|
||||
#include <chrono>
|
||||
|
||||
class ClientData {
|
||||
public:
|
||||
CoordSpaceHelper camCoords;
|
||||
Vector2f windowSize = {1000.0f, 1000.0f};
|
||||
Vector2f cursorPos = {1.0f, 1.0f};
|
||||
|
||||
Vector3f cursorColor = {1.0f, 1.0f, 1.0f};
|
||||
std::string displayName;
|
||||
ServerPortionID serverID = 0;
|
||||
|
||||
uint64_t canvasScale = 0;
|
||||
|
||||
template <typename Archive> void serialize(Archive& a) {
|
||||
a(camCoords, windowSize, cursorPos, cursorColor, displayName);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
#include "MainServer.hpp"
|
||||
#include "CommandList.hpp"
|
||||
#include "Helpers/HsvRgb.hpp"
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "ServerData.hpp"
|
||||
#include "../SharedTypes.hpp"
|
||||
#include "../CoordSpaceHelper.hpp"
|
||||
#include <cereal/archives/portable_binary.hpp>
|
||||
#include <cereal/types/vector.hpp>
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include <cereal/types/utility.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <cereal/types/unordered_set.hpp>
|
||||
#include <Helpers/Serializers.hpp>
|
||||
#include <Helpers/Random.hpp>
|
||||
#include <chrono>
|
||||
#include <limits>
|
||||
#include <fstream>
|
||||
#include "../World.hpp"
|
||||
|
||||
MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
|
||||
world(initWorld)
|
||||
{
|
||||
data.canvasScale = world.canvasScale;
|
||||
|
||||
lastKeepAliveSent = std::chrono::steady_clock::now();
|
||||
|
||||
netServer = std::make_shared<NetServer>(serverLocalID);
|
||||
NetLibrary::register_server(netServer);
|
||||
|
||||
world.netObjMan.set_server(netServer, CLIENT_UPDATE_NETWORK_OBJECT);
|
||||
|
||||
netServer->add_recv_callback(SERVER_INITIAL_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
bool isDirectConnect;
|
||||
ClientData newClient;
|
||||
Vector3f hsv;
|
||||
hsv[0] = Random::get().real_range(0.0f, 360.0f);
|
||||
hsv[1] = Random::get().real_range(0.3f, 0.7f);
|
||||
hsv[2] = 1.0;
|
||||
newClient.cursorColor = hsv_to_rgb<Vector3f>(hsv);
|
||||
newClient.canvasScale = data.canvasScale;
|
||||
message(newClient.displayName, isDirectConnect);
|
||||
ensure_display_name_unique(newClient.displayName);
|
||||
|
||||
if(isDirectConnect) {
|
||||
fileDisplayName = newClient.displayName;
|
||||
message(newClient.camCoords, newClient.windowSize);
|
||||
}
|
||||
else {
|
||||
auto& [randomClientServerID, randomClient] = *clients.begin();
|
||||
newClient.camCoords = randomClient.camCoords;
|
||||
newClient.windowSize = randomClient.windowSize;
|
||||
}
|
||||
|
||||
newClient.serverID = Random::get().int_range<ServerPortionID>(1, std::numeric_limits<ServerPortionID>::max());
|
||||
client->customID = newClient.serverID;
|
||||
netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_USER_CONNECT, newClient.serverID, newClient.displayName, newClient.cursorColor);
|
||||
if(isDirectConnect)
|
||||
netServer->send_items_to_client(client, RELIABLE_COMMAND_CHANNEL, CLIENT_INITIAL_DATA, isDirectConnect, newClient.serverID, newClient.cursorColor);
|
||||
else {
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive a(*ss);
|
||||
a(CLIENT_INITIAL_DATA, isDirectConnect, newClient.serverID, newClient.cursorColor, newClient.displayName, newClient.camCoords, newClient.windowSize, fileDisplayName, clients, data);
|
||||
world.bMan.bookmarks.write_create_message(a);
|
||||
world.gridMan.grids.write_create_message(a);
|
||||
world.drawProg.write_components_server(a);
|
||||
world.canvasTheme.write_create_message(a);
|
||||
}
|
||||
netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss);
|
||||
for(auto& r : world.rMan.resource_list()) {
|
||||
netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, r.get_net_id());
|
||||
netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, *r);
|
||||
}
|
||||
}
|
||||
clients.emplace(newClient.serverID, newClient);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_UPDATE_NETWORK_OBJECT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
world.netObjMan.read_update_message(message, client);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_MOVE_CAMERA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
auto& c = clients[client->customID];
|
||||
message(c.camCoords, c.windowSize);
|
||||
netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_MOVE_CAMERA, c.serverID, c.camCoords, c.windowSize);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_MOVE_SCREEN_MOUSE, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
auto& c = clients[client->customID];
|
||||
message(c.cursorPos);
|
||||
netServer->send_items_to_all_clients_except(client, UNRELIABLE_COMMAND_CHANNEL, CLIENT_MOVE_SCREEN_MOUSE, c.serverID, c.cursorPos);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_KEEP_ALIVE, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
});
|
||||
netServer->add_disconnect_callback([&](std::shared_ptr<NetServer::ClientData> client) {
|
||||
auto it = clients.find(client->customID);
|
||||
if(it != clients.end()) {
|
||||
netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_USER_DISCONNECT, client->customID);
|
||||
clients.erase(it);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MainServer::ensure_display_name_unique(std::string& displayName) {
|
||||
for(;;) {
|
||||
bool isUnique = true;
|
||||
for(auto& [id, client] : clients) {
|
||||
if(client.displayName == displayName) {
|
||||
size_t leftParenthesisIndex = displayName.find_last_of('(');
|
||||
size_t rightParenthesisIndex = displayName.find_last_of(')');
|
||||
bool failToIncrement = true;
|
||||
if(leftParenthesisIndex != std::string::npos && rightParenthesisIndex != std::string::npos && leftParenthesisIndex < rightParenthesisIndex) {
|
||||
std::string numStr = displayName.substr(leftParenthesisIndex + 1, rightParenthesisIndex - leftParenthesisIndex - 1);
|
||||
bool isAllDigits = true;
|
||||
for(char c : numStr) {
|
||||
if(!isdigit(c)) {
|
||||
isAllDigits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isAllDigits) {
|
||||
try {
|
||||
int s = std::stoi(numStr);
|
||||
s++;
|
||||
displayName = displayName.substr(0, leftParenthesisIndex);
|
||||
displayName += "(" + std::to_string(s) + ")";
|
||||
failToIncrement = false;
|
||||
}
|
||||
catch(...) {}
|
||||
}
|
||||
}
|
||||
if(failToIncrement)
|
||||
displayName += " (2)";
|
||||
isUnique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isUnique)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MainServer::update() {
|
||||
netServer->update();
|
||||
if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) {
|
||||
netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE);
|
||||
lastKeepAliveSent = std::chrono::steady_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
MainServer::~MainServer() {
|
||||
//netServer->close_server();
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#pragma once
|
||||
#include <Helpers/Networking/NetServer.hpp>
|
||||
#include <chrono>
|
||||
#include "ClientData.hpp"
|
||||
#include "Helpers/Networking/NetLibrary.hpp"
|
||||
#include "ServerData.hpp"
|
||||
|
||||
class MainServer {
|
||||
public:
|
||||
MainServer(World& initWorld, const std::string& serverLocalID);
|
||||
void update();
|
||||
~MainServer();
|
||||
std::shared_ptr<NetServer> netServer;
|
||||
std::unordered_map<ServerPortionID, ClientData> clients;
|
||||
private:
|
||||
World& world;
|
||||
void ensure_display_name_unique(std::string& displayName);
|
||||
ServerData data;
|
||||
std::string fileDisplayName;
|
||||
std::chrono::steady_clock::time_point lastKeepAliveSent;
|
||||
};
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#include "ServerData.hpp"
|
||||
|
||||
void ServerData::save(cereal::PortableBinaryOutputArchive& a) const {
|
||||
a(canvasScale);
|
||||
}
|
||||
|
||||
void ServerData::load(cereal::PortableBinaryInputArchive& a) {
|
||||
a(canvasScale);
|
||||
}
|
||||
|
||||
void ServerData::scale_up(const WorldScalar& scaleUpAmount) {
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
#include "cereal/archives/portable_binary.hpp"
|
||||
#include "../SharedTypes.hpp"
|
||||
#include "../ResourceManager.hpp"
|
||||
#include "../WorldGrid.hpp"
|
||||
|
||||
class DrawComponent;
|
||||
|
||||
class ServerData {
|
||||
public:
|
||||
uint64_t canvasScale = 0;
|
||||
|
||||
void save(cereal::PortableBinaryOutputArchive& a) const;
|
||||
void load(cereal::PortableBinaryInputArchive& a);
|
||||
void scale_up(const WorldScalar& scaleUpAmount);
|
||||
};
|
||||
|
|
@ -10,26 +10,7 @@ using namespace Eigen;
|
|||
|
||||
typedef Vector<WorldScalar, 2> WorldVec;
|
||||
|
||||
enum DrawComponentType : uint8_t {
|
||||
DRAWCOMPONENT_BRUSHSTROKE = 0,
|
||||
DRAWCOMPONENT_RECTANGLE,
|
||||
DRAWCOMPONENT_ELLIPSE,
|
||||
DRAWCOMPONENT_TEXTBOX,
|
||||
DRAWCOMPONENT_IMAGE
|
||||
};
|
||||
|
||||
typedef uint64_t ClientPortionID;
|
||||
typedef uint64_t ServerPortionID;
|
||||
typedef std::pair<ServerPortionID, ClientPortionID> ServerClientID;
|
||||
|
||||
template <> struct std::hash<ServerClientID> {
|
||||
size_t operator()(const ServerClientID& v) const
|
||||
{
|
||||
uint64_t h = 0;
|
||||
hash_combine(h, v.first, v.second);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
typedef uint64_t NetClientID;
|
||||
|
||||
template <typename F, typename S> std::ostream& operator<<(std::ostream& os, const std::pair<F, S>& p) {
|
||||
os << p.first << ", " << p.second;
|
||||
|
|
|
|||
|
|
@ -1275,33 +1275,37 @@ void Toolbar::player_list() {
|
|||
gui.obstructing_window();
|
||||
gui.push_id("client list");
|
||||
gui.text_label_centered("Player List");
|
||||
gui.left_to_right_line_layout([&]() {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)}
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(SkColor4f{main.world->userColor.x(), main.world->userColor.y(), main.world->userColor.z(), 1.0f}),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(3)
|
||||
}) {}
|
||||
gui.text_label(main.world->displayName);
|
||||
});
|
||||
size_t num = 0;
|
||||
for(auto& [id, client] : main.world->clients) {
|
||||
gui.push_id(num++);
|
||||
if(!main.world->clientStillConnecting) {
|
||||
gui.left_to_right_line_layout([&]() {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)}
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(SkColor4f{client.cursorColor.x(), client.cursorColor.y(), client.cursorColor.z(), 1.0f}),
|
||||
.backgroundColor = convert_vec4<Clay_Color>(SkColor4f{main.world->ownClientData->get_cursor_color().x(), main.world->ownClientData->get_cursor_color().y(), main.world->ownClientData->get_cursor_color().z(), 1.0f}),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(3)
|
||||
}) {}
|
||||
gui.text_label(client.displayName);
|
||||
CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
|
||||
if(gui.text_button("teleport button", "Jump To"))
|
||||
main.world->drawData.cam.smooth_move_to(*main.world, client.camCoords, client.windowSize);
|
||||
gui.text_label(main.world->ownClientData->get_display_name());
|
||||
});
|
||||
gui.pop_id();
|
||||
size_t num = 0;
|
||||
for(auto& client : main.world->clients->get_data()) {
|
||||
if(client != main.world->ownClientData) {
|
||||
gui.push_id(num++);
|
||||
gui.left_to_right_line_layout([&]() {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(20), .height = CLAY_SIZING_FIXED(20)}
|
||||
},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(SkColor4f{client->get_cursor_color().x(), client->get_cursor_color().y(), client->get_cursor_color().z(), 1.0f}),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(3)
|
||||
}) {}
|
||||
gui.text_label(client->get_display_name());
|
||||
CLAY_AUTO_ID({.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
|
||||
if(gui.text_button("teleport button", "Jump To"))
|
||||
main.world->drawData.cam.smooth_move_to(*main.world, client->get_cam_coords(), client->get_window_size());
|
||||
});
|
||||
gui.pop_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(gui.text_button_wide("close list", "Done"))
|
||||
playerMenuOpen = false;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#include "GUIStuff/GUIManager.hpp"
|
||||
#include "DrawData.hpp"
|
||||
#include "Helpers/FileDownloader.hpp"
|
||||
#include "Server/CommandList.hpp"
|
||||
#include <filesystem>
|
||||
#include <modules/skparagraph/include/Paragraph.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
|
|
|||
274
src/World.cpp
274
src/World.cpp
|
|
@ -8,7 +8,9 @@
|
|||
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
|
||||
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
|
||||
#include <cereal/types/unordered_map.hpp>
|
||||
#include "Server/CommandList.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjTemporaryPtr.decl.hpp"
|
||||
#include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp"
|
||||
#include "CommandList.hpp"
|
||||
#include "MainProgram.hpp"
|
||||
#include "SharedTypes.hpp"
|
||||
#include "Toolbar.hpp"
|
||||
|
|
@ -42,13 +44,12 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
|||
canvasTheme(*this)
|
||||
{
|
||||
init_net_obj_type_list();
|
||||
init_client_data_list();
|
||||
gridMan.init();
|
||||
bMan.init();
|
||||
drawProg.init();
|
||||
canvasTheme.init();
|
||||
|
||||
displayName = main.displayName;
|
||||
|
||||
netSource = worldInfo.netSource;
|
||||
|
||||
if(worldInfo.conType == CONNECTIONTYPE_CLIENT || worldInfo.conType == CONNECTIONTYPE_SERVER)
|
||||
|
|
@ -76,9 +77,36 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
|
|||
}
|
||||
}
|
||||
|
||||
rMan.init_client_callbacks();
|
||||
init_client_callbacks();
|
||||
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, false);
|
||||
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, main.displayName);
|
||||
}
|
||||
|
||||
void World::init_client_data_list() {
|
||||
if(netObjMan.is_server()) {
|
||||
clients = netObjMan.make_obj<NetworkingObjects::NetObjUnorderedSet<ClientData>>();
|
||||
ownClientData = clients->emplace_direct(clients, ClientData::InitStruct{
|
||||
.cursorColor = get_random_cursor_color(),
|
||||
.displayName = main.displayName
|
||||
});
|
||||
init_client_data_list_callbacks();
|
||||
}
|
||||
}
|
||||
|
||||
Vector3f World::get_random_cursor_color() {
|
||||
Vector3f hsv;
|
||||
hsv[0] = Random::get().real_range(0.0f, 360.0f);
|
||||
hsv[1] = Random::get().real_range(0.3f, 0.7f);
|
||||
hsv[2] = 1.0;
|
||||
return hsv_to_rgb<Vector3f>(hsv);
|
||||
}
|
||||
|
||||
void World::init_client_data_list_callbacks() {
|
||||
clients->set_insert_callback([&](const NetworkingObjects::NetObjOwnerPtr<ClientData>& objPtr) {
|
||||
add_chat_message(objPtr->get_display_name(), "joined", Toolbar::ChatMessage::Type::JOIN);
|
||||
});
|
||||
clients->set_erase_callback([&](const NetworkingObjects::NetObjOwnerPtr<ClientData>& objPtr) {
|
||||
add_chat_message(objPtr->get_display_name(), "left", Toolbar::ChatMessage::Type::JOIN);
|
||||
});
|
||||
}
|
||||
|
||||
void World::init_net_obj_type_list() {
|
||||
|
|
@ -90,83 +118,74 @@ void World::init_net_obj_type_list() {
|
|||
CanvasComponentContainer::register_class(netObjMan);
|
||||
NetworkingObjects::register_ordered_list_class<CanvasComponentContainer>(netObjMan);
|
||||
canvasTheme.register_class();
|
||||
ClientData::register_class(*this);
|
||||
NetworkingObjects::register_unordered_set_class<ClientData>(netObjMan);
|
||||
}
|
||||
|
||||
void World::init_server_callbacks() {
|
||||
con.localServer->netServer->add_recv_callback(SERVER_CHAT_MESSAGE, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
std::string chatMessage;
|
||||
message(chatMessage);
|
||||
add_chat_message(clients[client->customID].displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
|
||||
con.localServer->netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_CHAT_MESSAGE, client->customID, chatMessage);
|
||||
rMan.init_server_callbacks();
|
||||
netServer->add_recv_callback(SERVER_INITIAL_DATA, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
std::cout << "Received server init data" << std::endl;
|
||||
ClientData::InitStruct newClientData;
|
||||
newClientData.cursorColor = get_random_cursor_color();
|
||||
message(newClientData.displayName);
|
||||
ensure_display_name_unique(newClientData.displayName);
|
||||
|
||||
newClientData.camCoords = ownClientData->get_cam_coords();
|
||||
newClientData.windowSize = ownClientData->get_window_size();
|
||||
|
||||
NetworkingObjects::NetObjTemporaryPtr<ClientData> clientDataObjPtr = clients->emplace_direct(clients, newClientData);
|
||||
client->customID = clientDataObjPtr.get_net_id().data;
|
||||
auto ss(std::make_shared<std::stringstream>());
|
||||
{
|
||||
cereal::PortableBinaryOutputArchive a(*ss);
|
||||
a(CLIENT_INITIAL_DATA, name, clientDataObjPtr.get_net_id());
|
||||
bMan.bookmarks.write_create_message(a);
|
||||
gridMan.grids.write_create_message(a);
|
||||
drawProg.write_components_server(a);
|
||||
canvasTheme.write_create_message(a);
|
||||
clients.write_create_message(a);
|
||||
}
|
||||
netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss);
|
||||
for(auto& r : rMan.resource_list()) {
|
||||
netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_ID, r.get_net_id());
|
||||
netServer->send_items_to_client(client, RESOURCE_COMMAND_CHANNEL, CLIENT_NEW_RESOURCE_DATA, *r);
|
||||
}
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_UPDATE_NETWORK_OBJECT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
netObjMan.read_update_message(message, client);
|
||||
});
|
||||
netServer->add_recv_callback(SERVER_KEEP_ALIVE, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
|
||||
});
|
||||
netServer->add_disconnect_callback([&](std::shared_ptr<NetServer::ClientData> client) {
|
||||
NetworkingObjects::NetObjID idToErase;
|
||||
idToErase.data = client->customID;
|
||||
clients->erase(clients, idToErase);
|
||||
});
|
||||
}
|
||||
|
||||
void World::init_client_callbacks() {
|
||||
rMan.init_client_callbacks();
|
||||
con.client_add_recv_callback(CLIENT_INITIAL_DATA, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
bool isDirectConnect;
|
||||
message(isDirectConnect, ownID, userColor);
|
||||
if(!isDirectConnect) {
|
||||
std::string fileDisplayName;
|
||||
CoordSpaceHelper camCoordsToMoveTo;
|
||||
Vector2f windowSizeToMoveTo;
|
||||
message(displayName);
|
||||
message(camCoordsToMoveTo);
|
||||
message(windowSizeToMoveTo);
|
||||
message(fileDisplayName);
|
||||
message(clients);
|
||||
set_name(fileDisplayName);
|
||||
drawData.cam.smooth_move_to(*main.world, camCoordsToMoveTo, windowSizeToMoveTo, true);
|
||||
message(canvasScale);
|
||||
bMan.bookmarks = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<Bookmark>>(message, nullptr);
|
||||
gridMan.grids = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<WorldGrid>>(message, nullptr);
|
||||
drawProg.read_components_client(message);
|
||||
canvasTheme.read_create_message(message);
|
||||
}
|
||||
std::cout << "Received client init data" << std::endl;
|
||||
std::string fileDisplayName;
|
||||
NetworkingObjects::NetObjID clientDataObjID;
|
||||
message(fileDisplayName, clientDataObjID);
|
||||
set_name(fileDisplayName);
|
||||
bMan.bookmarks = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<Bookmark>>(message, nullptr);
|
||||
gridMan.grids = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<WorldGrid>>(message, nullptr);
|
||||
drawProg.read_components_client(message);
|
||||
canvasTheme.read_create_message(message);
|
||||
|
||||
clients = netObjMan.read_create_message<NetworkingObjects::NetObjUnorderedSet<ClientData>>(message, nullptr);
|
||||
init_client_data_list_callbacks();
|
||||
ownClientData = netObjMan.get_obj_from_id<ClientData>(clientDataObjID);
|
||||
drawData.cam.smooth_move_to(*main.world, ownClientData->get_cam_coords(), ownClientData->get_window_size(), true);
|
||||
|
||||
clientStillConnecting = false;
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_USER_CONNECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
ServerPortionID id;
|
||||
std::string displayName;
|
||||
Vector3f cursorColor;
|
||||
message(id, displayName, cursorColor);
|
||||
clients[id].displayName = displayName;
|
||||
clients[id].cursorColor = cursorColor;
|
||||
add_chat_message(clients[id].displayName, "joined", Toolbar::ChatMessage::Type::JOIN);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_UPDATE_NETWORK_OBJECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
if(!con.host_exists() && !clientStillConnecting) // Dont update a direct connected client (which is just the server), and dont process these until the CLIENT_INITIAL_DATA message is received first
|
||||
netObjMan.read_update_message(message, nullptr);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_USER_DISCONNECT, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
ServerPortionID id;
|
||||
message(id);
|
||||
auto it = clients.find(id);
|
||||
if(it != clients.end()) {
|
||||
add_chat_message(clients[id].displayName, "left", Toolbar::ChatMessage::Type::JOIN);
|
||||
clients.erase(id);
|
||||
}
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_MOVE_CAMERA, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
ServerPortionID id;
|
||||
message(id);
|
||||
auto& c = clients[id];
|
||||
message(c.camCoords, c.windowSize);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_MOVE_SCREEN_MOUSE, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
ServerPortionID id;
|
||||
message(id);
|
||||
auto& c = clients[id];
|
||||
message(c.cursorPos);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_CHAT_MESSAGE, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
if(!con.host_exists() && !clientStillConnecting) { // Dont update a direct connected client (which is just the server), and dont process these until the CLIENT_INITIAL_DATA message is received first
|
||||
ServerPortionID senderID;
|
||||
std::string chatMessage;
|
||||
message(senderID, chatMessage);
|
||||
auto it = clients.find(senderID);
|
||||
if(it != clients.end())
|
||||
add_chat_message(clients[senderID].displayName, chatMessage, Toolbar::ChatMessage::Type::NORMAL);
|
||||
}
|
||||
netObjMan.read_update_message(message, nullptr);
|
||||
});
|
||||
con.client_add_recv_callback(CLIENT_KEEP_ALIVE, [&](cereal::PortableBinaryInputArchive& message) {
|
||||
});
|
||||
|
|
@ -175,11 +194,10 @@ void World::init_client_callbacks() {
|
|||
void World::focus_update() {
|
||||
con.update();
|
||||
|
||||
if(con.is_host_disconnected()) {
|
||||
if(netServer && netServer->is_disconnected()) {
|
||||
Logger::get().log("USERINFO", "Host connection failed");
|
||||
clientStillConnecting = false;
|
||||
clients.clear();
|
||||
netSource.clear();
|
||||
netServer = nullptr;
|
||||
conType = CONNECTIONTYPE_LOCAL;
|
||||
con = ConnectionManager();
|
||||
}
|
||||
|
|
@ -196,15 +214,10 @@ void World::focus_update() {
|
|||
timeToSendCameraData.update_time_since();
|
||||
if(timeToSendCameraData.get_time_since() > SECONDS_TO_SEND_CAMERA_DATA) {
|
||||
timeToSendCameraData.update_time_point();
|
||||
if(!sentCameraData.has_value() || (sentCameraData.value().windowSize != main.window.size.cast<float>().eval() || sentCameraData.value().camTransform != drawData.cam.c)) {
|
||||
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_MOVE_CAMERA, drawData.cam.c, main.window.size.cast<float>().eval());
|
||||
sentCameraData = {
|
||||
.camTransform = drawData.cam.c,
|
||||
.windowSize = main.window.size.cast<float>()
|
||||
};
|
||||
}
|
||||
ownClientData->set_window_size(ownClientData, main.window.size.cast<float>().eval());
|
||||
ownClientData->set_camera_coords(ownClientData, drawData.cam.c);
|
||||
}
|
||||
con.client_send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_MOVE_SCREEN_MOUSE, main.input.mouse.pos);
|
||||
ownClientData->set_cursor_pos(ownClientData, main.input.mouse.pos);
|
||||
drawProg.update();
|
||||
}
|
||||
|
||||
|
|
@ -237,16 +250,18 @@ void World::unfocus_update() {
|
|||
Logger::get().log("USERINFO", "Client connection failed");
|
||||
setToDestroy = true;
|
||||
}
|
||||
if(netServer) {
|
||||
netServer->update();
|
||||
if(std::chrono::steady_clock::now() - lastKeepAliveSent > std::chrono::seconds(2)) {
|
||||
netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_KEEP_ALIVE);
|
||||
lastKeepAliveSent = std::chrono::steady_clock::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::send_chat_message(const std::string& message) {
|
||||
if(!clientStillConnecting) {
|
||||
if(con.localServer)
|
||||
con.localServer->netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_CHAT_MESSAGE, ownID, message);
|
||||
else
|
||||
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_CHAT_MESSAGE, message);
|
||||
add_chat_message(displayName, message, Toolbar::ChatMessage::Type::NORMAL);
|
||||
}
|
||||
if(!clientStillConnecting)
|
||||
ownClientData->send_chat_message(ownClientData, *this, message);
|
||||
}
|
||||
|
||||
void World::add_chat_message(const std::string& name, const std::string& message, Toolbar::ChatMessage::Type type) {
|
||||
|
|
@ -279,18 +294,55 @@ void World::set_name(const std::string& n) {
|
|||
name = n;
|
||||
}
|
||||
|
||||
void World::ensure_display_name_unique(std::string& displayName) {
|
||||
for(;;) {
|
||||
bool isUnique = true;
|
||||
for(auto& client : clients->get_data()) {
|
||||
if(client->get_display_name() == displayName) {
|
||||
size_t leftParenthesisIndex = displayName.find_last_of('(');
|
||||
size_t rightParenthesisIndex = displayName.find_last_of(')');
|
||||
bool failToIncrement = true;
|
||||
if(leftParenthesisIndex != std::string::npos && rightParenthesisIndex != std::string::npos && leftParenthesisIndex < rightParenthesisIndex) {
|
||||
std::string numStr = displayName.substr(leftParenthesisIndex + 1, rightParenthesisIndex - leftParenthesisIndex - 1);
|
||||
bool isAllDigits = true;
|
||||
for(char c : numStr) {
|
||||
if(!isdigit(c)) {
|
||||
isAllDigits = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isAllDigits) {
|
||||
try {
|
||||
int s = std::stoi(numStr);
|
||||
s++;
|
||||
displayName = displayName.substr(0, leftParenthesisIndex);
|
||||
displayName += "(" + std::to_string(s) + ")";
|
||||
failToIncrement = false;
|
||||
}
|
||||
catch(...) {}
|
||||
}
|
||||
}
|
||||
if(failToIncrement)
|
||||
displayName += " (2)";
|
||||
isUnique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isUnique)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void World::start_hosting(const std::string& initNetSource, const std::string& serverLocalID) {
|
||||
if(conType != CONNECTIONTYPE_LOCAL)
|
||||
return;
|
||||
main.init_net_library();
|
||||
con.init_local_p2p(*this, serverLocalID);
|
||||
rMan.init_client_callbacks();
|
||||
rMan.init_server_callbacks();
|
||||
init_client_callbacks();
|
||||
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, true, drawData.cam.c, main.window.size.cast<float>().eval());
|
||||
netServer = std::make_shared<NetServer>(serverLocalID);
|
||||
NetLibrary::register_server(netServer);
|
||||
netObjMan.set_server(netServer, CLIENT_UPDATE_NETWORK_OBJECT);
|
||||
conType = CONNECTIONTYPE_SERVER;
|
||||
netSource = initNetSource;
|
||||
clientStillConnecting = true;
|
||||
init_server_callbacks();
|
||||
}
|
||||
|
||||
void World::save_to_file(const std::filesystem::path& filePathToSaveAt) {
|
||||
|
|
@ -409,34 +461,10 @@ WorldScalar World::calculate_zoom_from_uniform_zoom(WorldScalar uniformZoom, Wor
|
|||
}
|
||||
|
||||
void World::draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData) {
|
||||
for(auto& [id, data] : clients) {
|
||||
if((drawData.cam.c.inverseScale << 10) > data.camCoords.inverseScale && drawData.clampDrawMinimum < data.camCoords.inverseScale) {
|
||||
canvas->save();
|
||||
data.camCoords.transform_sk_canvas(canvas, drawData);
|
||||
|
||||
canvas->translate(data.cursorPos.x(), data.cursorPos.y());
|
||||
|
||||
SkPaint p(SkColor4f{data.cursorColor.x(), data.cursorColor.y(), data.cursorColor.z(), 0.2f});
|
||||
canvas->drawCircle(0.0f, 0.0f, 4.5f, p);
|
||||
p.setStroke(true);
|
||||
p.setStrokeWidth(1.0f);
|
||||
p.setColor4f({data.cursorColor.x(), data.cursorColor.y(), data.cursorColor.z(), 0.7f});
|
||||
canvas->drawCircle(0.0f, 0.0f, 5.0f, p);
|
||||
|
||||
SkFont f = main.toolbar.io->get_font(18.0f);
|
||||
SkFontMetrics metrics;
|
||||
f.getMetrics(&metrics);
|
||||
|
||||
float nextText = f.measureText(data.displayName.c_str(), data.displayName.length(), SkTextEncoding::kUTF8, nullptr);
|
||||
Vector2f bounds{nextText, - metrics.fAscent + metrics.fDescent};
|
||||
|
||||
SkPaint p2(SkColor4f{data.cursorColor.x(), data.cursorColor.y(), data.cursorColor.z(), 0.5f});
|
||||
canvas->drawSimpleText(data.displayName.c_str(), data.displayName.length(), SkTextEncoding::kUTF8, 6.0f, -metrics.fDescent, f, p2);
|
||||
|
||||
SkPaint p3(color_mul_alpha(main.toolbar.io->theme->backColor1, 0.5f));
|
||||
canvas->drawRoundRect(SkRect::MakeXYWH(6.0f, -bounds.y(), bounds.x(), bounds.y()), 3.0f, 3.0f, p3);
|
||||
|
||||
canvas->restore();
|
||||
if(clients) {
|
||||
for(auto& clientDataPtr : clients->get_data()) {
|
||||
if(clientDataPtr != ownClientData)
|
||||
clientDataPtr->draw_cursor(canvas, drawData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <Helpers/NetworkingObjects/DelayUpdateSerializedClassManager.hpp>
|
||||
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
|
||||
#include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp"
|
||||
#include "UndoManager.hpp"
|
||||
#include "BookmarkManager.hpp"
|
||||
#include "ResourceManager.hpp"
|
||||
|
|
@ -12,6 +13,7 @@
|
|||
#include "GridManager.hpp"
|
||||
#include <Helpers/NetworkingObjects/NetObjManager.hpp>
|
||||
#include <filesystem>
|
||||
#include "ClientData.hpp"
|
||||
|
||||
class MainProgram;
|
||||
|
||||
|
|
@ -56,8 +58,6 @@ class World {
|
|||
std::deque<Toolbar::ChatMessage> chatMessages;
|
||||
|
||||
std::string netSource;
|
||||
|
||||
std::string displayName;
|
||||
|
||||
void start_hosting(const std::string& initNetSource, const std::string& serverLocalID);
|
||||
|
||||
|
|
@ -86,39 +86,37 @@ class World {
|
|||
void undo_with_checks();
|
||||
void redo_with_checks();
|
||||
|
||||
ServerPortionID ownID = 0;
|
||||
|
||||
std::filesystem::path filePath;
|
||||
Vector3f userColor = {0.0f, 0.0f, 0.0f};
|
||||
std::string name;
|
||||
std::unordered_map<ServerPortionID, ClientData> clients;
|
||||
|
||||
NetworkingObjects::NetObjTemporaryPtr<ClientData> ownClientData;
|
||||
NetworkingObjects::NetObjOwnerPtr<NetworkingObjects::NetObjUnorderedSet<ClientData>> clients;
|
||||
|
||||
CanvasTheme canvasTheme;
|
||||
|
||||
void scale_up(const WorldScalar& scaleUpAmount);
|
||||
void scale_up_step();
|
||||
|
||||
uint64_t canvasScale = 0;
|
||||
|
||||
bool setToDestroy = false;
|
||||
NetworkingObjects::DelayUpdateSerializedClassManager delayedUpdateObjectManager;
|
||||
private:
|
||||
void init_net_obj_type_list();
|
||||
|
||||
std::shared_ptr<NetServer> netServer;
|
||||
private:
|
||||
Vector3f get_random_cursor_color();
|
||||
void init_client_data_list();
|
||||
void init_client_data_list_callbacks();
|
||||
void init_net_obj_type_list();
|
||||
|
||||
void init_client_callbacks();
|
||||
void init_server_callbacks();
|
||||
void set_name(const std::string& n);
|
||||
|
||||
void draw_other_player_cursors(SkCanvas* canvas, const DrawData& drawData);
|
||||
void ensure_display_name_unique(std::string& displayName);
|
||||
|
||||
TimePoint timeToSendCameraData;
|
||||
struct SentCameraData {
|
||||
CoordSpaceHelper camTransform;
|
||||
Vector2f windowSize;
|
||||
};
|
||||
std::optional<SentCameraData> sentCameraData;
|
||||
|
||||
WorldVec mousePreviousWorldVec = {0, 0};
|
||||
WorldVec mouseWorldMove = {0, 0};
|
||||
|
||||
std::chrono::steady_clock::time_point lastKeepAliveSent;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue