IDs are no longer generated on server, fixes error caused by spamming undo and redo

This commit is contained in:
Yousef Khadadeh 2025-08-27 11:38:36 +03:00
parent a9af3a9b17
commit 57392cdfdd
12 changed files with 92 additions and 108 deletions

View file

@ -50,7 +50,6 @@ set(sources "src/main.cpp"
"src/ResourceDisplay/ImageResourceDisplay.cpp"
"src/ResourceDisplay/FileResourceDisplay.cpp"
"src/Server/MainServer.cpp"
"src/Server/ClientData.cpp"
"src/CollabTextBox/CollabTextBox.cpp"
"src/CollabTextBox/CollabTextBoxShaper.cpp"
"src/DrawingProgram/DrawingProgramCache.cpp"

View file

@ -10,7 +10,6 @@ template <typename T, typename IDType> class CollabList {
struct ObjectInfo {
bool syncIgnore;
IDType id;
T obj;
uint64_t pos;
};
@ -45,7 +44,7 @@ template <typename T, typename IDType> class CollabList {
if(clientEraseCallback)
clientEraseCallback(clientSideList[i]);
clientSideList[i]->obj->collabListInfo.reset();
idToObjectMap.erase(clientSideList[i]->id);
idToObjectMap.erase(clientSideList[i]->obj->id);
clientSideList.erase(clientSideList.begin() + i);
i--;
if(updateCallback)
@ -57,16 +56,17 @@ template <typename T, typename IDType> class CollabList {
complete_client_pos_refresh(false);
}
ObjectInfoPtr client_insert(uint64_t pos, const T& item) {
ObjectInfoPtr client_insert(uint64_t pos, const T& item, bool createNewIDs = true) {
auto newObj(std::make_shared<ObjectInfo>());
newObj->syncIgnore = true;
newObj->id = getNewIDFunc();
newObj->obj = item;
if(createNewIDs)
newObj->obj->id = getNewIDFunc();
newObj->pos = std::min<uint64_t>(static_cast<uint64_t>(clientSideList.size()), pos);
item->collabListInfo = newObj;
clientSideList.insert(clientSideList.begin() + newObj->pos, newObj);
idToObjectMap.emplace(newObj->id, newObj);
idToObjectMap.emplace(newObj->obj->id, newObj);
client_pos_refresh_after_insert(newObj->pos);
@ -78,15 +78,16 @@ template <typename T, typename IDType> class CollabList {
return newObj;
}
std::vector<ObjectInfoPtr> client_insert_ordered_vector_items(uint64_t pos, const std::vector<T>& items) {
std::vector<ObjectInfoPtr> client_insert_ordered_vector_items(uint64_t pos, const std::vector<T>& items, bool createNewIDs = true) {
std::vector<ObjectInfoPtr> itemsToPushIn;
for(auto& item : items) {
auto& newObj = itemsToPushIn.emplace_back(std::make_shared<ObjectInfo>());
newObj->syncIgnore = true;
newObj->id = getNewIDFunc();
newObj->obj = item;
if(createNewIDs)
newObj->obj->id = getNewIDFunc();
item->collabListInfo = newObj;
idToObjectMap.emplace(newObj->id, newObj);
idToObjectMap.emplace(newObj->obj->id, newObj);
}
clientSideList.insert(clientSideList.begin() + pos, itemsToPushIn.begin(), itemsToPushIn.end());
@ -101,14 +102,15 @@ template <typename T, typename IDType> class CollabList {
return itemsToPushIn;
}
IDType client_insert(const ObjectInfoPtr& objInfoToInsert) {
IDType client_insert(const ObjectInfoPtr& objInfoToInsert, bool createNewIDs = true) {
objInfoToInsert->syncIgnore = true;
objInfoToInsert->id = getNewIDFunc();
if(createNewIDs)
objInfoToInsert->obj->id = getNewIDFunc();
objInfoToInsert->pos = std::min<uint64_t>(static_cast<uint64_t>(clientSideList.size()), objInfoToInsert->pos);
objInfoToInsert->obj->collabListInfo = objInfoToInsert;
clientSideList.insert(clientSideList.begin() + objInfoToInsert->pos, objInfoToInsert);
idToObjectMap.emplace(objInfoToInsert->id, objInfoToInsert);
idToObjectMap.emplace(objInfoToInsert->obj->id, objInfoToInsert);
client_pos_refresh_after_insert(objInfoToInsert->pos);
@ -117,7 +119,7 @@ template <typename T, typename IDType> class CollabList {
if(updateCallback)
updateCallback();
return objInfoToInsert->id;
return objInfoToInsert->obj->id;
}
void client_erase(const ObjectInfoPtr& objToErase) {
@ -126,7 +128,7 @@ template <typename T, typename IDType> class CollabList {
if(obj->obj == objToErase->obj) {
if(clientEraseCallback)
clientEraseCallback(obj);
idToObjectMap.erase(objToErase->id);
idToObjectMap.erase(objToErase->obj->id);
obj->syncIgnore = true;
obj->obj->collabListInfo.reset();
erasedSomething = true;
@ -147,7 +149,7 @@ template <typename T, typename IDType> class CollabList {
if(objSet.contains(obj)) {
if(clientEraseCallback)
clientEraseCallback(obj);
idToObjectMap.erase(obj->id);
idToObjectMap.erase(obj->obj->id);
obj->syncIgnore = true;
obj->obj->collabListInfo.reset();
erasedSomething = true;
@ -165,22 +167,24 @@ template <typename T, typename IDType> class CollabList {
}
// NOTE: Dont use this function unless you're certain every object in the vector isn't already in the client list
void client_insert_ordered_vector(const std::vector<ObjectInfoPtr>& objOrderedVector) {
void client_insert_ordered_vector(const std::vector<ObjectInfoPtr>& objOrderedVector, bool createNewIDs = true) {
if(objOrderedVector.empty())
return;
uint64_t startPoint = 0;
objOrderedVector.front()->syncIgnore = true;
objOrderedVector.front()->id = getNewIDFunc();
if(createNewIDs)
objOrderedVector.front()->obj->id = getNewIDFunc();
objOrderedVector.front()->obj->collabListInfo = objOrderedVector.front();
idToObjectMap.emplace(objOrderedVector.front()->id, objOrderedVector.front());
idToObjectMap.emplace(objOrderedVector.front()->obj->id, objOrderedVector.front());
for(uint64_t i = 1; i < static_cast<uint64_t>(objOrderedVector.size()); i++) {
auto& obj = objOrderedVector[i];
obj->syncIgnore = true;
obj->id = getNewIDFunc();
if(createNewIDs)
obj->obj->id = getNewIDFunc();
obj->obj->collabListInfo = obj;
idToObjectMap.emplace(obj->id, obj);
idToObjectMap.emplace(obj->obj->id, obj);
if(obj->pos - objOrderedVector[startPoint]->pos != (i - startPoint)) {
uint64_t insertPosition = std::min<uint64_t>(clientSideList.size(), objOrderedVector[startPoint]->pos);
clientSideList.insert(clientSideList.begin() + insertPosition, objOrderedVector.begin() + startPoint, objOrderedVector.begin() + i);
@ -203,7 +207,7 @@ template <typename T, typename IDType> class CollabList {
std::vector<bool> didntExistPreviously(objOrderedVector.size(), true);
uint64_t startPoint = 0;
auto foundInClient1 = idToObjectMap.emplace(objOrderedVector.front()->id, objOrderedVector.front());
auto foundInClient1 = idToObjectMap.emplace(objOrderedVector.front()->obj->id, objOrderedVector.front());
if(!foundInClient1.second) { // object already existed
objOrderedVector.front() = foundInClient1.first->second;
didntExistPreviously[0] = false;
@ -214,7 +218,7 @@ template <typename T, typename IDType> class CollabList {
for(uint64_t i = 1; i < static_cast<uint64_t>(objOrderedVector.size()); i++) {
auto& obj = objOrderedVector[i];
auto foundInClient = idToObjectMap.emplace(obj->id, obj);
auto foundInClient = idToObjectMap.emplace(obj->obj->id, obj);
if(!foundInClient.second) { // object already existed
obj = foundInClient.first->second;
didntExistPreviously[i] = false;
@ -241,8 +245,8 @@ template <typename T, typename IDType> class CollabList {
return didntExistPreviously;
}
bool server_insert(uint64_t pos, IDType id, const T& item) {
auto foundInClient = idToObjectMap.find(id);
bool server_insert(uint64_t pos, const T& item) {
auto foundInClient = idToObjectMap.find(item->id);
if(foundInClient != idToObjectMap.end()) {
ObjectInfoPtr& o = foundInClient->second;
serverSideList.insert(serverSideList.begin() + pos, o);
@ -252,10 +256,9 @@ template <typename T, typename IDType> class CollabList {
}
auto newObj(std::make_shared<ObjectInfo>());
newObj->syncIgnore = false;
newObj->id = id;
newObj->obj = item;
newObj->pos = std::min<uint64_t>(pos, clientSideList.size());
idToObjectMap.emplace(newObj->id, newObj);
idToObjectMap.emplace(newObj->obj->id, newObj);
item->collabListInfo = newObj;
serverSideList.insert(serverSideList.begin() + pos, newObj);
@ -272,16 +275,16 @@ template <typename T, typename IDType> class CollabList {
}
void server_erase(IDType id) {
std::erase_if(serverSideList, [&](const auto& obj) {
if(obj->id == id) {
if(obj->obj->id == id) {
obj->syncIgnore = false;
return true;
}
return false;
});
std::erase_if(clientSideList, [&](const auto& obj) {
if(obj->id == id) {
if(obj->obj->id == id) {
obj->syncIgnore = false;
idToObjectMap.erase(obj->id);
idToObjectMap.erase(obj->obj->id);
if(clientEraseCallback)
clientEraseCallback(obj);
obj->obj->collabListInfo.reset();
@ -294,18 +297,18 @@ template <typename T, typename IDType> class CollabList {
void server_erase_set(const std::unordered_set<ServerClientID>& idsToErase) {
std::erase_if(serverSideList, [&](const auto& obj) {
if(idsToErase.contains(obj->id)) {
if(idsToErase.contains(obj->obj->id)) {
obj->syncIgnore = false;
return true;
}
return false;
});
std::erase_if(clientSideList, [&](const auto& obj) {
if(idsToErase.contains(obj->id)) {
if(idsToErase.contains(obj->obj->id)) {
obj->syncIgnore = false;
if(clientEraseCallback)
clientEraseCallback(obj);
idToObjectMap.erase(obj->id);
idToObjectMap.erase(obj->obj->id);
obj->obj->collabListInfo.reset();
return true;
}
@ -314,13 +317,12 @@ template <typename T, typename IDType> class CollabList {
sync();
}
void init_emplace_back(IDType id, const T& item) {
void init_emplace_back(const T& item) {
auto newObj(std::make_shared<ObjectInfo>());
newObj->syncIgnore = false;
newObj->id = id;
newObj->obj = item;
item->collabListInfo = newObj;
idToObjectMap.emplace(newObj->id, newObj);
idToObjectMap.emplace(newObj->obj->id, newObj);
serverSideList.emplace_back(newObj);
clientSideList.emplace_back(newObj);

View file

@ -81,7 +81,7 @@ void DrawBrushStroke::draw(SkCanvas* canvas, const DrawData& drawData) {
canvas->save();
paint.setColor4f(SkColor4f{d->color.x(), d->color.y(), d->color.z(), d->color.w()});
canvas_do_calculated_transform(canvas);
if(drawSetupData.mipmapLevel == 0)
if(drawSetupData.mipmapLevel == 0 || drawData.dontUseDrawProgCache) // check dontUseDrawProgCache, to make sure that SVG screenshots dont use LOD
canvas->drawPath(*brushPath, paint);
else
canvas->drawPath(*brushPathLOD[drawSetupData.mipmapLevel - 1], paint);

View file

@ -16,14 +16,14 @@
void save(cereal::PortableBinaryOutputArchive& a, const CollabListType::ObjectInfo& o) {
// Client will send ID, but server should ignore ID and generate its own
a(o.pos, o.obj->get_type(), o.id, o.obj->coords, *o.obj);
a(o.pos, o.obj->get_type(), o.obj->id, o.obj->coords, *o.obj);
}
void load(cereal::PortableBinaryInputArchive& a, CollabListType::ObjectInfo& o) {
DrawComponentType t;
a(o.pos, t, o.id);
a(o.pos, t);
o.obj = DrawComponent::allocate_comp_type(t);
a(o.obj->coords, *o.obj);
a(o.obj->id, o.obj->coords, *o.obj);
}
void SendOrderedComponentVectorOp::save(cereal::PortableBinaryOutputArchive& a) const {
@ -60,7 +60,7 @@ void DrawComponent::server_send_place_many(MainServer& server, std::vector<Colla
server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_PLACE_MANY_COMPONENTS, SendOrderedComponentVectorOp{&comps});
}
void DrawComponent::server_send_place(MainServer& server, ServerClientID id, uint64_t placement) {
void DrawComponent::server_send_place(MainServer& server, uint64_t placement) {
server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_PLACE_SINGLE_COMPONENT, placement, get_type(), id, this->coords, *this);
}
@ -72,7 +72,7 @@ void DrawComponent::server_send_erase_set(MainServer& server, const std::unorder
server.netServer->send_items_to_all_clients(RELIABLE_COMMAND_CHANNEL, CLIENT_ERASE_MANY_COMPONENTS, ids);
}
void DrawComponent::server_send_update(MainServer& server, ServerClientID id) {
void DrawComponent::server_send_update(MainServer& server) {
server.netServer->send_items_to_all_clients(UNRELIABLE_COMMAND_CHANNEL, CLIENT_UPDATE_COMPONENT, id, *this);
}
@ -130,12 +130,12 @@ void DrawComponent::client_send_place_many(DrawingProgram& drawP, std::vector<Co
void DrawComponent::client_send_place(DrawingProgram& drawP) {
//if(collabListInfo.lock()) If this fails, then there's a real issue
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_PLACE_SINGLE_COMPONENT, collabListInfo.lock()->pos, get_type(), this->coords, *this);
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_PLACE_SINGLE_COMPONENT, collabListInfo.lock()->pos, get_type(), id, this->coords, *this);
}
void DrawComponent::client_send_update(DrawingProgram& drawP) {
if(collabListInfo.lock())
drawP.world.con.client_send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_UPDATE_COMPONENT, collabListInfo.lock()->id, *this);
drawP.world.con.client_send_items_to_server(UNRELIABLE_COMMAND_CHANNEL, SERVER_UPDATE_COMPONENT, id, *this);
}
void DrawComponent::client_send_transform_many(DrawingProgram& drawP, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms) {
@ -144,7 +144,7 @@ void DrawComponent::client_send_transform_many(DrawingProgram& drawP, const std:
void DrawComponent::client_send_erase(DrawingProgram& drawP) {
if(collabListInfo.lock())
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_ERASE_SINGLE_COMPONENT, collabListInfo.lock()->id);
drawP.world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_ERASE_SINGLE_COMPONENT, id);
}
void DrawComponent::client_send_erase_set(DrawingProgram& drawP, const std::unordered_set<ServerClientID>& ids) {

View file

@ -63,15 +63,16 @@ class DrawComponent {
void canvas_do_calculated_transform(SkCanvas* canvas);
void calculate_draw_transform(const DrawData& drawData);
void server_send_place(MainServer& server, ServerClientID id, uint64_t placement);
void server_send_place(MainServer& server, uint64_t placement);
static void server_send_place_many(MainServer& server, std::vector<CollabListType::ObjectInfoPtr>& comps);
static void server_send_erase(MainServer& server, ServerClientID id);
static void server_send_erase_set(MainServer& server, const std::unordered_set<ServerClientID>& ids);
void server_send_update(MainServer& server, ServerClientID id);
void server_send_update(MainServer& server);
static void server_send_transform_many(MainServer& server, const std::vector<std::pair<ServerClientID, CoordSpaceHelper>>& transforms);
std::weak_ptr<CollabListType::ObjectInfo> collabListInfo;
std::weak_ptr<DrawingProgramCacheBVHNode> parentBvhNode;
ServerClientID id;
#ifndef IS_SERVER
std::chrono::time_point<std::chrono::steady_clock> lastUpdateTime;

View file

@ -114,10 +114,9 @@ void DrawingProgram::init_client_callbacks() {
uint64_t insertPosition;
DrawComponentType type;
message(insertPosition, type);
ServerClientID newObjectID;
auto newObj = DrawComponent::allocate_comp_type(type);
message(newObjectID, newObj->coords, *newObj);
bool didntExistPreviously = components.server_insert(insertPosition, newObjectID, newObj);
message(newObj->id, newObj->coords, *newObj);
bool didntExistPreviously = components.server_insert(insertPosition, newObj);
if(didntExistPreviously)
newObj->commit_update(*this);
});
@ -439,11 +438,10 @@ void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a)
a(compCount);
for(uint64_t i = 0; i < compCount; i++) {
DrawComponentType t;
ServerClientID id;
a(t, id);
a(t);
auto newComp = DrawComponent::allocate_comp_type(t);
a(newComp->coords, *newComp);
components.init_emplace_back(id, newComp);
a(newComp->id, newComp->coords, *newComp);
components.init_emplace_back(newComp);
}
parallel_loop_all_components([&](const auto& c){
c->obj->commit_update(*this, false);
@ -454,7 +452,7 @@ void DrawingProgram::initialize_draw_data(cereal::PortableBinaryInputArchive& a)
void DrawingProgram::client_erase_set(std::unordered_set<CollabListType::ObjectInfoPtr> erasedComponents) {
std::unordered_set<ServerClientID> idsToErase;
for(auto& c : erasedComponents)
idsToErase.emplace(c->id);
idsToErase.emplace(c->obj->id);
DrawComponent::client_send_erase_set(*this, idsToErase);
components.client_erase_set(erasedComponents);
add_undo_erase_components(erasedComponents);
@ -470,7 +468,7 @@ void DrawingProgram::add_undo_place_component(const CollabListType::ObjectInfoPt
[&, objToUndo]() {
if(objToUndo->obj->collabListInfo.lock())
return false;
components.client_insert(objToUndo);
components.client_insert(objToUndo, false);
objToUndo->obj->client_send_place(*this);
return true;
}
@ -500,7 +498,7 @@ void DrawingProgram::add_undo_place_components(const std::unordered_set<CollabLi
std::unordered_set<ServerClientID> idsToErase;
for(auto& c : objSetToUndo)
idsToErase.emplace(c->id);
idsToErase.emplace(c->obj->id);
DrawComponent::client_send_erase_set(*this, idsToErase);
components.client_erase_set(objSetToUndo);
@ -517,7 +515,7 @@ void DrawingProgram::add_undo_place_components(const std::unordered_set<CollabLi
if(comp->obj->collabListInfo.lock())
return false;
components.client_insert_ordered_vector(sortedObjects);
components.client_insert_ordered_vector(sortedObjects, false);
DrawComponent::client_send_place_many(*this, sortedObjects);
return true;
@ -537,7 +535,7 @@ void DrawingProgram::add_undo_erase_components(const std::unordered_set<CollabLi
if(comp->obj->collabListInfo.lock())
return false;
components.client_insert_ordered_vector(sortedObjects);
components.client_insert_ordered_vector(sortedObjects, false);
DrawComponent::client_send_place_many(*this, sortedObjects);
return true;
@ -549,7 +547,7 @@ void DrawingProgram::add_undo_erase_components(const std::unordered_set<CollabLi
std::unordered_set<ServerClientID> idsToErase;
for(auto& c : objSetToUndo)
idsToErase.emplace(c->id);
idsToErase.emplace(c->obj->id);
DrawComponent::client_send_erase_set(*this, idsToErase);
components.client_erase_set(objSetToUndo);
@ -563,8 +561,8 @@ ClientPortionID DrawingProgram::get_max_id(ServerPortionID serverID) {
ClientPortionID maxClientID = 0;
auto& cList = components.client_list();
for(auto& comp : cList) {
if(comp->id.first == serverID)
maxClientID = std::max(maxClientID, comp->id.second);
if(comp->obj->id.first == serverID)
maxClientID = std::max(maxClientID, comp->obj->id.second);
}
return maxClientID;
}
@ -583,7 +581,7 @@ void DrawingProgram::write_to_file(cereal::PortableBinaryOutputArchive& a) {
auto& cList = components.client_list();
a((uint64_t)cList.size());
for(size_t i = 0; i < cList.size(); i++) {
a(cList[i]->obj->get_type(), cList[i]->id, cList[i]->obj->coords, *cList[i]->obj);
a(cList[i]->obj->get_type(), cList[i]->obj->id, cList[i]->obj->coords, *cList[i]->obj);
}
}

View file

@ -152,7 +152,7 @@ void DrawingProgramSelection::commit_transform_selection() {
std::vector<std::pair<CollabListType::ObjectInfoPtr, CoordSpaceHelper>> transformsTo;
std::vector<std::pair<ServerClientID, CoordSpaceHelper>> transformsToSend;
for(auto& transformedObj : a) {
transformsToSend.emplace_back(transformedObj->id, transformedObj->obj->coords);
transformsToSend.emplace_back(transformedObj->obj->id, transformedObj->obj->coords);
transformsTo.emplace_back(transformedObj, transformedObj->obj->coords);
}
DrawComponent::client_send_transform_many(drawP, transformsToSend);
@ -162,7 +162,7 @@ void DrawingProgramSelection::commit_transform_selection() {
for(auto& [comp, coords] : transformsFrom) {
auto lockObjInfo = comp->obj->collabListInfo.lock();
if(lockObjInfo)
transformsToSend.emplace_back(lockObjInfo->id, coords);
transformsToSend.emplace_back(lockObjInfo->obj->id, coords);
else
return false;
}
@ -186,7 +186,7 @@ void DrawingProgramSelection::commit_transform_selection() {
for(auto& [comp, coords] : transformsTo) {
auto lockObjInfo = comp->obj->collabListInfo.lock();
if(lockObjInfo)
transformsToSend.emplace_back(lockObjInfo->id, coords);
transformsToSend.emplace_back(lockObjInfo->obj->id, coords);
else
return false;
}

View file

@ -78,7 +78,7 @@ ServerClientID ResourceManager::add_resource(const ResourceData& resource) {
}
ServerClientID newID = world.get_new_id();
resources[newID] = resource;
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_RESOURCE_INIT);
world.con.client_send_items_to_server(RELIABLE_COMMAND_CHANNEL, SERVER_RESOURCE_INIT, newID);
world.con.client_send_items_to_server(RESOURCE_COMMAND_CHANNEL, SERVER_RESOURCE_DATA, resource);
return newID;
}

View file

@ -1,9 +0,0 @@
#include "ClientData.hpp"
#include "MainServer.hpp"
#include "CommandList.hpp"
ServerClientID ClientData::get_next_id() {
id.second++;
return id;
}

View file

@ -24,7 +24,5 @@ class ClientData {
template <typename Archive> void serialize(Archive& a) {
a(camCoords, windowSize, cursorPos, cursorColor, displayName);
}
ServerClientID get_next_id();
};

View file

@ -28,7 +28,7 @@ void ServerData::save(cereal::PortableBinaryOutputArchive& a) const {
a(canvasBackColor);
a((uint64_t)components.size());
for(uint64_t i = 0; i < components.size(); i++)
a(components[i].second->get_type(), components[i].first, components[i].second->coords, *(components[i].second));
a(components[i]->get_type(), components[i]->id, components[i]->coords, *components[i]);
a(bookmarks);
}
@ -38,12 +38,11 @@ void ServerData::load(cereal::PortableBinaryInputArchive& a) {
a(compCount);
for(uint64_t i = 0; i < compCount; i++) {
DrawComponentType t;
ServerClientID id;
a(t, id);
a(t);
auto newComp = DrawComponent::allocate_comp_type(t);
a(newComp->coords, *newComp);
components.emplace_back(id, newComp);
idToComponentMap.emplace(id, newComp);
a(newComp->id, newComp->coords, *newComp);
components.emplace_back(newComp);
idToComponentMap.emplace(newComp->id, newComp);
}
a(bookmarks);
}
@ -55,8 +54,8 @@ ClientPortionID ServerData::get_max_id(ServerPortionID serverID) const {
maxClientID = std::max(maxClientID, p.first.second);
}
for(auto& p : components) {
if(p.first.first == serverID)
maxClientID = std::max(maxClientID, p.first.second);
if(p->id.first == serverID)
maxClientID = std::max(maxClientID, p->id.second);
}
return maxClientID;
}
@ -65,8 +64,9 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
world(initWorld)
{
for(auto& c : world.drawProg.components.client_list()) {
data.components.emplace_back(c->id, c->obj->copy());
data.idToComponentMap.emplace(data.components.back().first, data.components.back().second);
data.components.emplace_back(c->obj->copy());
data.components.back()->id = c->obj->id;
data.idToComponentMap.emplace(data.components.back()->id, data.components.back());
}
data.bookmarks = world.bMan.bookmark_list();
data.resources = world.rMan.resource_list();
@ -114,36 +114,31 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
DrawComponentType type;
message(placement, type);
auto newComp = DrawComponent::allocate_comp_type(type);
message(newComp->coords, *newComp);
ServerClientID id = clients[client->customID].get_next_id();
message(newComp->id, newComp->coords, *newComp);
placement = std::min<uint64_t>(placement, data.components.size());
data.components.insert(data.components.begin() + placement, {id, newComp});
data.idToComponentMap.emplace(id, newComp);
newComp->server_send_place(*this, id, placement);
data.components.insert(data.components.begin() + placement, newComp);
data.idToComponentMap.emplace(newComp->id, newComp);
newComp->server_send_place(*this, placement);
});
netServer->add_recv_callback(SERVER_PLACE_MANY_COMPONENTS, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
auto& cli = clients[client->customID];
std::vector<CollabListType::ObjectInfoPtr> objOrderedVector;
SendOrderedComponentVectorOp a{&objOrderedVector};
message(a);
std::vector<std::pair<ServerClientID, std::shared_ptr<DrawComponent>>> objOrderedComponentPairs;
for(auto& o : objOrderedVector) {
o->id = cli.get_next_id();
objOrderedComponentPairs.emplace_back(o->id, o->obj);
}
std::vector<std::shared_ptr<DrawComponent>> objOrderedComponentPairs;
for(auto& o : objOrderedVector)
objOrderedComponentPairs.emplace_back(o->obj);
uint64_t startPoint = 0;
if(objOrderedVector.empty())
return;
data.idToComponentMap.emplace(objOrderedVector.front()->id, objOrderedVector.front()->obj);
data.idToComponentMap.emplace(objOrderedVector.front()->obj->id, objOrderedVector.front()->obj);
for(uint64_t i = 1; i < static_cast<uint64_t>(objOrderedVector.size()); i++) {
auto& obj = objOrderedVector[i];
data.idToComponentMap.emplace(obj->id, obj->obj);
data.idToComponentMap.emplace(obj->obj->id, obj->obj);
if(obj->pos - objOrderedVector[startPoint]->pos != (i - startPoint)) {
uint64_t insertPosition = std::min<uint64_t>(data.components.size(), objOrderedVector[startPoint]->pos);
data.components.insert(data.components.begin() + insertPosition, objOrderedComponentPairs.begin() + startPoint, objOrderedComponentPairs.begin() + i);
@ -158,10 +153,9 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
for(uint64_t i = 0; i < data.components.size(); i++) {
if(startPoint >= objOrderedVector.size())
break;
auto& [id, c] = data.components[i];
auto& c = data.components[i];
auto& o = objOrderedVector[startPoint];
if(c == o->obj) {
o->id = id;
o->pos = i;
startPoint++;
}
@ -175,7 +169,7 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
DrawComponent::server_send_erase(*this, compToRemove);
data.idToComponentMap.erase(compToRemove);
std::erase_if(data.components, [&](auto& p) {
return p.first == compToRemove;
return p->id == compToRemove;
});
});
netServer->add_recv_callback(SERVER_ERASE_MANY_COMPONENTS, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
@ -185,7 +179,7 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
for(auto& id : idsToRemove)
data.idToComponentMap.erase(id);
std::erase_if(data.components, [&](auto& p) {
return idsToRemove.contains(p.first);
return idsToRemove.contains(p->id);
});
});
netServer->add_recv_callback(SERVER_TRANSFORM_MANY_COMPONENTS, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
@ -205,12 +199,13 @@ MainServer::MainServer(World& initWorld, const std::string& serverLocalID):
if(it != data.idToComponentMap.end()) {
std::shared_ptr<DrawComponent>& comp = it->second;
message(*comp);
comp->server_send_update(*this, idToUpdate);
comp->server_send_update(*this);
}
});
netServer->add_recv_callback(SERVER_RESOURCE_INIT, [&](std::shared_ptr<NetServer::ClientData> client, cereal::PortableBinaryInputArchive& message) {
auto& c = clients[client->customID];
ServerClientID newID = c.get_next_id();
ServerClientID newID;
message(newID);
if(c.pendingResourceData.empty())
c.pendingResourceID.emplace(newID);
else {

View file

@ -8,7 +8,7 @@ class DrawComponent;
class ServerData {
public:
std::vector<std::pair<ServerClientID, std::shared_ptr<DrawComponent>>> components;
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<std::string, Bookmark> bookmarks;