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
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue