Guest User

Untitled

a guest
Mar 20th, 2023
953
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.50 KB | None | 0 0
  1. #include <fstream>
  2. #include <vector>
  3. #include <optional>
  4. #include <tuple>
  5. #include <utility>
  6. #include "cereal/cereal.hpp"
  7. #include "cereal/archives/xml.hpp"
  8. #include "cereal/types/vector.hpp"
  9. #include "cereal/types/memory.hpp"
  10. #include "cereal/types/tuple.hpp"
  11. #include "cereal/types/utility.hpp"
  12. #include "cereal/archives/portable_binary.hpp"
  13. #include "cereal/archives/binary.hpp"
  14. #include "entt.hpp"
  15.  
  16. namespace cereal {
  17.     template <class Archive, typename T>
  18.     inline void save(Archive& archive, const std::optional<T>& optional) {
  19.         bool has_value = optional.has_value();
  20.         archive(has_value);
  21.         if (has_value) {
  22.             archive(*optional);
  23.         }
  24.     }
  25.  
  26.     template <class Archive, typename T>
  27.     inline void load(Archive& archive, std::optional<T>& optional) {
  28.         bool has_value;
  29.         archive(has_value);
  30.         if (has_value) {
  31.             T value;
  32.             archive(value);
  33.             optional.emplace(std::move(value));
  34.         } else {
  35.             optional.reset();
  36.         }
  37.     }
  38. }  // namespace cereal
  39.  
  40. template <typename...>
  41. struct type_list {};
  42.  
  43. template <typename Components, typename ContextVars>
  44. struct RegistryArchive;
  45.  
  46. template <typename... Components, typename... ContextVars>
  47. struct RegistryArchive<type_list<Components...>, type_list<ContextVars...>> {
  48.     std::tuple<std::vector<std::pair<entt::entity, Components>>...> components;
  49.     std::tuple<std::optional<ContextVars>...> context_vars;
  50. };
  51.  
  52. template <typename... Components, typename... ContextVars, typename Archive>
  53. void serialize_registry(entt::registry const& registry,
  54.                         type_list<Components...>, type_list<ContextVars...>,
  55.                         Archive& archive) {
  56.     RegistryArchive<type_list<Components...>, type_list<ContextVars...>>
  57.         snapshot;
  58.  
  59.     registry.each([&](entt::entity ent) {
  60.         (
  61.             [&]() {
  62.                 if (registry.any_of<Components>(ent)) {
  63.                     if constexpr (std::is_empty_v<Components>) {
  64.                         std::get<
  65.                             std::vector<std::pair<entt::entity, Components>>>(
  66.                             snapshot.components)
  67.                             .emplace_back(ent, Components{});
  68.                     } else {
  69.                         std::get<
  70.                             std::vector<std::pair<entt::entity, Components>>>(
  71.                             snapshot.components)
  72.                             .emplace_back(ent, registry.get<Components>(ent));
  73.                     }
  74.                 }
  75.             }(),
  76.             ...);
  77.     });
  78.  
  79.     (
  80.         [&]() {
  81.             if (auto ptr = registry.ctx().find<ContextVars>()) {
  82.                 std::get<std::optional<ContextVars>>(snapshot.context_vars)
  83.                     .emplace(*ptr);
  84.             }
  85.         }(),
  86.         ...);
  87.  
  88.     archive(snapshot.components, snapshot.context_vars);
  89. }
  90.  
  91. template <typename T>
  92. void set_context_var(entt::registry& registry, const std::optional<T>& ctx_var_opt) {
  93.     if (ctx_var_opt.has_value()) {
  94.         registry.ctx().emplace<T>(ctx_var_opt.value());
  95.     }
  96. }
  97.  
  98. template <typename... Components, typename... ContextVars, typename Archive>
  99. void deserialize_registry(entt::registry& registry, type_list<Components...>, type_list<ContextVars...>, Archive& archive) {
  100.     RegistryArchive<type_list<Components...>, type_list<ContextVars...>> snapshot;
  101.  
  102.     archive(snapshot.components, snapshot.context_vars);
  103.  
  104.     registry = entt::registry();
  105.  
  106.     (
  107.         [&]() {
  108.             for (const auto& [entity, component] : std::get<std::vector<std::pair<entt::entity, Components>>>(snapshot.components)) {
  109.                 if (!registry.valid(entity)) {
  110.                     auto e = registry.create(entity);
  111.                 }
  112.                 registry.emplace_or_replace<Components>(entity, component);
  113.             }
  114.         }(),
  115.         ...);
  116.  
  117.     (
  118.         [&]() {
  119.             set_context_var<ContextVars>(registry, std::get<std::optional<ContextVars>>(snapshot.context_vars));
  120.         }(),
  121.         ...);
  122. }
  123.  
  124. struct position {
  125.     float x, y, z;
  126. };
  127. struct velocity {
  128.     float x, y, z;
  129. };
  130.  
  131. template <class Archive>
  132. void serialize(Archive& archive, position& v) {
  133.     archive(v.x, v.y, v.z);
  134. }
  135.  
  136. template <class Archive>
  137. void serialize(Archive& archive, velocity& v) {
  138.     archive(v.x, v.y, v.z);
  139. }
  140.  
  141. template <class Archive>
  142. void save(Archive& archive, entt::entity const& ent) {
  143.     archive(static_cast<entt::id_type>(ent));
  144. }
  145.  
  146. template <class Archive>
  147. void load(Archive& archive, entt::entity& ent) {
  148.     entt::id_type e;
  149.     archive(e);
  150.     ent = static_cast<entt::entity>(e);
  151. }
  152.  
  153. int main() {
  154.     entt::registry registry;
  155.     auto e1 = registry.create();
  156.     registry.emplace<position>(e1, position{ 1, 2, 3 });
  157.     registry.ctx().emplace<velocity>(velocity{ 0, 0 });
  158.  
  159.     {
  160.         auto view = registry.view<position>();
  161.         view.each([](position &p)
  162.         {
  163.             std::cout << "Entity Save Value: " + std::to_string(p.x) << std::endl;
  164.         });
  165.         std::cout << "Context Save Value: " << std::to_string(registry.ctx().get<velocity>().x) << std::endl;
  166.     }
  167.  
  168.     std::cout << std::endl;
  169.  
  170.     std::string savePath = "state.bin";
  171.     {
  172.         std::ofstream os(savePath, std::ios::binary);
  173.         cereal::PortableBinaryOutputArchive archive(os);
  174.         serialize_registry(registry, type_list<position, velocity>{}, type_list<position, velocity>{}, archive);
  175.     }
  176.  
  177.     {
  178.         auto view = registry.view<position>();
  179.         view.each([](position &p)
  180.         {
  181.             p.x += 99;
  182.             std::cout << "Entity value changed to: " + std::to_string(p.x) << std::endl;
  183.         });
  184.         registry.ctx().get<velocity>().x = 99;
  185.         std::cout << "Context value changed to: " << std::to_string(registry.ctx().get<velocity>().x) << std::endl;
  186.     }
  187.  
  188.     std::cout << std::endl;
  189.  
  190.     {
  191.         std::cout << "load();" << std::endl;
  192.         std::ifstream os(savePath, std::ios::binary);
  193.         cereal::PortableBinaryInputArchive archive(os);
  194.         deserialize_registry(registry, type_list<position, velocity>{}, type_list<position, velocity>{}, archive);
  195.     }
  196.  
  197.     std::cout << std::endl;
  198.  
  199.     {
  200.         auto view = registry.view<position>();
  201.         view.each([](position &p)
  202.         {
  203.             std::cout << "After Load Entity (expected: 1): " << std::to_string(p.x) << std::endl;
  204.         });
  205.  
  206.         std::cout << "After Load ctx (expected 0): " << std::to_string(registry.ctx().get<velocity>().x) << std::endl;
  207.     }
  208. }
Advertisement
Add Comment
Please, Sign In to add comment