GridManager now works on net objects

This commit is contained in:
Yousef Khadadeh 2025-12-10 13:06:45 +03:00
parent 67507a9a39
commit ceafbf8bb6
20 changed files with 214 additions and 222 deletions

View file

@ -1,4 +1,5 @@
#pragma once
#include "Helpers/NetworkingObjects/NetObjPtr.decl.hpp"
#include "NetObjPtr.hpp"
namespace NetworkingObjects {
@ -27,4 +28,10 @@ namespace NetworkingObjects {
},
});
}
template <typename T> void generic_serialized_class_send_update_to_all(const NetworkingObjects::NetObjPtr<T>& o) {
o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetworkingObjects::NetObjPtr<T>& o, cereal::PortableBinaryOutputArchive& a) {
a(*o);
});
}
}

View file

@ -69,6 +69,7 @@ namespace NetworkingObjects {
}
template <typename T> friend class NetObjPtr;
template <typename T> friend class NetObjWeakPtr;
struct SingleObjectData {
NetTypeIDType netTypeID;

View file

@ -56,6 +56,7 @@ namespace NetworkingObjects {
static uint32_t erase(const NetObjPtr<NetObjOrderedList<T>>& l, const NetObjPtr<T>& p) {
return l->erase_by_ptr(l, p);
}
virtual bool contains(const NetObjPtr<T>& p) const = 0;
virtual uint32_t size() const = 0;
virtual const NetObjPtr<T>& at(uint32_t index) const = 0;
virtual bool empty() const = 0;
@ -83,6 +84,9 @@ namespace NetworkingObjects {
template <typename T> class NetObjOrderedListServer : public NetObjOrderedList<T> {
public:
NetObjOrderedListServer() {}
virtual bool contains(const NetObjPtr<T>& p) const override {
return idToDataMap.contains(p.get_net_id());
}
virtual uint32_t size() const override {
return data.size();
}
@ -159,8 +163,11 @@ namespace NetworkingObjects {
uint32_t constructedSize;
a(constructedSize);
data.clear();
for(uint32_t i = 0; i < constructedSize; i++)
idToDataMap.clear();
for(uint32_t i = 0; i < constructedSize; i++) {
data.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(l.get_obj_man()->template read_create_message<T>(a, c), static_cast<uint32_t>(data.size()), false));
idToDataMap.emplace(data.back()->obj.get_net_id(), data.back());
}
// Dont send the object data to all clients in the constructor, as the function that called read_create_message is also the one that will decide where to send the data of the constructed object
// Example: the INSERT_SINGLE command in read_update, if it was inserting another NetObjOrderedList, would first construct the list using read_create_message, then it will call insert() to send it to clients
}
@ -190,6 +197,9 @@ namespace NetworkingObjects {
template <typename T> class NetObjOrderedListClient : public NetObjOrderedList<T> {
public:
NetObjOrderedListClient() {}
virtual bool contains(const NetObjPtr<T>& p) const override {
return clientIdToDataMap.contains(p.get_net_id());
}
virtual uint32_t size() const override {
return clientData.size();
}
@ -273,9 +283,14 @@ namespace NetworkingObjects {
a(constructedSize);
clientData.clear();
serverData.clear();
for(uint32_t i = 0; i < constructedSize; i++)
serverIdToDataMap.clear();
clientIdToDataMap.clear();
for(uint32_t i = 0; i < constructedSize; i++) {
serverData.emplace_back(std::make_shared<NetObjOrderedListObjectInfo<T>>(l.get_obj_man()->template read_create_message<T>(a, nullptr), static_cast<uint32_t>(serverData.size()), false));
serverIdToDataMap.emplace(serverData.back()->obj.get_net_id(), serverData.back());
}
clientData = serverData;
clientIdToDataMap = serverIdToDataMap;
}
virtual void read_update(const NetObjPtr<NetObjOrderedList<T>>& l, cereal::PortableBinaryInputArchive& a, const std::shared_ptr<NetServer::ClientData>&) override {
ObjPtrOrderedListCommand_StoC c;

View file

@ -21,10 +21,12 @@ namespace NetworkingObjects {
std::strong_ordering operator<=>(const NetObjPtr<T>& rhs) const;
void send_client_update(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const;
void send_server_update_to_all_clients(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const;
void send_update_to_all(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const;
void write_create_message(cereal::PortableBinaryOutputArchive& a) const;
private:
friend class NetObjManager;
template <typename S> friend class NetObjPtr;
template <typename S> friend class NetObjWeakPtr;
NetObjPtr(NetObjManager* initObjMan, NetObjID initID, const std::shared_ptr<T>& initPtr);
NetObjManager* objMan;

View file

@ -89,6 +89,13 @@ namespace NetworkingObjects {
}
}
template <typename T> void NetObjPtr<T>::send_update_to_all(const std::string& channel, std::function<void(const NetObjPtr<T>&, cereal::PortableBinaryOutputArchive&)> sendUpdateFunc) const {
if(objMan->is_server())
send_server_update_to_all_clients(channel, sendUpdateFunc);
else
send_client_update(channel, sendUpdateFunc);
}
template <typename T> void NetObjPtr<T>::write_create_message(cereal::PortableBinaryOutputArchive& a) const {
a(id);
objMan->typeList->get_type_index_data<T>(objMan->isServer).writeConstructorFunc(this->cast<void>(), a);

View file

@ -0,0 +1,63 @@
#pragma once
#include "NetObjID.hpp"
#include "NetObjManager.hpp"
#include "NetObjPtr.decl.hpp"
namespace NetworkingObjects {
template <typename T> class NetObjWeakPtr {
public:
NetObjWeakPtr():
objMan(nullptr),
id({0, 0})
{}
NetObjWeakPtr(const NetObjWeakPtr& other):
objMan(other.objMan),
id(other.id)
{}
NetObjWeakPtr(const NetObjPtr<T>& other):
objMan(other.objMan),
id(other.id)
{}
NetObjWeakPtr& operator=(const NetObjWeakPtr& other) {
objMan = other.objMan;
id = other.id;
}
template <typename S> NetObjWeakPtr<S> cast() const {
return NetObjWeakPtr<S>(objMan, id);
}
bool expired() const {
if(!objMan)
return true;
auto it = objMan->objectData.find(id);
return it == objMan->objectData.end();
}
NetObjPtr<T> lock() const {
auto it = objMan->objectData.find(id);
if(it == objMan->objectData.end())
return NetObjPtr<T>();
else
return NetObjPtr<T>(objMan, id, std::static_pointer_cast<T>(it->second.p));
}
NetObjManager* get_obj_man() const {
return objMan;
}
NetObjID get_net_id() const {
return id;
}
bool operator!=(const NetObjWeakPtr<T>& rhs) const {
return objMan != rhs.objMan || id != rhs.id;
}
bool operator==(const NetObjWeakPtr<T>& rhs) const {
return objMan == rhs.objMan && id == rhs.id;
}
private:
NetObjWeakPtr(NetObjManager* initObjMan, NetObjID initID):
objMan(initObjMan),
id(initID)
{}
template <typename S> friend class NetObjPtr;
NetObjManager* objMan;
NetObjID id;
};
}

View file

@ -20,6 +20,7 @@
#include "../World.hpp"
#include "../MainProgram.hpp"
#include "Helpers/FileDownloader.hpp"
#include "Helpers/NetworkingObjects/NetObjWeakPtr.hpp"
#include "Helpers/StringHelpers.hpp"
#include "LassoSelectTool.hpp"
#include <Helpers/Logger.hpp>
@ -283,9 +284,9 @@ void DrawingProgram::tool_options_gui() {
}
}
void DrawingProgram::modify_grid(ServerClientID gridToModifyID) {
void DrawingProgram::modify_grid(const NetworkingObjects::NetObjPtr<WorldGrid>& gridToModify) {
std::unique_ptr<GridModifyTool> newTool(std::make_unique<GridModifyTool>(*this));
newTool->set_grid_id(gridToModifyID);
newTool->set_grid(gridToModify);
switch_to_tool_ptr(std::move(newTool));
}

View file

@ -2,6 +2,7 @@
#include "../DrawData.hpp"
#include "DrawingProgramCache.hpp"
#include "GridModifyTool.hpp"
#include <Helpers/NetworkingObjects/NetObjPtr.hpp>
#include "PanCanvasTool.hpp"
#include "ZoomCanvasTool.hpp"
#include "cereal/archives/portable_binary.hpp"
@ -63,7 +64,7 @@ class DrawingProgram {
void clear_draw_cache();
void modify_grid(ServerClientID gridToModifyID);
void modify_grid(const NetworkingObjects::NetObjPtr<WorldGrid>& gridToModify);
private:
std::optional<std::chrono::steady_clock::time_point> badFrametimeTimePoint;

View file

@ -2,18 +2,21 @@
#include "DrawingProgram.hpp"
#include "../MainProgram.hpp"
#include "../DrawData.hpp"
#include <Helpers/NetworkingObjects/NetObjWeakPtr.hpp>
#include <Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp>
#include <cstddef>
using namespace NetworkingObjects;
GridModifyTool::GridModifyTool(DrawingProgram& initDrawP):
DrawingProgramToolBase(initDrawP)
{
}
void GridModifyTool::set_grid_id(ServerClientID newGridID) {
gridID = newGridID;
auto gridFoundIt = drawP.world.gridMan.grids.find(gridID);
if(gridFoundIt != drawP.world.gridMan.grids.end()) {
WorldGrid& g = gridFoundIt->second;
void GridModifyTool::set_grid(const NetObjPtr<WorldGrid>& newGrid) {
grid = newGrid;
if(drawP.world.gridMan.grids->contains(grid)) {
WorldGrid& g = *grid;
oldGrid = g;
CoordSpaceHelper newCam;
newCam.inverseScale = g.size / WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
@ -31,9 +34,8 @@ void GridModifyTool::gui_toolbox() {
Toolbar& t = drawP.world.main.toolbar;
t.gui.push_id("Grid modify tool");
t.gui.text_label_centered("Edit Grid");
auto gridFoundIt = drawP.world.gridMan.grids.find(gridID);
if(gridFoundIt != drawP.world.gridMan.grids.end()) {
WorldGrid& g = gridFoundIt->second;
if(drawP.world.gridMan.grids->contains(grid)) {
WorldGrid& g = *grid;
t.gui.input_text_field("grid name", "Name", &g.name);
t.gui.checkbox_field("Visible", "Visible", &g.visible);
t.gui.checkbox_field("Display in Front", "Display in front of canvas", &g.displayInFront);
@ -83,9 +85,8 @@ bool GridModifyTool::right_click_popup_gui(Vector2f popupPos) {
}
void GridModifyTool::tool_update() {
auto gridFoundIt = drawP.world.gridMan.grids.find(gridID);
if(gridFoundIt != drawP.world.gridMan.grids.end()) {
WorldGrid& g = gridFoundIt->second;
if(drawP.world.gridMan.grids->contains(grid)) {
WorldGrid& g = *grid;
switch(selectionMode) {
case 0:
if(drawP.controls.leftClick) {
@ -145,9 +146,8 @@ bool GridModifyTool::prevent_undo_or_redo() {
}
void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) {
auto gridFoundIt = drawP.world.gridMan.grids.find(gridID);
if(gridFoundIt != drawP.world.gridMan.grids.end()) {
WorldGrid& g = gridFoundIt->second;
if(drawP.world.gridMan.grids->contains(grid)) {
WorldGrid& g = *grid;
if(g.bounds.has_value()) {
const auto& b = g.bounds.value();
Vector2f bMin = drawP.world.drawData.cam.c.to_space(b.min);
@ -178,5 +178,5 @@ void GridModifyTool::draw(SkCanvas* canvas, const DrawData& drawData) {
}
void GridModifyTool::switch_tool(DrawingProgramToolType newTool) {
drawP.world.gridMan.send_grid_info(oldGrid, gridID);
NetworkingObjects::generic_serialized_class_send_update_to_all<WorldGrid>(grid);
}

View file

@ -1,13 +1,14 @@
#pragma once
#include "DrawingProgramToolBase.hpp"
#include "../WorldGrid.hpp"
#include "Helpers/NetworkingObjects/NetObjPtr.hpp"
class DrawingProgram;
class GridModifyTool : public DrawingProgramToolBase {
public:
GridModifyTool(DrawingProgram& initDrawP);
void set_grid_id(ServerClientID newGridID);
void set_grid(const NetworkingObjects::NetObjPtr<WorldGrid>& newGrid);
virtual DrawingProgramToolType get_type() override;
virtual void gui_toolbox() override;
virtual bool right_click_popup_gui(Vector2f popupPos) override;
@ -17,6 +18,6 @@ class GridModifyTool : public DrawingProgramToolBase {
virtual void switch_tool(DrawingProgramToolType newTool) override;
private:
WorldGrid oldGrid;
ServerClientID gridID;
NetworkingObjects::NetObjPtr<WorldGrid> grid;
unsigned selectionMode = 0;
};

View file

@ -1,4 +1,5 @@
#include "GridManager.hpp"
#include "Helpers/Networking/NetLibrary.hpp"
#include "Server/CommandList.hpp"
#include "SharedTypes.hpp"
#include "World.hpp"
@ -6,166 +7,87 @@
#include <algorithm>
GridManager::GridManager(World& w):
world(w) {}
void GridManager::init_client_callbacks() {
world.con.client_add_recv_callback(CLIENT_SET_GRID, [&](cereal::PortableBinaryInputArchive& message) {
ServerClientID gID;
message(gID);
auto& g = grids[gID];
message(g);
changed = true;
});
world.con.client_add_recv_callback(CLIENT_REMOVE_GRID, [&](cereal::PortableBinaryInputArchive& message) {
ServerClientID gID;
message(gID);
grids.erase(gID);
changed = true;
});
world(w) {
if(w.netObjMan.is_server())
grids = w.netObjMan.make_obj<NetworkingObjects::NetObjOrderedList<WorldGrid>>();
}
ServerClientID GridManager::add_default_grid(const std::string& newName) {
ServerClientID newID = world.get_new_id();
WorldGrid g;
g.name = newName;
g.color = color_mul_alpha(convert_vec4<Vector4f>(world.canvasTheme.toolFrontColor), 0.4f);
g.size = world.drawData.cam.c.inverseScale * WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
g.offset = world.drawData.cam.c.pos + world.drawData.cam.c.dir_from_space(world.main.window.size.cast<float>() * 0.5f);
grids[newID] = g;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, newID, g);
void GridManager::add_default_grid(const std::string& newName) {
if(grids) {
WorldGrid g;
g.name = newName;
g.color = color_mul_alpha(convert_vec4<Vector4f>(world.canvasTheme.toolFrontColor), 0.4f);
g.size = world.drawData.cam.c.inverseScale * WorldScalar(WorldGrid::GRID_UNIT_PIXEL_SIZE);
g.offset = world.drawData.cam.c.pos + world.drawData.cam.c.dir_from_space(world.main.window.size.cast<float>() * 0.5f);
NetworkingObjects::NetObjPtr<WorldGrid> gridPtr = grids->emplace_back_direct(grids, g);
changed = true;
world.undo.push({[&world = world, &changed = changed, &grids = grids, newID]() {
grids.erase(newID);
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, newID);
changed = true;
return true;
},
[&world = world, &changed = changed, &grids = grids, g, newID]() {
grids[newID] = g;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, newID, g);
changed = true;
return true;
}});
return newID;
}
void GridManager::send_grid_info(WorldGrid oldGrid, ServerClientID gridID) {
auto gridFoundIt = grids.find(gridID);
if(gridFoundIt != grids.end()) {
WorldGrid& g = gridFoundIt->second;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, g);
world.undo.push({[&world = world, &changed = changed, &grids = grids, gridID, oldGrid]() {
auto gridFoundIt = grids.find(gridID);
if(gridFoundIt == grids.end())
return false;
gridFoundIt->second = oldGrid;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, oldGrid);
changed = true;
uint32_t pos = grids->size() - 1;
world.undo.push({[&grids = grids, gridPtr](){
grids->erase(grids, gridPtr);
return true;
},
[&world = world, &changed = changed, &grids = grids, gridID, g]() {
auto gridFoundIt = grids.find(gridID);
if(gridFoundIt == grids.end())
return false;
gridFoundIt->second = g;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, gridID, g);
changed = true;
[&grids = grids, gridPtr, pos]() {
grids->insert_and_send_create(grids, pos, gridPtr);
return true;
}});
changed = true;
}
}
void GridManager::remove_grid(ServerClientID idToRemove) {
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, idToRemove);
changed = true;
auto it = grids.find(idToRemove);
if(it == grids.end())
return;
WorldGrid g = it->second;
grids.erase(it);
world.undo.push({[&world = world, &changed = changed, &grids = grids, idToRemove, g]() {
grids[idToRemove] = g;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_SET_GRID, idToRemove, g);
changed = true;
return true;
},
[&world = world, &changed = changed, &grids = grids, idToRemove]() {
grids.erase(idToRemove);
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_REMOVE_GRID, idToRemove);
changed = true;
return true;
}});
}
const std::vector<ServerClientID>& GridManager::sorted_grid_ids() {
if(changed) {
sortedGridIDs.clear();
for(auto& [k, v] : grids)
sortedGridIDs.emplace_back(k);
std::sort(sortedGridIDs.begin(), sortedGridIDs.end(), [&](ServerClientID a, ServerClientID b) {
std::string nameA = grids[a].get_display_name();
std::string nameB = grids[b].get_display_name();
bool namesEqual = nameA == nameB;
return (!namesEqual && std::lexicographical_compare(nameA.begin(), nameA.end(), nameB.begin(), nameB.end())) || (namesEqual && a < b);
});
changed = false;
void GridManager::remove_grid(uint32_t indexToRemove) {
if(grids) {
NetworkingObjects::NetObjPtr<WorldGrid> gridPtr = grids->erase(grids, indexToRemove);
world.undo.push({[&grids = grids, gridPtr, indexToRemove]() {
grids->insert_and_send_create(grids, indexToRemove, gridPtr);
return true;
},
[&grids = grids, gridPtr](){
grids->erase(grids, gridPtr);
return true;
}});
}
return sortedGridIDs;
}
ClientPortionID GridManager::get_max_id(ServerPortionID serverID) const {
ClientPortionID maxClientID = 0;
for(auto& p : grids) {
if(p.first.first == serverID)
maxClientID = std::max(maxClientID, p.first.second);
}
return maxClientID;
}
void GridManager::draw_back(SkCanvas* canvas, const DrawData& drawData) {
auto& sortedGridIDS = sorted_grid_ids();
for(ServerClientID id : sortedGridIDS) {
if(!grids[id].displayInFront)
grids[id].draw(*this, canvas, drawData);
if(grids) {
for(uint32_t i = 0; i < grids->size(); i++) {
if(!grids->at(i)->displayInFront)
grids->at(i)->draw(*this, canvas, drawData);
}
}
}
void GridManager::draw_front(SkCanvas* canvas, const DrawData& drawData) {
auto& sortedGridIDS = sorted_grid_ids();
for(ServerClientID id : sortedGridIDS) {
if(grids[id].displayInFront)
grids[id].draw(*this, canvas, drawData);
if(grids) {
for(uint32_t i = 0; i < grids->size(); i++) {
if(grids->at(i)->displayInFront)
grids->at(i)->draw(*this, canvas, drawData);
}
}
}
void GridManager::draw_coordinates(SkCanvas* canvas, const DrawData& drawData) {
auto& sortedGridIDS = sorted_grid_ids();
Vector2f axisOffset{0.0f, 0.0f};
for(ServerClientID id : sortedGridIDS) {
auto& g = grids[id];
if(g.coordinatesWillBeDrawn && g.coordinatesAxisOnBounds) {
grids[id].draw_coordinates(canvas, drawData, axisOffset);
g.coordinatesWillBeDrawn = false;
if(grids) {
Vector2f axisOffset{0.0f, 0.0f};
for(uint32_t i = 0; i < grids->size(); i++) {
auto& g = grids->at(i);
if(g->coordinatesWillBeDrawn && g->coordinatesAxisOnBounds) {
g->draw_coordinates(canvas, drawData, axisOffset);
g->coordinatesWillBeDrawn = false;
}
}
for(uint32_t i = 0; i < grids->size(); i++) {
auto& g = grids->at(i);
if(g->coordinatesWillBeDrawn && !g->coordinatesAxisOnBounds)
g->draw_coordinates(canvas, drawData, axisOffset);
g->coordinatesWillBeDrawn = false;
}
}
for(ServerClientID id : sortedGridIDS) {
auto& g = grids[id];
if(g.coordinatesWillBeDrawn && !g.coordinatesAxisOnBounds)
grids[id].draw_coordinates(canvas, drawData, axisOffset);
g.coordinatesWillBeDrawn = false;
}
}
void GridManager::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& [id, g] : grids) {
g.scale_up(scaleUpAmount);
if(grids) {
for(uint32_t i = 0; i < grids->size(); i++) {
grids->at(i)->scale_up(scaleUpAmount);
}
}
}

View file

@ -1,38 +1,37 @@
#pragma once
#include "Helpers/NetworkingObjects/NetObjPtr.decl.hpp"
#include "WorldGrid.hpp"
#include <Helpers/NetworkingObjects/NetObjOrderedList.hpp>
class World;
class GridManager {
public:
GridManager(World& w);
void init_client_callbacks();
ServerClientID add_default_grid(const std::string& newName);
void add_default_grid(const std::string& newName);
template <typename Archive> void save(Archive& a) const {
a(grids);
a(grids->size());
for(uint32_t i = 0; i < grids->size(); i++)
a(*grids->at(i));
}
template <typename Archive> void load(Archive& a) {
a(grids);
changed = true;
uint32_t newSize = grids->size();
for(uint32_t i = 0; i < newSize; i++) {
WorldGrid b;
a(b);
grids->emplace_back_direct(grids, b);
}
}
void send_grid_info(WorldGrid oldGrid, ServerClientID gridID);
void remove_grid(ServerClientID idToRemove);
void remove_grid(uint32_t indexToRemove);
void draw_back(SkCanvas* canvas, const DrawData& drawData);
void draw_front(SkCanvas* canvas, const DrawData& drawData);
void draw_coordinates(SkCanvas* canvas, const DrawData& drawData);
void scale_up(const WorldScalar& scaleUpAmount);
ClientPortionID get_max_id(ServerPortionID serverID) const;
const std::vector<ServerClientID>& sorted_grid_ids();
std::unordered_map<ServerClientID, WorldGrid> grids;
NetworkingObjects::NetObjPtr<NetworkingObjects::NetObjOrderedList<WorldGrid>> grids;
World& world;
private:
bool changed = true;
std::vector<ServerClientID> sortedGridIDs;
};

View file

@ -50,6 +50,8 @@ MainProgram::MainProgram():
NetworkingObjects::register_ordered_list_class<std::string>(*netObjectTypeList);
NetworkingObjects::register_generic_serialized_class<Bookmark>(*netObjectTypeList);
NetworkingObjects::register_ordered_list_class<Bookmark>(*netObjectTypeList);
NetworkingObjects::register_generic_serialized_class<WorldGrid>(*netObjectTypeList);
NetworkingObjects::register_ordered_list_class<WorldGrid>(*netObjectTypeList);
displayName = Random::get().alphanumeric_str(10);

View file

@ -19,8 +19,6 @@ enum ServerCommands : MessageCommandType {
SERVER_NEW_RESOURCE_DATA,
SERVER_CHAT_MESSAGE,
SERVER_CANVAS_COLOR,
SERVER_SET_GRID,
SERVER_REMOVE_GRID,
SERVER_CANVAS_SCALE
};
@ -43,8 +41,6 @@ enum ClientCommands : MessageCommandType {
CLIENT_NEW_RESOURCE_DATA,
CLIENT_CHAT_MESSAGE,
CLIENT_CANVAS_COLOR,
CLIENT_SET_GRID,
CLIENT_REMOVE_GRID,
CLIENT_CANVAS_SCALE
};

View file

@ -31,7 +31,6 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
data.idToComponentMap.emplace(data.components.back()->id, data.components.back());
}
data.canvasScale = world.canvasScale;
data.grids = world.gridMan.grids;
data.resources = world.rMan.resource_list();
data.canvasBackColor = convert_vec3<Vector3f>(world.canvasTheme.backColor);
@ -75,6 +74,7 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
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);
}
netServer->send_string_stream_to_client(client, RELIABLE_COMMAND_CHANNEL, ss);
for(auto& [id, rData] : data.resources) {
@ -229,24 +229,6 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
message(chatMessage);
netServer->send_items_to_all_clients_except(client, RELIABLE_COMMAND_CHANNEL, CLIENT_CHAT_MESSAGE, client->customID, chatMessage);
});
netServer->add_recv_callback(SERVER_SET_GRID, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
ServerClientID gID;
message(gID);
WorldGrid& g = data.grids[gID];
message(g);
auto& c = clients[client->customID];
if(c.canvasScale < data.canvasScale)
g.scale_up(FixedPoint::pow_int(CANVAS_SCALE_UP_STEP, data.canvasScale - c.canvasScale));
netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_SET_GRID, gID, g);
});
netServer->add_recv_callback(SERVER_REMOVE_GRID, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
ServerClientID gID;
message(gID);
data.grids.erase(gID);
netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_REMOVE_GRID, gID);
});
netServer->add_recv_callback(SERVER_CANVAS_COLOR, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
message(data.canvasBackColor);
netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_CANVAS_COLOR, data.canvasBackColor);

View file

@ -6,7 +6,6 @@ void ServerData::save(cereal::PortableBinaryOutputArchive& a) const {
a((uint64_t)components.size());
for(uint64_t i = 0; i < components.size(); i++)
a(components[i]->get_type(), components[i]->id, components[i]->coords, *components[i]);
a(grids);
}
void ServerData::load(cereal::PortableBinaryInputArchive& a) {
@ -21,12 +20,9 @@ void ServerData::load(cereal::PortableBinaryInputArchive& a) {
components.emplace_back(newComp);
idToComponentMap.emplace(newComp->id, newComp);
}
a(grids);
}
void ServerData::scale_up(const WorldScalar& scaleUpAmount) {
for(auto& [n, g] : grids)
g.scale_up(scaleUpAmount);
for(auto& c : components)
c->scale_up(scaleUpAmount);
}

View file

@ -11,7 +11,6 @@ class ServerData {
std::vector<std::shared_ptr<DrawComponent>> components;
std::unordered_map<ServerClientID, std::shared_ptr<DrawComponent>> idToComponentMap;
std::unordered_map<ServerClientID, ResourceData> resources;
std::unordered_map<ServerClientID, WorldGrid> grids;
uint64_t canvasScale = 0;
Vector3f canvasBackColor;

View file

@ -5,6 +5,7 @@
#include "Helpers/ConvertVec.hpp"
#include "Helpers/FileDownloader.hpp"
#include "Helpers/Networking/NetLibrary.hpp"
#include "Helpers/NetworkingObjects/NetObjGenericSerializedClass.hpp"
#include "MainProgram.hpp"
#include "GUIStuff/Elements/Element.hpp"
#include "GUIStuff/GUIManager.hpp"
@ -708,13 +709,12 @@ void Toolbar::grid_menu(bool justOpened) {
gui.obstructing_window();
gui.text_label_centered("Grids");
float entryHeight = 25.0f;
if(main.world->gridMan.sorted_grid_ids().empty())
if(main.world->gridMan.grids->empty())
gui.text_label_centered("No grids yet...");
ServerClientID toDelete{0, 0};
gui.scroll_bar_many_entries_area("grid menu entries", entryHeight, main.world->gridMan.sorted_grid_ids().size(), true, [&](size_t i, bool isListHovered) {
ServerClientID gridID = main.world->gridMan.sorted_grid_ids()[i];
WorldGrid& grid = main.world->gridMan.grids[gridID];
bool selectedEntry = gridID == gridMenu.gridSelected;
uint32_t toDelete = std::numeric_limits<uint32_t>::max();
gui.scroll_bar_many_entries_area("grid menu entries", entryHeight, main.world->gridMan.grids->size(), true, [&](size_t i, bool isListHovered) {
auto& grid = main.world->gridMan.grids->at(i);
bool selectedEntry = gridMenu.selectedGrid == i;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(entryHeight)},
@ -724,7 +724,7 @@ void Toolbar::grid_menu(bool justOpened) {
},
.backgroundColor = selectedEntry ? convert_vec4<Clay_Color>(io->theme->backColor1) : convert_vec4<Clay_Color>(io->theme->backColor2)
}) {
gui.text_label(grid.get_display_name());
gui.text_label(grid->get_display_name());
bool miniButtonClicked = false;
CLAY_AUTO_ID({
.layout = {
@ -734,32 +734,31 @@ void Toolbar::grid_menu(bool justOpened) {
.layoutDirection = CLAY_LEFT_TO_RIGHT
}
}) {
if(gui.svg_icon_button_transparent("visibility eye", grid.visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, entryHeight, false)) {
if(gui.svg_icon_button_transparent("visibility eye", grid->visible ? "data/icons/eyeopen.svg" : "data/icons/eyeclose.svg", false, entryHeight, false)) {
miniButtonClicked = true;
WorldGrid oldGrid = grid;
grid.visible = !grid.visible;
main.world->gridMan.send_grid_info(oldGrid, gridID);
grid->visible = !grid->visible;
NetworkingObjects::generic_serialized_class_send_update_to_all<WorldGrid>(grid);
}
if(gui.svg_icon_button_transparent("edit pencil", "data/icons/pencil.svg", false, entryHeight, false)) {
miniButtonClicked = true;
main.world->drawProg.modify_grid(gridID);
main.world->drawProg.modify_grid(grid);
stop_displaying_grid_menu();
}
if(gui.svg_icon_button_transparent("delete trash", "data/icons/trash.svg", false, entryHeight, false)) {
miniButtonClicked = true;
toDelete = gridID;
toDelete = i;
}
}
if(Clay_Hovered() && io->mouse.leftClick && isListHovered && !miniButtonClicked) {
gridMenu.gridSelected = gridID;
gridMenu.selectedGrid = i;
if(io->mouse.leftClick >= 2) {
main.world->drawProg.modify_grid(gridID);
main.world->drawProg.modify_grid(grid);
stop_displaying_grid_menu();
}
}
}
});
if(toDelete != ServerClientID{0, 0})
if(toDelete != std::numeric_limits<uint32_t>::max())
main.world->gridMan.remove_grid(toDelete);
gui.left_to_right_line_layout([&]() {
bool addByEnter = false;
@ -767,7 +766,8 @@ void Toolbar::grid_menu(bool justOpened) {
addByEnter = s.selected && io->key.enter;
});
if(gui.svg_icon_button("grid add button", "data/icons/plus.svg", false, GUIStuff::GUIManager::SMALL_BUTTON_SIZE) || (addByEnter && !gridMenu.newName.empty())) {
main.world->drawProg.modify_grid(main.world->gridMan.add_default_grid(gridMenu.newName));
main.world->gridMan.add_default_grid(gridMenu.newName);
main.world->drawProg.modify_grid(main.world->gridMan.grids->at(main.world->gridMan.grids->size() - 1));
stop_displaying_grid_menu();
}
});
@ -782,7 +782,7 @@ void Toolbar::grid_menu(bool justOpened) {
void Toolbar::stop_displaying_grid_menu() {
gridMenu.newName.clear();
gridMenu.popupOpen = false;
gridMenu.gridSelected = ServerClientID{0, 0};
gridMenu.selectedGrid = std::numeric_limits<uint32_t>::max();
}
void Toolbar::bookmark_menu(bool justOpened) {

View file

@ -198,7 +198,7 @@ class Toolbar {
struct GridMenu {
bool popupOpen = false;
std::string newName;
ServerClientID gridSelected = {0, 0};
uint32_t selectedGrid = std::numeric_limits<uint32_t>::max();
} gridMenu;
bool useNativeFilePicker = true;

View file

@ -66,7 +66,6 @@ World::World(MainProgram& initMain, OpenWorldInfo& worldInfo):
drawProg.init_client_callbacks();
rMan.init_client_callbacks();
gridMan.init_client_callbacks();
init_client_callbacks();
con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_INITIAL_DATA, displayName, false);
}
@ -87,8 +86,8 @@ void World::init_client_callbacks() {
set_canvas_background_color(newBackColor, false);
message(canvasScale);
drawProg.initialize_draw_data(message);
message(gridMan);
bMan.bookmarks = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<Bookmark>>(message, nullptr);
gridMan.grids = netObjMan.read_create_message<NetworkingObjects::NetObjOrderedList<WorldGrid>>(message, nullptr);
}
nextClientID = get_max_id(ownID);
clientStillConnecting = false;
@ -284,7 +283,6 @@ void World::start_hosting(const std::string& initNetSource, const std::string& s
con.init_local_p2p(*this, serverLocalID);
drawProg.init_client_callbacks();
rMan.init_client_callbacks();
gridMan.init_client_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());
conType = CONNECTIONTYPE_SERVER;
@ -374,7 +372,7 @@ void World::load_from_file(const std::filesystem::path& filePathToLoadFrom, std:
}
ClientPortionID World::get_max_id(ServerPortionID serverID) {
return std::max(std::max(rMan.get_max_id(serverID), drawProg.get_max_id(serverID)), gridMan.get_max_id(serverID));
return std::max(rMan.get_max_id(serverID), drawProg.get_max_id(serverID));
}
void World::save_file(cereal::PortableBinaryOutputArchive& a) const {