Project Alice
Loading...
Searching...
No Matches
serialization.cpp
Go to the documentation of this file.
1#include "dcon_generated.hpp"
2#include "system_state.hpp"
3#include "serialization.hpp"
4#include <random>
5#include <ctime>
6
7#define ZSTD_STATIC_LINKING_ONLY
8#define XXH_NAMESPACE ZSTD_
9
10#include "blake2.h"
11#include "zstd.h"
12
13namespace sys {
14
15uint8_t const* read_scenario_header(uint8_t const* ptr_in, scenario_header& header_out) {
16 uint32_t length = 0;
17 memcpy(&length, ptr_in, sizeof(uint32_t));
18 memcpy(&header_out, ptr_in + sizeof(uint32_t), std::min(length, uint32_t(sizeof(scenario_header))));
19 return ptr_in + sizeof(uint32_t) + length;
20}
21
22uint8_t const* read_save_header(uint8_t const* ptr_in, save_header& header_out) {
23 uint32_t length = 0;
24 memcpy(&length, ptr_in, sizeof(uint32_t));
25 memcpy(&header_out, ptr_in + sizeof(uint32_t), std::min(length, uint32_t(sizeof(save_header))));
26 return ptr_in + sizeof(uint32_t) + length;
27}
28
30 uint32_t length = uint32_t(sizeof(scenario_header));
31 memcpy(ptr_in, &length, sizeof(uint32_t));
32 memcpy(ptr_in + sizeof(uint32_t), &header_in, sizeof(scenario_header));
33 return ptr_in + sizeof_scenario_header(header_in);
34}
35uint8_t* write_save_header(uint8_t* ptr_in, save_header const& header_in) {
36 uint32_t length = uint32_t(sizeof(save_header));
37 memcpy(ptr_in, &length, sizeof(uint32_t));
38 memcpy(ptr_in + sizeof(uint32_t), &header_in, sizeof(save_header));
39 return ptr_in + sizeof_save_header(header_in);
40}
41
42size_t sizeof_scenario_header(scenario_header const& header_in) {
43 return sizeof(uint32_t) + sizeof(scenario_header);
44}
45
46size_t sizeof_save_header(save_header const& header_in) {
47 return sizeof(uint32_t) + sizeof(save_header);
48}
49
50void read_mod_path(uint8_t const* ptr_in, uint8_t const* lim, native_string& path_out) {
51 uint32_t length = 0;
52 if(size_t(lim - ptr_in) < sizeof(uint32_t))
53 return;
54
55 memcpy(&length, ptr_in, sizeof(uint32_t));
56 ptr_in += sizeof(uint32_t);
57
58 if(size_t(lim - ptr_in) < sizeof(uint32_t) + length * sizeof(native_char))
59 return;
60
61 path_out = native_string(native_string_view(reinterpret_cast<native_char const*>(ptr_in), length));
62}
63uint8_t const* load_mod_path(uint8_t const* ptr_in, sys::state& state) {
64 uint32_t length = 0;
65 memcpy(&length, ptr_in, sizeof(uint32_t));
66 ptr_in += sizeof(uint32_t);
67
68 simple_fs::restore_state(state.common_fs, native_string_view(reinterpret_cast<native_char const*>(ptr_in), length));
69 return ptr_in + length * sizeof(native_char);
70}
71uint8_t* write_mod_path(uint8_t* ptr_in, native_string const& path_in) {
72 uint32_t length = uint32_t(path_in.length());
73 memcpy(ptr_in, &length, sizeof(uint32_t));
74 ptr_in += sizeof(uint32_t);
75 memcpy(ptr_in, path_in.c_str(), length * sizeof(native_char));
76 ptr_in += length * sizeof(native_char);
77 return ptr_in;
78}
79size_t sizeof_mod_path(native_string const& path_in) {
80 size_t sz = 0;
81 uint32_t length = uint32_t(path_in.length());
82 sz += sizeof(uint32_t);
83 sz += length * sizeof(native_char);
84 return sz;
85}
86
89
90 auto file_end = ptr_in + file_size;
91
92 if(file_size > sizeof_scenario_header(h)) {
93 ptr_in = read_scenario_header(ptr_in, h);
94 }
95
97 return mod_identifier{ native_string{}, 0, 0 };
98 }
99
100 native_string mod_path;
101 read_mod_path(ptr_in, file_end, mod_path);
102
103 return mod_identifier{ mod_path, h.timestamp, h.count };
104}
105
106uint8_t* write_compressed_section(uint8_t* ptr_out, uint8_t const* ptr_in, uint32_t uncompressed_size) {
107 uint32_t decompressed_length = uncompressed_size;
108
109 uint32_t section_length = uint32_t(ZSTD_compress(ptr_out + sizeof(uint32_t) * 2, ZSTD_compressBound(uncompressed_size), ptr_in,
110 uncompressed_size, 0)); // write compressed data
111
112 memcpy(ptr_out, &section_length, sizeof(uint32_t));
113 memcpy(ptr_out + sizeof(uint32_t), &decompressed_length, sizeof(uint32_t));
114
115 return ptr_out + sizeof(uint32_t) * 2 + section_length;
116}
117
118template<typename T>
119uint8_t const* with_decompressed_section(uint8_t const* ptr_in, T const& function) {
120 uint32_t section_length = 0;
121 uint32_t decompressed_length = 0;
122 memcpy(&section_length, ptr_in, sizeof(uint32_t));
123 memcpy(&decompressed_length, ptr_in + sizeof(uint32_t), sizeof(uint32_t));
124
125 uint8_t* temp_buffer = new uint8_t[decompressed_length];
126 // TODO: allocate memory for decompression and decompress into it
127
128 ZSTD_decompress(temp_buffer, decompressed_length, ptr_in + sizeof(uint32_t) * 2, section_length);
129
130 // function(ptr_in + sizeof(uint32_t) * 2, decompressed_length);
131 function(temp_buffer, decompressed_length);
132
133 delete[] temp_buffer;
134 return ptr_in + sizeof(uint32_t) * 2 + section_length;
135}
136
137uint8_t const* read_scenario_section(uint8_t const* ptr_in, uint8_t const* section_end, sys::state& state) {
138 // hand-written contribution
139 { // map
149 ptr_in = deserialize(ptr_in, state.map_state.map_data.borders);
154 }
155 {
156 memcpy(&(state.defines), ptr_in, sizeof(parsing::defines));
157 ptr_in += sizeof(parsing::defines);
158 }
159 {
160 memcpy(&(state.economy_definitions), ptr_in, sizeof(economy::global_economy_state));
161 ptr_in += sizeof(economy::global_economy_state);
162 }
163 { // culture definitions
194 }
195 { // military definitions
210 }
211 { // national definitions
280 }
281 { // provincial definitions
292 }
293 ptr_in = memcpy_deserialize(ptr_in, state.start_date);
294 ptr_in = memcpy_deserialize(ptr_in, state.end_date);
295 ptr_in = deserialize(ptr_in, state.trigger_data);
296 ptr_in = deserialize(ptr_in, state.trigger_data_indices);
297 ptr_in = deserialize(ptr_in, state.effect_data);
298 ptr_in = deserialize(ptr_in, state.effect_data_indices);
299 ptr_in = deserialize(ptr_in, state.value_modifier_segments);
300 ptr_in = deserialize(ptr_in, state.value_modifiers);
301 ptr_in = deserialize(ptr_in, state.key_data);
303
304 { // ui definitions
305 ptr_in = deserialize(ptr_in, state.ui_defs.gfx);
306 ptr_in = deserialize(ptr_in, state.ui_defs.textures);
307 ptr_in = deserialize(ptr_in, state.ui_defs.gui);
309 ptr_in = deserialize(ptr_in, state.ui_defs.extensions);
310 }
311
312 // data container
313
314 dcon::load_record loaded;
315 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
316 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded);
317
318 return section_end;
319}
321 // hand-written contribution
322 { // map
332 ptr_in = serialize(ptr_in, state.map_state.map_data.borders);
337 }
338 {
339 memcpy(ptr_in, &(state.defines), sizeof(parsing::defines));
340 ptr_in += sizeof(parsing::defines);
341 }
342 {
343 memcpy(ptr_in, &(state.economy_definitions), sizeof(economy::global_economy_state));
344 ptr_in += sizeof(economy::global_economy_state);
345 }
346 { // culture definitions
353 ptr_in = serialize(ptr_in, state.culture_definitions.crimes);
377 }
378 { // military definitions
393 }
394 { // national definitions
463 }
464 { // provincial definitions
465 ptr_in = serialize(ptr_in, state.province_definitions.canals);
475 }
476 ptr_in = memcpy_serialize(ptr_in, state.start_date);
477 ptr_in = memcpy_serialize(ptr_in, state.end_date);
478 ptr_in = serialize(ptr_in, state.trigger_data);
479 ptr_in = serialize(ptr_in, state.trigger_data_indices);
480 ptr_in = serialize(ptr_in, state.effect_data);
481 ptr_in = serialize(ptr_in, state.effect_data_indices);
482 ptr_in = serialize(ptr_in, state.value_modifier_segments);
483 ptr_in = serialize(ptr_in, state.value_modifiers);
484 ptr_in = serialize(ptr_in, state.key_data);
486
487 { // ui definitions
488 ptr_in = serialize(ptr_in, state.ui_defs.gfx);
489 ptr_in = serialize(ptr_in, state.ui_defs.textures);
490 ptr_in = serialize(ptr_in, state.ui_defs.gui);
491 ptr_in = serialize(ptr_in, state.font_collection.font_names);
492 ptr_in = serialize(ptr_in, state.ui_defs.extensions);
493 }
494
495 dcon::load_record result = state.world.make_serialize_record_store_scenario();
496 std::byte* start = reinterpret_cast<std::byte*>(ptr_in);
497 state.world.serialize(start, result);
498
499 return reinterpret_cast<uint8_t*>(start);
500}
502 size_t sz = 0;
503
504 // hand-written contribution
505 { // map
506 sz += sizeof(state.map_state.map_data.size_x);
507 sz += sizeof(state.map_state.map_data.size_y);
520 }
521 { sz += sizeof(parsing::defines); }
522 { sz += sizeof(economy::global_economy_state); }
523 { // culture definitions
531 sz += sizeof(state.culture_definitions.artisans);
533 sz += sizeof(state.culture_definitions.farmers);
534 sz += sizeof(state.culture_definitions.laborers);
535 sz += sizeof(state.culture_definitions.clergy);
536 sz += sizeof(state.culture_definitions.soldiers);
537 sz += sizeof(state.culture_definitions.officers);
538 sz += sizeof(state.culture_definitions.slaves);
546 sz += sizeof(state.culture_definitions.jingoism);
554 }
555 { // military definitions
563 sz += sizeof(state.military_definitions.liberate);
568 sz += sizeof(state.military_definitions.infantry);
570 }
571 { // national definitions
576 sz += sizeof(state.national_definitions.rebel_id);
582 sz += sizeof(state.national_definitions.easy_ai);
583 sz += sizeof(state.national_definitions.hard_ai);
585 sz += sizeof(state.national_definitions.overseas);
586 sz += sizeof(state.national_definitions.coastal);
589 sz += sizeof(state.national_definitions.sea_zone);
593 sz += sizeof(state.national_definitions.core);
595 sz += sizeof(state.national_definitions.occupied);
599 sz += sizeof(state.national_definitions.war);
600 sz += sizeof(state.national_definitions.peace);
603 sz += sizeof(state.national_definitions.badboy);
640 }
641 { // provincial definitions
646 sz += sizeof(state.province_definitions.europe);
647 sz += sizeof(state.province_definitions.asia);
648 sz += sizeof(state.province_definitions.africa);
651 sz += sizeof(state.province_definitions.oceania);
652 }
653 sz += sizeof(state.start_date);
654 sz += sizeof(state.end_date);
663
664 { // ui definitions
670 }
671
672 // data container contribution
673 dcon::load_record loaded = state.world.make_serialize_record_store_scenario();
674 // dcon::load_record loaded;
675 auto szb = state.world.serialize_size(loaded);
676
677 return scenario_size{ sz + szb, sz };
678}
679
680uint8_t const* read_save_section(uint8_t const* ptr_in, uint8_t const* section_end, sys::state& state) {
681 // hand-written contribution
682 ptr_in = deserialize(ptr_in, state.unit_names);
683 ptr_in = deserialize(ptr_in, state.unit_names_indices);
685 ptr_in = memcpy_deserialize(ptr_in, state.current_date);
686 ptr_in = memcpy_deserialize(ptr_in, state.game_seed);
687 ptr_in = memcpy_deserialize(ptr_in, state.crisis_state);
688 ptr_in = deserialize(ptr_in, state.crisis_participants);
689 ptr_in = memcpy_deserialize(ptr_in, state.current_crisis);
695 ptr_in = memcpy_deserialize(ptr_in, state.crisis_war);
698 ptr_in = memcpy_deserialize(ptr_in, state.crisis_colony);
699 ptr_in = memcpy_deserialize(ptr_in, state.inflation);
700 ptr_in = deserialize(ptr_in, state.great_nations);
701 ptr_in = deserialize(ptr_in, state.pending_n_event);
702 ptr_in = deserialize(ptr_in, state.pending_f_n_event);
703 ptr_in = deserialize(ptr_in, state.pending_p_event);
704 ptr_in = deserialize(ptr_in, state.pending_f_p_event);
705 ptr_in = memcpy_deserialize(ptr_in, state.pending_messages);
707 ptr_in = deserialize(ptr_in, state.future_n_event);
708 ptr_in = deserialize(ptr_in, state.future_p_event);
709
710 { // national definitions
712 }
713
714 { // military definitions
717 }
718
719 // data container contribution
720
721 dcon::load_record loaded;
722
724 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
725 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded);
726 } else {
727 dcon::load_record loadmask = state.world.make_serialize_record_store_save();
728 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
729 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded, loadmask);
730 }
731 return section_end;
732}
733
735 // hand-written contribution
736 ptr_in = serialize(ptr_in, state.unit_names);
737 ptr_in = serialize(ptr_in, state.unit_names_indices);
739 ptr_in = memcpy_serialize(ptr_in, state.current_date);
740 ptr_in = memcpy_serialize(ptr_in, state.game_seed);
741 ptr_in = memcpy_serialize(ptr_in, state.crisis_state);
742 ptr_in = serialize(ptr_in, state.crisis_participants);
743 ptr_in = memcpy_serialize(ptr_in, state.current_crisis);
744 ptr_in = memcpy_serialize(ptr_in, state.crisis_temperature);
749 ptr_in = memcpy_serialize(ptr_in, state.crisis_war);
752 ptr_in = memcpy_serialize(ptr_in, state.crisis_colony);
753 ptr_in = memcpy_serialize(ptr_in, state.inflation);
754 ptr_in = serialize(ptr_in, state.great_nations);
755 ptr_in = serialize(ptr_in, state.pending_n_event);
756 ptr_in = serialize(ptr_in, state.pending_f_n_event);
757 ptr_in = serialize(ptr_in, state.pending_p_event);
758 ptr_in = serialize(ptr_in, state.pending_f_p_event);
759 ptr_in = memcpy_serialize(ptr_in, state.pending_messages);
760 ptr_in = memcpy_serialize(ptr_in, state.player_data_cache);
761 ptr_in = serialize(ptr_in, state.future_n_event);
762 ptr_in = serialize(ptr_in, state.future_p_event);
763
764 { // national definitions
766 }
767 { // military definitions
770 }
771
772 // data container contribution
773 dcon::load_record loaded = state.world.make_serialize_record_store_full_save();
774 std::byte* start = reinterpret_cast<std::byte*>(ptr_in);
775 state.world.serialize(start, loaded);
776
777 return reinterpret_cast<uint8_t*>(start);
778}
780 size_t sz = 0;
781
782 // hand-written contribution
783
786 sz += sizeof(state.local_player_nation);
787 sz += sizeof(state.current_date);
788 sz += sizeof(state.game_seed);
789 sz += sizeof(state.crisis_state);
791 sz += sizeof(state.current_crisis);
792 sz += sizeof(state.crisis_temperature);
793 sz += sizeof(state.primary_crisis_attacker);
794 sz += sizeof(state.primary_crisis_defender);
795 sz += sizeof(state.current_crisis_mode);
796 sz += sizeof(state.crisis_last_checked_gp);
797 sz += sizeof(state.crisis_war);
798 sz += sizeof(state.last_crisis_end_date);
799 sz += sizeof(state.crisis_liberation_tag);
800 sz += sizeof(state.crisis_colony);
801 sz += sizeof(state.inflation);
807 sz += sizeof(state.pending_messages);
808 sz += sizeof(state.player_data_cache);
811
812 { // national definitions
814 }
815 { // military definitions
818 }
819
820 // data container contribution
821 dcon::load_record loaded = state.world.make_serialize_record_store_full_save();
822 sz += state.world.serialize_size(loaded);
823
824 return sz;
825}
826
828 scenario_header header;
829 header.count = count;
830 header.timestamp = uint64_t(std::time(nullptr));
831
832 auto scenario_space = sizeof_scenario_section(state);
833 size_t save_space = sizeof_save_section(state);
834
837
838
839 // this is an upper bound, since compacting the data may require less space
840 size_t total_size =
841 sizeof_scenario_header(header) + sizeof_mod_path(simple_fs::extract_state(state.common_fs)) + ZSTD_compressBound(scenario_space.total_size) + ZSTD_compressBound(save_space) + sizeof(uint32_t) * 4;
842
843 uint8_t* temp_buffer = new uint8_t[total_size];
844 uint8_t* buffer_position = temp_buffer;
845
846 buffer_position = write_scenario_header(buffer_position, header);
847 buffer_position = write_mod_path(buffer_position, simple_fs::extract_state(state.common_fs));
848
849 uint8_t* temp_scenario_buffer = new uint8_t[scenario_space.total_size];
850 auto last_written = write_scenario_section(temp_scenario_buffer, state);
851 auto last_written_count = last_written - temp_scenario_buffer;
852 assert(size_t(last_written_count) == scenario_space.total_size);
853 // calculate checksum
854 checksum_key* checksum = &reinterpret_cast<scenario_header*>(temp_buffer + sizeof(uint32_t))->checksum;
855 blake2b(checksum, sizeof(*checksum), temp_scenario_buffer + scenario_space.checksum_offset, scenario_space.total_size - scenario_space.checksum_offset, nullptr, 0);
856 state.scenario_checksum = *checksum;
857
858 buffer_position = write_compressed_section(buffer_position, temp_scenario_buffer, uint32_t(scenario_space.total_size));
859 delete[] temp_scenario_buffer;
860
861 uint8_t* temp_save_buffer = new uint8_t[save_space];
862 auto last_save_written = write_save_section(temp_save_buffer, state);
863 auto last_save_written_count = last_save_written - temp_save_buffer;
864 assert(size_t(last_save_written_count) == save_space);
865 buffer_position = write_compressed_section(buffer_position, temp_save_buffer, uint32_t(save_space));
866 delete[] temp_save_buffer;
867
868 auto total_size_used = buffer_position - temp_buffer;
869
870 simple_fs::write_file(simple_fs::get_or_create_scenario_directory(), name, reinterpret_cast<char*>(temp_buffer),
871 uint32_t(total_size_used));
872
873 delete[] temp_buffer;
874}
877 auto save_file = open_file(dir, name);
878 if(save_file) {
879 scenario_header header;
880 header.version = 0;
881
882 auto contents = simple_fs::view_contents(*save_file);
883 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
884 auto file_end = buffer_pos + contents.file_size;
885
886 if(contents.file_size > sizeof_scenario_header(header)) {
887 buffer_pos = read_scenario_header(buffer_pos, header);
888 }
889
890 if(header.version != sys::scenario_file_version) {
891 return false;
892 }
893
899
900 buffer_pos = load_mod_path(buffer_pos, state);
901
902 buffer_pos = with_decompressed_section(buffer_pos,
903 [&](uint8_t const* ptr_in, uint32_t length) { read_scenario_section(ptr_in, ptr_in + length, state); });
904
905 return true;
906 } else {
907 return false;
908 }
909}
910
913 auto save_file = open_file(dir, name);
914 if(save_file) {
915 scenario_header header;
916 header.version = 0;
917
918 auto contents = simple_fs::view_contents(*save_file);
919 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
920 auto file_end = buffer_pos + contents.file_size;
921
922 if(contents.file_size > sizeof_scenario_header(header)) {
923 buffer_pos = read_scenario_header(buffer_pos, header);
924 }
925
926 if(header.version != sys::scenario_file_version) {
927 return false;
928 }
929
933
936
937 buffer_pos = load_mod_path(buffer_pos, state);
938
939 buffer_pos = with_decompressed_section(buffer_pos,
940 [&](uint8_t const* ptr_in, uint32_t length) { read_scenario_section(ptr_in, ptr_in + length, state); });
941 buffer_pos = with_decompressed_section(buffer_pos,
942 [&](uint8_t const* ptr_in, uint32_t length) { read_save_section(ptr_in, ptr_in + length, state); });
943
944 state.game_seed = uint32_t(std::random_device()());
945
947
948 return true;
949 } else {
950 return false;
951 }
952}
953
956 auto save_file = open_file(dir, name);
957 if(save_file) {
958 scenario_header header;
959 header.version = 0;
960
961 auto contents = simple_fs::view_contents(*save_file);
962 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
963 auto file_end = buffer_pos + contents.file_size;
964
965 if(contents.file_size > sizeof_scenario_header(header)) {
966 buffer_pos = read_scenario_header(buffer_pos, header);
967 }
968
969 if(header.version != sys::scenario_file_version) {
970 return false;
971 }
972
974 return false;
975
977
978 buffer_pos = load_mod_path(buffer_pos, state);
979
980 buffer_pos = with_decompressed_section(buffer_pos,
981 [&](uint8_t const* ptr_in, uint32_t length) {
982 // DO NOTHING -- this skips over reading the scenario section
983 });
984 buffer_pos = with_decompressed_section(buffer_pos,
985 [&](uint8_t const* ptr_in, uint32_t length) {
986 read_save_section(ptr_in, ptr_in + length, state);
987 });
988
989 state.game_seed = uint32_t(std::random_device()());
990
991 return true;
992 } else {
993 return false;
994 }
995}
996
997std::string make_time_string(uint64_t value) {
998 std::string result;
999 for(int32_t i = 64 / 4; i --> 0; ) {
1000 result += char('a' + (0x0F & (value >> (i * 4))));
1001 }
1002 return result;
1003}
1004
1005void write_save_file(sys::state& state, save_type type, std::string const& name) {
1006 save_header header;
1007 header.count = state.scenario_counter;
1008 //header.timestamp = state.scenario_time_stamp;
1009 auto time_stamp = std::time(nullptr);
1010 header.timestamp = int64_t(time_stamp);
1012 header.tag = state.world.nation_get_identity_from_identity_holder(state.local_player_nation);
1013 header.cgov = state.world.nation_get_government_type(state.local_player_nation);
1014 header.d = state.current_date;
1015
1016 memcpy(header.save_name, name.c_str(), std::min(name.length(), size_t(31)));
1017 if(name.length() < 31) {
1018 header.save_name[name.length()] = 0;
1019 } else {
1020 header.save_name[31] = 0;
1021 }
1022
1023 size_t save_space = sizeof_save_section(state);
1024
1025 // this is an upper bound, since compacting the data may require less space
1026 size_t total_size = sizeof_save_header(header) + ZSTD_compressBound(save_space) + sizeof(uint32_t) * 2;
1027
1028 uint8_t* temp_buffer = new uint8_t[total_size];
1029 uint8_t* buffer_position = temp_buffer;
1030
1031 buffer_position = write_save_header(buffer_position, header);
1032
1033 uint8_t* temp_save_buffer = new uint8_t[save_space];
1034 write_save_section(temp_save_buffer, state);
1035
1036 buffer_position = write_compressed_section(buffer_position, temp_save_buffer, uint32_t(save_space));
1037 delete[] temp_save_buffer;
1038
1039 auto total_size_used = buffer_position - temp_buffer;
1040
1042
1043 if(type == sys::save_type::autosave) {
1044 simple_fs::write_file(sdir, native_string(NATIVE("autosave_")) + simple_fs::utf8_to_native(std::to_string(state.autosave_counter)) + native_string(NATIVE(".bin")), reinterpret_cast<char*>(temp_buffer), uint32_t(total_size_used));
1046 } else if(type == sys::save_type::bookmark) {
1047 auto ymd_date = state.current_date.to_ymd(state.start_date);
1048 auto base_str = "bookmark_" + make_time_string(uint64_t(std::time(nullptr))) + "-" + std::to_string(ymd_date.year) + "-" + std::to_string(ymd_date.month) + "-" + std::to_string(ymd_date.day) + ".bin";
1049 simple_fs::write_file(sdir, simple_fs::utf8_to_native(base_str), reinterpret_cast<char*>(temp_buffer), uint32_t(total_size_used));
1050 } else {
1051 auto ymd_date = state.current_date.to_ymd(state.start_date);
1052 auto base_str = make_time_string(uint64_t(std::time(nullptr))) + "-" + nations::int_to_tag(state.world.national_identity_get_identifying_int(header.tag)) + "-" + std::to_string(ymd_date.year) + "-" + std::to_string(ymd_date.month) + "-" + std::to_string(ymd_date.day) + ".bin";
1053 simple_fs::write_file(sdir, simple_fs::utf8_to_native(base_str), reinterpret_cast<char*>(temp_buffer), uint32_t(total_size_used));
1054 }
1055 delete[] temp_buffer;
1056
1057 state.save_list_updated.store(true, std::memory_order::release); // update for ui
1058
1059
1061 auto data_dumps_directory = simple_fs::get_or_create_data_dumps_directory();
1062
1064 data_dumps_directory,
1065 NATIVE("economy_dump.txt"),
1068 );
1070 data_dumps_directory,
1071 NATIVE("prices_dump.txt"),
1074 );
1076 data_dumps_directory,
1077 NATIVE("demand_dump.txt"),
1080 );
1082 data_dumps_directory,
1083 NATIVE("supply_dump.txt"),
1086 );
1088 data_dumps_directory,
1089 NATIVE("demand_by_category_dump.txt"),
1092 );
1093 }
1094}
1097 auto save_file = open_file(dir, name);
1098 if(save_file) {
1099 save_header header;
1100 header.version = 0;
1101
1102 auto contents = simple_fs::view_contents(*save_file);
1103 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
1104 auto file_end = buffer_pos + contents.file_size;
1105
1106 if(contents.file_size > sizeof_save_header(header)) {
1107 buffer_pos = read_save_header(buffer_pos, header);
1108 }
1109
1110 if(header.version != sys::save_file_version) {
1111 return false;
1112 }
1113
1114 //if(state.scenario_counter != header.count)
1115 // return false;
1116 //if(state.scenario_time_stamp != header.timestamp)
1117 // return false;
1119 return false;
1120
1121 state.loaded_save_file = name;
1122
1123 buffer_pos = with_decompressed_section(buffer_pos,
1124 [&](uint8_t const* ptr_in, uint32_t length) { read_save_section(ptr_in, ptr_in + length, state); });
1125
1126 return true;
1127 } else {
1128 return false;
1129 }
1130}
1131
1132} // namespace sys
int blake2b(void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen)
Definition: blake2.c:259
std::vector< textured_line_with_width_vertex > river_vertices
Definition: map.hpp:116
std::vector< GLsizei > river_counts
Definition: map.hpp:118
std::vector< GLsizei > coastal_counts
Definition: map.hpp:124
std::vector< GLint > coastal_starts
Definition: map.hpp:123
std::vector< border > borders
Definition: map.hpp:114
std::vector< GLint > river_starts
Definition: map.hpp:117
std::vector< uint16_t > province_id_map
Definition: map.hpp:162
std::vector< uint8_t > diagonal_borders
Definition: map.hpp:159
std::vector< textured_line_vertex_b > border_vertices
Definition: map.hpp:115
std::vector< textured_line_vertex_b > coastal_vertices
Definition: map.hpp:122
std::vector< uint8_t > terrain_id_map
Definition: map.hpp:156
uint32_t size_y
Definition: map.hpp:169
uint32_t size_x
Definition: map.hpp:168
std::vector< uint32_t > province_area
Definition: map.hpp:158
display_data map_data
Definition: map_state.hpp:60
year_month_day to_ymd(absolute_time_point base) const noexcept
ankerl::unordered_dense::map< uint16_t, dcon::text_key > font_names
Definition: fonts.hpp:178
tagged_vector< element_data, dcon::gui_def_id > gui
std::vector< window_extension > extensions
tagged_vector< gfx_object, dcon::gfx_object_id > gfx
tagged_vector< dcon::text_key, dcon::texture_id > textures
#define assert(condition)
Definition: debug.h:74
std::string int_to_tag(uint32_t v)
Definition: nations.hpp:10
native_string utf8_to_native(std::string_view data_in)
native_string extract_state(file_system const &fs)
void restore_state(file_system &fs, native_string_view data)
void write_file(directory const &dir, native_string_view file_name, char const *file_data, uint32_t file_size)
directory get_or_create_save_game_directory()
directory get_or_create_data_dumps_directory()
file_contents view_contents(file const &f)
directory get_or_create_scenario_directory()
Definition: constants.hpp:4
uint8_t * write_mod_path(uint8_t *ptr_in, native_string const &path_in)
uint8_t * write_scenario_section(uint8_t *ptr_in, sys::state &state)
bool try_read_scenario_as_save_file(sys::state &state, native_string_view name)
size_t sizeof_save_section(sys::state &state)
uint8_t const * read_save_header(uint8_t const *ptr_in, save_header &header_out)
mod_identifier extract_mod_information(uint8_t const *ptr_in, uint64_t file_size)
constexpr uint32_t scenario_file_version
size_t sizeof_mod_path(native_string const &path_in)
uint8_t const * memcpy_deserialize(uint8_t const *ptr_in, T &obj)
save_type
Definition: constants.hpp:565
@ autosave
Definition: constants.hpp:567
@ bookmark
Definition: constants.hpp:568
uint8_t * write_scenario_header(uint8_t *ptr_in, scenario_header const &header_in)
void write_scenario_file(sys::state &state, native_string_view name, uint32_t count)
uint8_t const * with_decompressed_section(uint8_t const *ptr_in, T const &function)
uint8_t const * deserialize(uint8_t const *ptr_in, std::vector< T > &vec)
uint8_t * write_save_section(uint8_t *ptr_in, sys::state &state)
scenario_size sizeof_scenario_section(sys::state &state)
uint8_t const * read_scenario_header(uint8_t const *ptr_in, scenario_header &header_out)
void read_mod_path(uint8_t const *ptr_in, uint8_t const *lim, native_string &path_out)
uint8_t * write_save_header(uint8_t *ptr_in, save_header const &header_in)
std::string make_time_string(uint64_t value)
uint8_t * memcpy_serialize(uint8_t *ptr_in, T const &obj)
bool try_read_scenario_file(sys::state &state, native_string_view name)
size_t serialize_size(std::vector< T > const &vec)
constexpr int32_t max_autosaves
Definition: constants.hpp:176
uint8_t * serialize(uint8_t *ptr_in, std::vector< T > const &vec)
uint8_t const * read_save_section(uint8_t const *ptr_in, uint8_t const *section_end, sys::state &state)
size_t sizeof_save_header(save_header const &header_in)
uint8_t * write_compressed_section(uint8_t *ptr_out, uint8_t const *ptr_in, uint32_t uncompressed_size)
bool try_read_save_file(sys::state &state, native_string_view name)
void write_save_file(sys::state &state, save_type type, std::string const &name)
uint8_t const * load_mod_path(uint8_t const *ptr_in, sys::state &state)
size_t sizeof_scenario_header(scenario_header const &header_in)
constexpr uint32_t save_file_version
uint8_t const * read_scenario_section(uint8_t const *ptr_in, uint8_t const *section_end, sys::state &state)
bool try_read_scenario_and_save_file(sys::state &state, native_string_view name)
char native_char
#define NATIVE(X)
std::string_view native_string_view
std::string native_string
uint uint32_t
ulong uint64_t
uchar uint8_t
std::vector< dcon::issue_id > political_issues
Definition: culture.hpp:126
dcon::value_modifier_key conversion_chance
Definition: culture.hpp:166
std::vector< dcon::reform_id > military_issues
Definition: culture.hpp:128
dcon::pop_type_id farmers
Definition: culture.hpp:139
dcon::value_modifier_key migration_chance
Definition: culture.hpp:162
dcon::pop_type_id clergy
Definition: culture.hpp:141
dcon::value_modifier_key colonialmigration_chance
Definition: culture.hpp:163
tagged_vector< crime_info, dcon::crime_id > crimes
Definition: culture.hpp:134
dcon::value_modifier_key demotion_chance
Definition: culture.hpp:161
std::vector< dcon::reform_id > economic_issues
Definition: culture.hpp:129
dcon::pop_type_id secondary_factory_worker
Definition: culture.hpp:149
dcon::pop_type_id bureaucrat
Definition: culture.hpp:145
dcon::pop_type_id artisans
Definition: culture.hpp:137
std::vector< folder_info > tech_folders
Definition: culture.hpp:131
std::vector< dcon::issue_id > party_issues
Definition: culture.hpp:125
std::vector< dcon::issue_id > social_issues
Definition: culture.hpp:127
dcon::pop_type_id soldiers
Definition: culture.hpp:142
dcon::pop_type_id primary_factory_worker
Definition: culture.hpp:148
dcon::value_modifier_key assimilation_chance
Definition: culture.hpp:165
dcon::pop_type_id officers
Definition: culture.hpp:143
dcon::pop_type_id aristocrat
Definition: culture.hpp:146
dcon::issue_option_id jingoism
Definition: culture.hpp:157
dcon::pop_type_id capitalists
Definition: culture.hpp:138
dcon::ideology_id conservative
Definition: culture.hpp:155
dcon::value_modifier_key promotion_chance
Definition: culture.hpp:160
dcon::pop_type_id laborers
Definition: culture.hpp:140
dcon::pop_type_id slaves
Definition: culture.hpp:144
dcon::value_modifier_key emigration_chance
Definition: culture.hpp:164
dcon::cb_type_id standard_civil_war
Definition: military.hpp:150
dcon::cb_type_id uninstall_communist_gov
Definition: military.hpp:156
dcon::unit_type_id base_army_unit
Definition: military.hpp:147
dcon::unit_type_id irregular
Definition: military.hpp:161
tagged_vector< unit_definition, dcon::unit_type_id > unit_base_definitions
Definition: military.hpp:140
dcon::unit_type_id infantry
Definition: military.hpp:162
dcon::cb_type_id standard_status_quo
Definition: military.hpp:153
dcon::cb_type_id crisis_liberate
Definition: military.hpp:159
dcon::cb_type_id crisis_colony
Definition: military.hpp:158
dcon::cb_type_id standard_great_war
Definition: military.hpp:151
dcon::unit_type_id base_naval_unit
Definition: military.hpp:148
dcon::unit_type_id artillery
Definition: military.hpp:163
dcon::leader_trait_id first_background_trait
Definition: military.hpp:142
std::vector< fixed_event > on_surrender
Definition: nations.hpp:139
std::vector< fixed_event > on_colony_to_state
Definition: nations.hpp:143
std::vector< fixed_event > on_lost_great_nation
Definition: nations.hpp:141
dcon::modifier_id overseas
Definition: nations.hpp:87
std::vector< fixed_event > on_yearly_pulse
Definition: nations.hpp:135
dcon::modifier_id total_occupation
Definition: nations.hpp:117
dcon::modifier_id total_blockaded
Definition: nations.hpp:118
std::vector< fixed_event > on_civilize
Definition: nations.hpp:149
std::vector< fixed_event > on_debtor_default_small
Definition: nations.hpp:147
std::vector< fixed_event > on_state_conquest
Definition: nations.hpp:144
std::vector< fixed_event > on_election_started
Definition: nations.hpp:152
dcon::modifier_id land_province
Definition: nations.hpp:92
dcon::modifier_id easy_ai
Definition: nations.hpp:82
tagged_vector< dcon::text_key, dcon::national_variable_id > variable_names
Definition: nations.hpp:73
dcon::modifier_id very_hard_ai
Definition: nations.hpp:84
dcon::modifier_id base_values
Definition: nations.hpp:102
dcon::modifier_id generalised_debt_default
Definition: nations.hpp:116
dcon::modifier_id coastal_sea
Definition: nations.hpp:90
dcon::national_identity_id rebel_id
Definition: nations.hpp:75
dcon::modifier_id very_hard_player
Definition: nations.hpp:80
dcon::modifier_id hard_ai
Definition: nations.hpp:83
std::vector< fixed_event > on_election_finished
Definition: nations.hpp:153
dcon::modifier_id nationalism
Definition: nations.hpp:98
std::vector< fixed_province_event > on_battle_won
Definition: nations.hpp:137
dcon::modifier_id debt_default_to
Definition: nations.hpp:108
dcon::modifier_id badboy
Definition: nations.hpp:107
dcon::modifier_id coastal
Definition: nations.hpp:88
tagged_vector< dcon::text_key, dcon::global_flag_id > global_flag_variable_names
Definition: nations.hpp:72
std::vector< fixed_event > on_colony_to_state_free_slaves
Definition: nations.hpp:145
dcon::modifier_id hard_player
Definition: nations.hpp:79
dcon::modifier_id very_easy_ai
Definition: nations.hpp:81
dcon::modifier_id unciv_nation
Definition: nations.hpp:113
std::vector< fixed_event > on_quarterly_pulse
Definition: nations.hpp:136
dcon::modifier_id non_coastal
Definition: nations.hpp:89
dcon::modifier_id in_bankrupcy
Definition: nations.hpp:119
dcon::modifier_id disarming
Definition: nations.hpp:105
dcon::modifier_id easy_player
Definition: nations.hpp:78
dcon::modifier_id bad_debter
Definition: nations.hpp:109
tagged_vector< dcon::text_key, dcon::national_flag_id > flag_variable_names
Definition: nations.hpp:71
dcon::modifier_id civ_nation
Definition: nations.hpp:112
dcon::national_focus_id flashpoint_focus
Definition: nations.hpp:125
dcon::modifier_id plurality
Definition: nations.hpp:115
dcon::modifier_id no_adjacent_controlled
Definition: nations.hpp:94
std::vector< fixed_event > on_debtor_default
Definition: nations.hpp:146
std::vector< fixed_event > on_crisis_declare_interest
Definition: nations.hpp:151
dcon::modifier_id sea_zone
Definition: nations.hpp:91
dcon::modifier_id blockaded
Definition: nations.hpp:93
dcon::modifier_id peace
Definition: nations.hpp:104
std::vector< triggered_modifier > triggered_modifiers
Definition: nations.hpp:67
std::vector< fixed_event > on_my_factories_nationalized
Definition: nations.hpp:150
dcon::modifier_id great_power
Definition: nations.hpp:110
std::vector< fixed_election_event > on_election_tick
Definition: nations.hpp:142
dcon::modifier_id war_exhaustion
Definition: nations.hpp:106
dcon::modifier_id infrastructure
Definition: nations.hpp:99
dcon::modifier_id average_literacy
Definition: nations.hpp:114
dcon::modifier_id second_power
Definition: nations.hpp:111
dcon::modifier_id occupied
Definition: nations.hpp:97
dcon::modifier_id very_easy_player
Definition: nations.hpp:77
dcon::modifier_id has_siege
Definition: nations.hpp:96
dcon::modifier_id core
Definition: nations.hpp:95
std::vector< fixed_event > on_new_great_nation
Definition: nations.hpp:140
std::vector< fixed_event > on_debtor_default_second
Definition: nations.hpp:148
std::vector< fixed_province_event > on_battle_lost
Definition: nations.hpp:138
std::vector< dcon::bitfield_type > global_flag_variables
Definition: nations.hpp:68
dcon::modifier_id south_america
Definition: province.hpp:31
ankerl::unordered_dense::map< dcon::modifier_id, dcon::gfx_object_id, sys::modifier_hash > terrain_to_gfx_map
Definition: province.hpp:23
std::vector< dcon::province_adjacency_id > canals
Definition: province.hpp:21
dcon::province_id first_sea_province
Definition: province.hpp:26
dcon::modifier_id north_america
Definition: province.hpp:30
std::vector< dcon::province_id > canal_provinces
Definition: province.hpp:22
std::string national_economy_dump_buffer
std::string prices_dump_buffer
std::string supply_dump_buffer
std::string demand_by_category_dump_buffer
std::string demand_dump_buffer
bool is_equal(const checksum_key &a) noexcept
dcon::national_identity_id tag
dcon::government_type_id cgov
checksum_key checksum
uint64_t scenario_time_stamp
text::font_manager font_collection
dcon::national_identity_id crisis_liberation_tag
culture::global_cultural_state culture_definitions
network_mode_type network_mode
std::vector< char > key_data
std::vector< event::pending_human_p_event > future_p_event
std::atomic< bool > save_list_updated
std::vector< event::pending_human_p_event > pending_p_event
std::vector< value_modifier_segment > value_modifier_segments
ankerl::unordered_dense::set< dcon::text_key, text::vector_backed_ci_hash, text::vector_backed_ci_eq > untrans_key_to_text_sequence
dcon::data_container world
std::vector< crisis_member_def > crisis_participants
std::vector< event::pending_human_f_p_event > pending_f_p_event
std::vector< uint16_t > effect_data
dcon::state_definition_id crisis_colony
dcon::nation_id local_player_nation
parsing::defines defines
std::vector< char > unit_names
std::vector< int32_t > trigger_data_indices
uint32_t crisis_last_checked_gp
tagged_vector< value_modifier_description, dcon::value_modifier_key > value_modifiers
economy::global_economy_state economy_definitions
simple_fs::file_system common_fs
absolute_time_point start_date
absolute_time_point end_date
uint32_t game_seed
military::global_military_state military_definitions
sys::date current_date
sys::checksum_key scenario_checksum
std::vector< int32_t > unit_names_indices
native_string loaded_save_file
player_data player_data_cache
dcon::nation_id primary_crisis_defender
std::array< diplomatic_message::message, 128 > pending_messages
std::vector< event::pending_human_n_event > future_n_event
cheat_data_s cheat_data
uint32_t scenario_counter
std::vector< great_nation > great_nations
dcon::war_id crisis_war
crisis_type current_crisis
native_string loaded_scenario_file
map::map_state map_state
province::global_provincial_state province_definitions
int32_t autosave_counter
sys::date last_crisis_end_date
std::vector< event::pending_human_f_n_event > pending_f_n_event
void on_scenario_load()
dcon::state_instance_id crisis_state
dcon::nation_id primary_crisis_attacker
std::vector< int32_t > effect_data_indices
ui::definitions ui_defs
std::vector< event::pending_human_n_event > pending_n_event
std::vector< uint16_t > trigger_data
float crisis_temperature
crisis_mode current_crisis_mode
nations::global_national_state national_definitions
size_t ZSTD_compressBound(size_t srcSize)
Definition: zstd_compress.c:69
size_t ZSTD_compress(void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel)
size_t ZSTD_decompress(void *dst, size_t dstCapacity, const void *src, size_t srcSize)