diff --git a/data/models/rofi/pad_board.obj b/data/models/rofi/pad_board.obj
index 297cfee546ae96a89fd6b82bf1b68acf48c9140e..4891eb2981a03f1aae89c12b7cdf33ebd6e06c85 100644
--- a/data/models/rofi/pad_board.obj
+++ b/data/models/rofi/pad_board.obj
@@ -1,46 +1,44 @@
-# Blender v2.90.1 OBJ File: ''
+# Blender 3.6.2
 # www.blender.org
-# mtllib untitled.mtl
-o Cube
-v 1.000000 -1.000000 1.000000
-v 1.000000 1.000000 1.000000
-v 1.000000 -1.000000 -1.000000
-v 1.000000 1.000000 -1.000000
-v -1.000000 -1.000000 1.000000
-v -1.000000 1.000000 1.000000
-v -1.000000 -1.000000 -1.000000
-v -1.000000 1.000000 -1.000000
-vt 0.875000 0.500000
-vt 0.625000 0.750000
-vt 0.625000 0.500000
-vt 0.375000 1.000000
-vt 0.375000 0.750000
+o padboard
+v -0.500000 -0.516747 0.500000
+v -0.500000 0.449759 0.500000
+v -0.500000 -0.516747 -0.500000
+v -0.500000 0.449759 -0.500000
+v 0.500000 -0.516747 0.500000
+v 0.500000 0.449759 0.500000
+v 0.500000 -0.516747 -0.500000
+v 0.500000 0.449759 -0.500000
+vn -1.0000 -0.0000 -0.0000
+vn -0.0000 -0.0000 -1.0000
+vn 1.0000 -0.0000 -0.0000
+vn -0.0000 -0.0000 1.0000
+vn -0.0000 -1.0000 -0.0000
+vn -0.0000 1.0000 -0.0000
 vt 0.625000 0.000000
 vt 0.375000 0.250000
 vt 0.375000 0.000000
+vt 0.625000 0.250000
 vt 0.375000 0.500000
+vt 0.625000 0.500000
+vt 0.375000 0.750000
+vt 0.625000 0.750000
+vt 0.375000 1.000000
 vt 0.125000 0.750000
 vt 0.125000 0.500000
-vt 0.625000 0.250000
-vt 0.875000 0.750000
+vt 0.875000 0.500000
 vt 0.625000 1.000000
-vn 0.0000 -1.0000 0.0000
-vn 0.0000 0.0000 -1.0000
-vn -1.0000 0.0000 0.0000
-vn 0.0000 1.0000 0.0000
-vn 1.0000 0.0000 0.0000
-vn 0.0000 0.0000 1.0000
-# usemtl Material
-s off
-f 5/1/1 3/2/1 1/3/1
-f 3/2/2 8/4/2 4/5/2
-f 7/6/3 6/7/3 8/8/3
-f 2/9/4 8/10/4 6/11/4
-f 1/3/5 4/5/5 2/9/5
-f 5/12/6 2/9/6 6/7/6
-f 5/1/1 7/13/1 3/2/1
-f 3/2/2 7/14/2 8/4/2
-f 7/6/3 5/12/3 6/7/3
-f 2/9/4 4/5/4 8/10/4
-f 1/3/5 3/2/5 4/5/5
-f 5/12/6 1/3/6 2/9/6
+vt 0.875000 0.750000
+s 0
+f 2/1/1 3/2/1 1/3/1
+f 4/4/2 7/5/2 3/2/2
+f 8/6/3 5/7/3 7/5/3
+f 6/8/4 1/9/4 5/7/4
+f 7/5/5 1/10/5 3/11/5
+f 4/12/6 6/8/6 8/6/6
+f 2/1/1 4/4/1 3/2/1
+f 4/4/2 8/6/2 7/5/2
+f 8/6/3 6/8/3 5/7/3
+f 6/8/4 2/13/4 1/9/4
+f 7/5/5 5/7/5 1/10/5
+f 4/12/6 2/14/6 6/8/6
diff --git a/src/algo/include/algo/misc.hpp b/src/algo/include/algo/misc.hpp
index 20134b5d47eef8c07affbb0d5813ae4ece92dc65..61e9e54faa17a07d86db2f0a495f079c4885522d 100644
--- a/src/algo/include/algo/misc.hpp
+++ b/src/algo/include/algo/misc.hpp
@@ -4,9 +4,11 @@
 #include <common/aabb.hpp>
 #include <common/node.hpp>
 #include <common/objectbase.hpp>
+#include <rofi/connector.hpp>
 #include <utils/math.hpp>
 
 #include <cmath>
+#include <vector>
 
 bool check_grid_alignment(node_ptr node);
 node_ptr find_node_with_rofi_object(const std::vector<node_ptr> &nodes, objectbase_ptr object);
@@ -20,6 +22,6 @@ bool face_each_other(node_ptr fst_node, node_ptr snd_node, glm::vec3 axis);
 
 bool AABB_intersect(const AABB &fst_aabb, const AABB &snd_aabb, const node_ptr &fst_node, const node_ptr &snd_node);
 
-std::pair<std::size_t, std::size_t> get_pad_width_height(const std::vector<connector_ptr> &connectors);
+std::pair<std::size_t, std::size_t> get_pad_width_height_from_connector_count(const std::vector<connector_ptr> &connectors);
 
 #endif
\ No newline at end of file
diff --git a/src/algo/src/misc.cpp b/src/algo/src/misc.cpp
index a24079353bd9c272a118db98a9f88764ae41025c..0effe7d4e1978a9fc4e186a408ef5028325e1ee4 100644
--- a/src/algo/src/misc.cpp
+++ b/src/algo/src/misc.cpp
@@ -91,7 +91,7 @@ bool AABB_intersect(const AABB &fst_aabb, const AABB &snd_aabb, const node_ptr &
            && AABB_intersect_axis(fst_LH, snd_LH, 2);
 }
 
-std::pair<std::size_t, std::size_t> get_pad_width_height(const std::vector<connector_ptr> &connectors)
+std::pair<std::size_t, std::size_t> get_pad_width_height_from_connector_count(const std::vector<connector_ptr> &connectors)
 {
     float max_x_pos = 0;
     float max_z_pos = 0;
diff --git a/src/edit/include/edit/editor.hpp b/src/edit/include/edit/editor.hpp
index 4f208d666c8c3408021b26f4de0daa0118f8ec78..b20e8af7abea5656a39a8658fa9bda9fd2e6c085 100644
--- a/src/edit/include/edit/editor.hpp
+++ b/src/edit/include/edit/editor.hpp
@@ -49,6 +49,9 @@ public:
     bool save_module_prompt = false;
     bool save_module_visible = false;
     bool save_module_error = false;
+    bool save_rofiworld_prompt = false;
+    bool save_rofiworld_visible = false;
+    bool save_rofiworld_error = false;
     char name_buffer[256] = {0};
     int module_id = 0;
     int add_module_list_index = -1;
@@ -222,11 +225,13 @@ class Editor
     std::pair<glm::vec3, node_ptr> first_connector_highlights = {glm::vec3(0.0f), nullptr};
     std::pair<glm::vec3, node_ptr> second_connector_highlights = {glm::vec3(0.0f), nullptr};
 
+    std::vector<objectbase_ptr> selected_space_joints;
+
     // Default Mesh
 
     mesh_ptr voxel_mesh = Mesh::loadMesh("./data/models/rofi/cube_new_scale.obj");
     mesh_ptr body_mesh = Mesh::loadMesh("./data/models/rofi/body_new_scale.obj", false, false);
-    mesh_ptr pad_board_mesh = Mesh::loadMesh("./data/models/rofi/pad_board.obj", true, false);
+    mesh_ptr pad_board_mesh = Mesh::loadMesh("./data/models/rofi/pad_board.obj", false, false);
 
     mesh_ptr fixed_connector_mesh = Mesh::loadMesh("./data/models/rofi/pad_connector.obj", false, false);
     mesh_ptr open_connector_mesh = Mesh::loadMesh("./data/models/rofi/connector_new_scale.obj", false, false);
@@ -321,6 +326,8 @@ public:
     void setError(std::string message);
 
     void manageUI();
+    void manageUISaveModule();
+    void manageUISaveRofiWorld();
 
     state &getControlState() { return control_state; }
 
@@ -541,6 +548,9 @@ private:
 
     /* COLLISION DETECTION */
     bool detectCollision(bool something_changed, rofiworld_ptr rofiworld);
+
+    /* ROFIWORLD EXPORT */
+    void pickSpaceJoints(rofiworld_ptr rofiworld, bool automatic);
 };
 
 }
diff --git a/src/edit/src/editor.cpp b/src/edit/src/editor.cpp
index 1f60bc94f91fa574c9fe81abdc1d99746cc9bf1e..587e782fd6717508d5d16937a24ee87c64ff4545 100644
--- a/src/edit/src/editor.cpp
+++ b/src/edit/src/editor.cpp
@@ -3,6 +3,7 @@
 #include <algo/misc.hpp>
 #include <gfx/shapes.hpp>
 #include <filein/module_loader.hpp>
+#include <filein/rofiworld_loader.hpp>
 
 #include <iostream>
 #include <iterator>
@@ -46,6 +47,15 @@ void Editor::manageUI()
         ui.connector = nullptr;
     }
 
+    manageUISaveModule();
+    manageUISaveRofiWorld();
+}
+
+void Editor::manageUISaveModule()
+{
+    if (editor_phase != phase::one)
+        return;
+    
     bool saved = false;
     bool exported = false;
     if (ui.save_module_prompt)
@@ -88,6 +98,52 @@ void Editor::manageUI()
     }
 }
 
+void Editor::manageUISaveRofiWorld()
+{
+    if (editor_phase != phase::two)
+        return;
+    
+    bool saved = false;
+    bool exported = false;
+    if (ui.save_rofiworld_prompt)
+    {
+        // check valid
+        if (voxel_graph->empty() || detectCollision(true, rofiworld))
+        {
+            ui.save_rofiworld_error = true;
+            ui.save_rofiworld_visible = true;
+            ui.export_file_prompt = false;
+        }
+        else
+        {
+            saved = true;
+            ui.save_rofiworld_prompt = false;
+            ui.save_rofiworld_error = false;
+            ui.export_file_prompt = false;
+            pickSpaceJoints(rofiworld, true);
+            export_rofiworld(rofiworld, selected_space_joints, ui.name_buffer);
+            // addToModules(std::string(ui.name_buffer), std::string(module_type_buffer));
+        }
+    }
+
+    if (ui.export_file_prompt)
+    {
+        exported = true;
+        ui.export_file_prompt = false;
+        pickSpaceJoints(rofiworld, true);
+        export_rofiworld(rofiworld, selected_space_joints, ui.name_buffer);
+    }
+
+    // if (saved)
+    //     resetModuleVoxelGraph(editor_build_mode_I);
+
+    if (saved || exported)
+    {
+        selected_space_joints.clear();
+        ui.name_buffer[0] = '\0';
+    }
+}
+
 void Editor::update()
 {
     // WARNING: Not tested when placed here, before the rest of the methods
@@ -2734,4 +2790,44 @@ bool Editor::detectCollision(bool something_changed, rofiworld_ptr rofiworld)
     return collision_detected;
 }
 
+/* ROFIWORLD EXPORT */
+
+void Editor::pickSpaceJoints(rofiworld_ptr rofiworld, bool automatic)
+{
+    if (automatic)
+    {
+        std::set<module_ptr> found_modules;
+        for (const auto [module, id] : rofiworld->getModulesMap())
+        {
+            if (found_modules.contains(module))
+                continue;
+
+            std::set<module_ptr> reachable_modules;
+            auto module_vg = module->getParts();
+            if (module_vg->getConnections().empty())
+            {
+                const auto voxel = module_vg->getVoxels().front();
+                reachable_modules = rofiworld->reachableModules(voxel);
+                selected_space_joints.emplace_back(voxel);
+            }
+            else
+            {
+                connector_ptr connector = nullptr;
+                for (const auto &con : module_vg->getConnections())
+                {
+                    if (con->getType(false) != rofi::connector_type::shared_rotation)
+                        connector = con;
+                }
+                ASSUMPTION(connector);
+                
+                reachable_modules = rofiworld->reachableModules(connector);
+                selected_space_joints.emplace_back(connector);
+            }
+
+            found_modules.insert(reachable_modules.begin(), reachable_modules.end()); 
+        }
+    }
+
+}
+
 }
diff --git a/src/filein/include/filein/module_loader.hpp b/src/filein/include/filein/module_loader.hpp
index 006f7a5b7c8dbff82791fe8e65617767bf81afa4..f570642c39414e30bc3e1e14503c72b314d63ca2 100644
--- a/src/filein/include/filein/module_loader.hpp
+++ b/src/filein/include/filein/module_loader.hpp
@@ -80,4 +80,6 @@ const std::map<uint64_t, objectbase_ptr> import_um_shoes(voxel_graph_ptr vg,
 std::vector<std::tuple<uint64_t, uint64_t, float, float>> get_rotation_joints(const boost::json::array &joints_array, const std::set<uint64_t> &body_ids);
 float get_limit(const boost::json::value &limit_value);
 
+std::pair<uint64_t, uint64_t> get_pad_width_height_from_joints(const std::size_t roficom_count, const std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> &from_to_std);
+
 #endif
\ No newline at end of file
diff --git a/src/filein/src/module_loader.cpp b/src/filein/src/module_loader.cpp
index 712639e7ed27b7e81f68e24e4335f370b89bb354..92cee9f592c4ff4398aad895ce0e70fca52143c5 100644
--- a/src/filein/src/module_loader.cpp
+++ b/src/filein/src/module_loader.cpp
@@ -108,7 +108,7 @@ void export_joints_pad(boost::json::array &joints, voxel_graph_ptr &voxel_graph,
 {
     const auto &connections = voxel_graph->getConnections();
     connector_ptr fake_connector = std::make_shared<rofi::OpenConnector>(Node::create());
-    auto [width, height] = get_pad_width_height(connections);
+    auto [width, height] = get_pad_width_height_from_connector_count(connections);
 
     for ( int i = 0; i < width; i++ )
     {
@@ -699,7 +699,7 @@ voxel_graph_ptr import_pad(const boost::json::array &components_array, const boo
     
     auto from_to_std = get_rigid_joints(joints_array, pad_board_ids, roficom_ids);
 
-    const auto [width, height] = get_pad_width_height(roficom_ids.size(), from_to_std);
+    const auto [width, height] = get_pad_width_height_from_joints(roficom_ids.size(), from_to_std);
 
     for ( int x = 0; x < width; ++x ) 
     {
@@ -958,7 +958,7 @@ float get_limit(const boost::json::value &limit_value)
     return 0.0f;
 }
 
-std::pair<uint64_t, uint64_t> get_pad_width_height(const std::size_t roficom_count, const std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> &from_to_std)
+std::pair<uint64_t, uint64_t> get_pad_width_height_from_joints(const std::size_t roficom_count, const std::vector<std::tuple<uint64_t, uint64_t, glm::mat4>> &from_to_std)
 {
     if (roficom_count == 1)
         return {1, 1};
@@ -966,9 +966,18 @@ std::pair<uint64_t, uint64_t> get_pad_width_height(const std::size_t roficom_cou
     if (roficom_count > from_to_std.size())
         return {roficom_count, 1};
 
-    auto [from, to, std] = from_to_std.at(1);
-    uint64_t height = to;
-    std::tie(from, to, std) = from_to_std.back();
+    uint64_t max_to_from_0 = 0;
+
+    for (const auto &[from, to, std] : from_to_std)
+    {
+        if (from > 0)
+            continue;
+
+        if (to > max_to_from_0)
+            max_to_from_0 = to;
+    }
+    uint64_t height = max_to_from_0;
+    const auto &[from, to, std] = from_to_std.back();
     uint64_t width = (to + 1) / height;
 
     return {width, height};
diff --git a/src/filein/src/rofiworld_loader.cpp b/src/filein/src/rofiworld_loader.cpp
index 237091b6962c8e12480060a8a0b88891b079763b..dd5dc6563668935d57f8046bc369f9c83bde58ce 100644
--- a/src/filein/src/rofiworld_loader.cpp
+++ b/src/filein/src/rofiworld_loader.cpp
@@ -18,7 +18,7 @@ void export_rofiworld(const rofiworld_ptr rofiworld, const std::vector<objectbas
     rofiworld_object.emplace("spaceJoints", spaceJoints_array);
 
     boost::json::array moduleJoints_array;
-    // TO DO
+    export_moduleJoints(moduleJoints_array, rofiworld);
     rofiworld_object.emplace("moduleJoints", moduleJoints_array);
 
     save_configuration(rofiworld_object, "./data/rofi/rofiworlds", file_name);
@@ -85,7 +85,7 @@ void export_module_pad(boost::json::array &modules_array, const module_ptr modul
 {
     boost::json::object module_object;
 
-    const auto [width, height] = get_pad_width_height(module->getParts()->getConnections());
+    const auto [width, height] = get_pad_width_height_from_connector_count(module->getParts()->getConnections());
 
     module_object.emplace("width", width);
     module_object.emplace("height", height);
diff --git a/src/gui/include/gui/ui.hpp b/src/gui/include/gui/ui.hpp
index 67c3f12a505fddd3430b7fb3ab5777b3e5a07274..9f46ed12d6512634f0be1d6e80189f6349d2b9cf 100644
--- a/src/gui/include/gui/ui.hpp
+++ b/src/gui/include/gui/ui.hpp
@@ -52,6 +52,8 @@ void module_rotation_manual(edit::UIData &data, glm::vec3 &euler_angles);
 void component_rotation_ui(const osi::Window &window, edit::UIData &data);
 void save_module_ui(const osi::Window &window, edit::UIData &data);
 void export_file_ui(const osi::Window &window, edit::UIData &data);
+void export_module_file_ui(const osi::Window &window, edit::UIData &data);
+void export_rofiworld_file_ui(const osi::Window &window, edit::UIData &data);
 void rotation_settings(const osi::Window &window, edit::UIData &data);
 void experimental_warning(const osi::Window &window, edit::UIData &data);
 
diff --git a/src/gui/src/ui.cpp b/src/gui/src/ui.cpp
index f02399fc3f39b1a64bb6e751ce87fbb45f1a2973..02bb78d9a00b5140e066ab62092b646f85664489 100644
--- a/src/gui/src/ui.cpp
+++ b/src/gui/src/ui.cpp
@@ -179,10 +179,10 @@ void file_menu_ui(const osi::Window &window, edit::UIData &data)
     {
         data.export_file_visible = true;
     }
-    if (ImGui::MenuItem("Import Configuration", NULL, false, data.editor_mode_I == edit::mode_I::build)) 
-    {
-        // TO DO
-    }
+    // if (ImGui::MenuItem("Import Configuration", NULL, false, data.editor_mode_I == edit::mode_I::build)) 
+    // {
+    //     // TO DO
+    // }
 }
 
 void help_menu_ui(const osi::Window &window, edit::UIData &data)
@@ -815,7 +815,19 @@ void export_file_ui(const osi::Window &window, edit::UIData &data)
     if (!data.export_file_visible)
         return;
 
-    if (!ImGui::Begin("Export Module Configuration", &data.export_file_visible, ImGuiWindowFlags_NoCollapse))
+    ImGui::SetNextWindowPos(ImVec2(0, mode_toolbar_height * 3), ImGuiCond_Appearing, ImVec2(0.0f, 0.0f));
+
+    if (data.editor_phase == edit::phase::one)
+        export_module_file_ui(window, data);
+    else if (data.editor_phase == edit::phase::two)
+        export_rofiworld_file_ui(window, data);
+
+}
+
+void export_module_file_ui(const osi::Window &window, edit::UIData &data)
+{
+    if (!ImGui::Begin("Export Module Configuration", &data.export_file_visible, 
+                      ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize))
     {
         ImGui::End();
         return;
@@ -841,6 +853,33 @@ void export_file_ui(const osi::Window &window, edit::UIData &data)
     ImGui::End();
 }
 
+void export_rofiworld_file_ui(const osi::Window &window, edit::UIData &data)
+{
+    if (!ImGui::Begin("Export RofiWorld Configuration", &data.export_file_visible, 
+                      ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize))
+    {
+        ImGui::End();
+        return;
+    }
+
+    ImGui::Text("Enter Text:");
+    
+    // InputText takes a pointer to a buffer, a maximum buffer size, and optional flags
+    ImGui::InputText("File Name##RofiWorldFileNameInput", data.name_buffer, sizeof(data.name_buffer), 
+                     ImGuiInputTextFlags_AutoSelectAll
+                     | ImGuiInputTextFlags_AlwaysOverwrite);
+
+
+    // NECO SE SPACE JOINTS
+
+    if (ImGui::Button("Submit")) {
+        data.export_file_prompt = true;
+        data.export_file_visible = false;
+    }
+
+    ImGui::End();
+}
+
 void rotation_settings(const osi::Window &window, edit::UIData &data)
 {
     if (!data.connector_selected 
diff --git a/src/rofi/include/rofi/module.hpp b/src/rofi/include/rofi/module.hpp
index 52f851966d260f4fd82eea49728546c507c4d918..475d39d3211dd043cb415a153fb03a40c9df4fd8 100644
--- a/src/rofi/include/rofi/module.hpp
+++ b/src/rofi/include/rofi/module.hpp
@@ -30,6 +30,7 @@ class Module
 
     void makeNodeTree();
     void setConnectorDocks();
+    void setComponentIDs();
 
     Module(const Module &other);
     Module(const Module &&other);
diff --git a/src/rofi/include/rofi/rofiworld.hpp b/src/rofi/include/rofi/rofiworld.hpp
index dc8e00c102707a75a77d49a676c1ad793f62d911..aba17839f204a96999725752828a116818db5ede 100644
--- a/src/rofi/include/rofi/rofiworld.hpp
+++ b/src/rofi/include/rofi/rofiworld.hpp
@@ -46,6 +46,7 @@ public:
     void removeModule(module_ptr module);
 
     bool reachable(module_ptr fst_module, module_ptr snd_module) const;
+    std::set<module_ptr> reachableModules(objectbase_ptr component) const;
 
 
     bool rebuildNodeTree(module_ptr module, node_ptr root_node);
diff --git a/src/rofi/include/rofi/voxel_graph.hpp b/src/rofi/include/rofi/voxel_graph.hpp
index bbc504547850e3eb421b470fbc0054999ee81ea6..bde705b43baa9e969afdd125689b7b7ef0176280 100644
--- a/src/rofi/include/rofi/voxel_graph.hpp
+++ b/src/rofi/include/rofi/voxel_graph.hpp
@@ -40,8 +40,8 @@ public:
     bool contains(connector_ptr connector);
 
     static voxel_graph_ptr copy(const voxel_graph_ptr other_voxel_graph, const std::vector<node_ptr> &new_nodes);
-    static void copy_nodes(const std::map<voxel_ptr, voxel_ptr> &voxel_pairs, 
-                           const std::map<connector_ptr, connector_ptr> &connection_pairs, 
+    static void copy_nodes(const std::vector<std::pair<voxel_ptr, voxel_ptr>> &voxel_pairs, 
+                           const std::vector<std::pair<connector_ptr, connector_ptr>> &connection_pairs, 
                            const std::vector<node_ptr> &new_nodes);
 
     void extend(const voxel_graph_ptr other_voxel_graph);
diff --git a/src/rofi/src/module.cpp b/src/rofi/src/module.cpp
index f7a3225054cfe72635d2eaa258650f2cdb5944b2..ac26ba56e039452f0be64126d731fdf730815350 100644
--- a/src/rofi/src/module.cpp
+++ b/src/rofi/src/module.cpp
@@ -45,13 +45,33 @@ void Module::setConnectorDocks() // TO DO: change if connector placement gets ch
     }
 }
 
+void Module::setComponentIDs()
+{
+    for (const auto connector : parts->getConnections())
+    {
+        if (connector->getType(true) == connector_type::open)
+            component_ids.emplace(connector, component_ids.size());
+    }
+    for (const auto connector : parts->getConnections())
+    {
+        if (connector->getType(true) == connector_type::rotation)
+            component_ids.emplace(connector, component_ids.size());
+    }
+
+    for (const auto voxel : parts->getVoxels())
+    {
+        if (!std::dynamic_pointer_cast<ModuleLink>(voxel) && !std::dynamic_pointer_cast<PadBoard>(voxel))
+            component_ids.emplace(voxel, component_ids.size());
+    }
+}
+
 Module::Module(const Module &other)
 {
     node = Node::copy_deep(other.node);
     parts = VoxelGraph::copy(other.parts, node->getChildren());
     name = other.name;
     type = other.type;
-    component_ids = other.component_ids;
+    setComponentIDs();
     setConnectorDocks();
 }
 Module::Module(const Module &&other)
@@ -60,7 +80,7 @@ Module::Module(const Module &&other)
     parts = std::move(other.parts);
     name = std::move(other.name);
     type = std::move(other.type);
-    component_ids = std::move(other.component_ids);
+    setComponentIDs();
     setConnectorDocks();
 }
 Module& Module::operator=(const Module &other)
@@ -80,7 +100,7 @@ Module& Module::operator=(const Module &&other)
     parts = std::move(other.parts);
     name = std::move(other.name);
     type = std::move(other.type);
-    component_ids = std::move(other.component_ids);
+    setComponentIDs();
     setConnectorDocks();
 
     return *this;
diff --git a/src/rofi/src/rofiworld.cpp b/src/rofi/src/rofiworld.cpp
index 431f0c866a0e6b6ceffe10a21513a2b4af600cc0..aa5790ba0aca8b642c2052c3c8bbdb09ba0c304c 100644
--- a/src/rofi/src/rofiworld.cpp
+++ b/src/rofi/src/rofiworld.cpp
@@ -89,6 +89,23 @@ bool RofiWorld::reachable(module_ptr fst_module, module_ptr snd_module) const
     return found_modules.contains(snd_module);
 }
 
+std::set<module_ptr> RofiWorld::reachableModules(objectbase_ptr component) const
+{
+    node_ptr start_node;
+    if (auto voxel = std::dynamic_pointer_cast<Voxel>(component))
+        start_node = voxel->getNode();
+    else if (auto connector = std::dynamic_pointer_cast<Connector>(component))
+        start_node = connector->getNode();
+
+    auto start_module = getModuleWithNode(start_node);
+
+    bool has_cycle = false; // Not being detected here
+    std::set<module_ptr> found_modules;
+    traverseConnectedModules(start_module, nullptr, nullptr, found_modules, has_cycle);
+    
+    return found_modules;
+}
+
 bool RofiWorld::rebuildNodeTree(module_ptr module, node_ptr root_node) // NOTE: Maybe could use views if I knew how to.
 {
     std::set<module_ptr> found_modules;
diff --git a/src/rofi/src/voxel_graph.cpp b/src/rofi/src/voxel_graph.cpp
index dc8bd3677e8a9db189d934009aeaeccb3f7ad71b..284a9f19b37eefb33798944f51daab7e24ae2e97 100644
--- a/src/rofi/src/voxel_graph.cpp
+++ b/src/rofi/src/voxel_graph.cpp
@@ -85,22 +85,31 @@ bool VoxelGraph::contains(connector_ptr connector)
     return std::find(connections.begin(), connections.end(), connector) != connections.end();
 }
 
+auto find_new_from_orig(auto orig_new_pairs, auto orig_component)
+{
+    return std::find_if(orig_new_pairs.begin(), orig_new_pairs.end(), [&orig_component](const auto & pair) { return pair.first == orig_component; } )->second;
+}
+
 voxel_graph_ptr VoxelGraph::copy(const voxel_graph_ptr other_voxel_graph, const std::vector<node_ptr> &new_nodes)
 {
-    std::map<voxel_ptr, voxel_ptr> voxel_pairs;
-    std::map<connector_ptr, connector_ptr> connection_pairs;
+    std::vector<std::pair<voxel_ptr, voxel_ptr>> voxel_pairs;
+    std::vector<std::pair<connector_ptr, connector_ptr>> connection_pairs;
 
     for (const auto &orig_voxel : other_voxel_graph->voxels)
-        voxel_pairs[orig_voxel] = Voxel::copy(orig_voxel);
+        voxel_pairs.emplace_back(orig_voxel, Voxel::copy(orig_voxel));
+        // voxel_pairs[orig_voxel] = Voxel::copy(orig_voxel);
     for (const auto &orig_connector : other_voxel_graph->connections)
-        connection_pairs[orig_connector] = Connector::copy(orig_connector);
+        connection_pairs.emplace_back(orig_connector, Connector::copy(orig_connector));
+        // connection_pairs[orig_connector] = Connector::copy(orig_connector);
 
     for (const auto &orig_voxel : other_voxel_graph->voxels)
     {
         for (const auto &[side, weak_con] : orig_voxel->connections)
         {
             auto orig_connector = weak_con.lock();
-            voxel_pairs[orig_voxel]->connections[side] = connection_pairs[orig_connector];
+            auto new_voxel = find_new_from_orig(voxel_pairs, orig_voxel);
+            new_voxel->connections[side] = find_new_from_orig(connection_pairs, orig_connector);
+            // voxel_pairs[orig_voxel]->connections[side] = connection_pairs[orig_connector];
         }
     }
 
@@ -109,20 +118,22 @@ voxel_graph_ptr VoxelGraph::copy(const voxel_graph_ptr other_voxel_graph, const
         if (!orig_connector->connection.first.expired())
         {
             const auto orig_voxel = orig_connector->connection.first.lock();
-            connection_pairs[orig_connector]->connection.first = voxel_pairs[orig_voxel];
+            find_new_from_orig(connection_pairs, orig_connector)->connection.first = find_new_from_orig(voxel_pairs, orig_voxel);
+            // connection_pairs[orig_connector]->connection.first = find_new_from_orig(voxel_pairs, orig_voxel);
         }
 
         if (!orig_connector->connection.second.expired())
         {
             const auto orig_voxel = orig_connector->connection.second.lock();
-            connection_pairs[orig_connector]->connection.second = voxel_pairs[orig_voxel];
+            find_new_from_orig(connection_pairs, orig_connector)->connection.second = find_new_from_orig(voxel_pairs, orig_voxel);
+            // connection_pairs[orig_connector]->connection.second = find_new_from_orig(voxel_pairs, orig_voxel);
         }
 
         if (const auto orig_rot_con = std::dynamic_pointer_cast<RotationConnector>(orig_connector))
         {
-            auto rot_con = std::dynamic_pointer_cast<RotationConnector>(connection_pairs[orig_connector]);
-            auto fst = connection_pairs[orig_rot_con->getBoundConnectors().first.lock()];
-            auto snd = connection_pairs[orig_rot_con->getBoundConnectors().second.lock()];
+            auto rot_con = std::dynamic_pointer_cast<RotationConnector>(find_new_from_orig(connection_pairs, orig_connector));
+            auto fst = find_new_from_orig(connection_pairs, orig_rot_con->getBoundConnectors().first.lock());
+            auto snd = find_new_from_orig(connection_pairs, orig_rot_con->getBoundConnectors().second.lock());
             rot_con->setBoundConnectors(fst, snd);
         }
     }
@@ -139,7 +150,9 @@ voxel_graph_ptr VoxelGraph::copy(const voxel_graph_ptr other_voxel_graph, const
     return std::make_shared<VoxelGraph>(copy_voxels, copy_connections);
 }
 
-void VoxelGraph::copy_nodes(const std::map<voxel_ptr, voxel_ptr> &voxel_pairs, const std::map<connector_ptr, connector_ptr> &connection_pairs, const std::vector<node_ptr> &new_nodes)
+void VoxelGraph::copy_nodes(const std::vector<std::pair<voxel_ptr, voxel_ptr>> &voxel_pairs, 
+                            const std::vector<std::pair<connector_ptr, connector_ptr>> &connection_pairs, 
+                            const std::vector<node_ptr> &new_nodes)
 {
     for (auto &[orig_voxel, new_voxel] : voxel_pairs)
     {