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
208 }
209 { // national definitions
278 }
279 { // provincial definitions
290 }
291 ptr_in = memcpy_deserialize(ptr_in, state.start_date);
292 ptr_in = memcpy_deserialize(ptr_in, state.end_date);
293 ptr_in = deserialize(ptr_in, state.trigger_data);
294 ptr_in = deserialize(ptr_in, state.trigger_data_indices);
295 ptr_in = deserialize(ptr_in, state.effect_data);
296 ptr_in = deserialize(ptr_in, state.effect_data_indices);
297 ptr_in = deserialize(ptr_in, state.value_modifier_segments);
298 ptr_in = deserialize(ptr_in, state.value_modifiers);
299 ptr_in = deserialize(ptr_in, state.key_data);
301
302 { // ui definitions
303 ptr_in = deserialize(ptr_in, state.ui_defs.gfx);
304 ptr_in = deserialize(ptr_in, state.ui_defs.textures);
305 ptr_in = deserialize(ptr_in, state.ui_defs.gui);
307 ptr_in = deserialize(ptr_in, state.ui_defs.extensions);
308 }
309
310 // data container
311
312 dcon::load_record loaded;
313 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
314 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded);
315
316 return section_end;
317}
319 // hand-written contribution
320 { // map
330 ptr_in = serialize(ptr_in, state.map_state.map_data.borders);
335 }
336 {
337 memcpy(ptr_in, &(state.defines), sizeof(parsing::defines));
338 ptr_in += sizeof(parsing::defines);
339 }
340 {
341 memcpy(ptr_in, &(state.economy_definitions), sizeof(economy::global_economy_state));
342 ptr_in += sizeof(economy::global_economy_state);
343 }
344 { // culture definitions
351 ptr_in = serialize(ptr_in, state.culture_definitions.crimes);
375 }
376 { // military definitions
389 }
390 { // national definitions
459 }
460 { // provincial definitions
461 ptr_in = serialize(ptr_in, state.province_definitions.canals);
471 }
472 ptr_in = memcpy_serialize(ptr_in, state.start_date);
473 ptr_in = memcpy_serialize(ptr_in, state.end_date);
474 ptr_in = serialize(ptr_in, state.trigger_data);
475 ptr_in = serialize(ptr_in, state.trigger_data_indices);
476 ptr_in = serialize(ptr_in, state.effect_data);
477 ptr_in = serialize(ptr_in, state.effect_data_indices);
478 ptr_in = serialize(ptr_in, state.value_modifier_segments);
479 ptr_in = serialize(ptr_in, state.value_modifiers);
480 ptr_in = serialize(ptr_in, state.key_data);
482
483 { // ui definitions
484 ptr_in = serialize(ptr_in, state.ui_defs.gfx);
485 ptr_in = serialize(ptr_in, state.ui_defs.textures);
486 ptr_in = serialize(ptr_in, state.ui_defs.gui);
487 ptr_in = serialize(ptr_in, state.font_collection.font_names);
488 ptr_in = serialize(ptr_in, state.ui_defs.extensions);
489 }
490
491 dcon::load_record result = state.world.make_serialize_record_store_scenario();
492 std::byte* start = reinterpret_cast<std::byte*>(ptr_in);
493 state.world.serialize(start, result);
494
495 return reinterpret_cast<uint8_t*>(start);
496}
498 size_t sz = 0;
499
500 // hand-written contribution
501 { // map
502 sz += sizeof(state.map_state.map_data.size_x);
503 sz += sizeof(state.map_state.map_data.size_y);
516 }
517 { sz += sizeof(parsing::defines); }
518 { sz += sizeof(economy::global_economy_state); }
519 { // culture definitions
527 sz += sizeof(state.culture_definitions.artisans);
529 sz += sizeof(state.culture_definitions.farmers);
530 sz += sizeof(state.culture_definitions.laborers);
531 sz += sizeof(state.culture_definitions.clergy);
532 sz += sizeof(state.culture_definitions.soldiers);
533 sz += sizeof(state.culture_definitions.officers);
534 sz += sizeof(state.culture_definitions.slaves);
542 sz += sizeof(state.culture_definitions.jingoism);
550 }
551 { // military definitions
559 sz += sizeof(state.military_definitions.liberate);
564 }
565 { // national definitions
570 sz += sizeof(state.national_definitions.rebel_id);
576 sz += sizeof(state.national_definitions.easy_ai);
577 sz += sizeof(state.national_definitions.hard_ai);
579 sz += sizeof(state.national_definitions.overseas);
580 sz += sizeof(state.national_definitions.coastal);
583 sz += sizeof(state.national_definitions.sea_zone);
587 sz += sizeof(state.national_definitions.core);
589 sz += sizeof(state.national_definitions.occupied);
593 sz += sizeof(state.national_definitions.war);
594 sz += sizeof(state.national_definitions.peace);
597 sz += sizeof(state.national_definitions.badboy);
634 }
635 { // provincial definitions
640 sz += sizeof(state.province_definitions.europe);
641 sz += sizeof(state.province_definitions.asia);
642 sz += sizeof(state.province_definitions.africa);
645 sz += sizeof(state.province_definitions.oceania);
646 }
647 sz += sizeof(state.start_date);
648 sz += sizeof(state.end_date);
657
658 { // ui definitions
664 }
665
666 // data container contribution
667 dcon::load_record loaded = state.world.make_serialize_record_store_scenario();
668 // dcon::load_record loaded;
669 auto szb = state.world.serialize_size(loaded);
670
671 return scenario_size{ sz + szb, sz };
672}
673
674uint8_t const* read_save_section(uint8_t const* ptr_in, uint8_t const* section_end, sys::state& state) {
675 // hand-written contribution
676 ptr_in = deserialize(ptr_in, state.unit_names);
677 ptr_in = deserialize(ptr_in, state.unit_names_indices);
679 ptr_in = memcpy_deserialize(ptr_in, state.current_date);
680 ptr_in = memcpy_deserialize(ptr_in, state.game_seed);
682 ptr_in = deserialize(ptr_in, state.crisis_participants);
688 ptr_in = memcpy_deserialize(ptr_in, state.crisis_war);
692 ptr_in = memcpy_deserialize(ptr_in, state.inflation);
693 ptr_in = deserialize(ptr_in, state.great_nations);
694 ptr_in = deserialize(ptr_in, state.pending_n_event);
695 ptr_in = deserialize(ptr_in, state.pending_f_n_event);
696 ptr_in = deserialize(ptr_in, state.pending_p_event);
697 ptr_in = deserialize(ptr_in, state.pending_f_p_event);
698 ptr_in = memcpy_deserialize(ptr_in, state.pending_messages);
700 ptr_in = deserialize(ptr_in, state.future_n_event);
701 ptr_in = deserialize(ptr_in, state.future_p_event);
702
703 { // national definitions
705 }
706
707 { // military definitions
710 }
711
712 // data container contribution
713
714 dcon::load_record loaded;
715
717 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
718 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded);
719 } else {
720 dcon::load_record loadmask = state.world.make_serialize_record_store_save();
721 std::byte const* start = reinterpret_cast<std::byte const*>(ptr_in);
722 state.world.deserialize(start, reinterpret_cast<std::byte const*>(section_end), loaded, loadmask);
723 }
724 return section_end;
725}
726
728 // hand-written contribution
729 ptr_in = serialize(ptr_in, state.unit_names);
730 ptr_in = serialize(ptr_in, state.unit_names_indices);
732 ptr_in = memcpy_serialize(ptr_in, state.current_date);
733 ptr_in = memcpy_serialize(ptr_in, state.game_seed);
735 ptr_in = serialize(ptr_in, state.crisis_participants);
736 ptr_in = memcpy_serialize(ptr_in, state.crisis_temperature);
741 ptr_in = memcpy_serialize(ptr_in, state.crisis_war);
743 ptr_in = serialize(ptr_in, state.crisis_defender_wargoals);
744 ptr_in = serialize(ptr_in, state.crisis_attacker_wargoals);
745 ptr_in = memcpy_serialize(ptr_in, state.inflation);
746 ptr_in = serialize(ptr_in, state.great_nations);
747 ptr_in = serialize(ptr_in, state.pending_n_event);
748 ptr_in = serialize(ptr_in, state.pending_f_n_event);
749 ptr_in = serialize(ptr_in, state.pending_p_event);
750 ptr_in = serialize(ptr_in, state.pending_f_p_event);
751 ptr_in = memcpy_serialize(ptr_in, state.pending_messages);
752 ptr_in = memcpy_serialize(ptr_in, state.player_data_cache);
753 ptr_in = serialize(ptr_in, state.future_n_event);
754 ptr_in = serialize(ptr_in, state.future_p_event);
755
756 { // national definitions
758 }
759 { // military definitions
762 }
763
764 // data container contribution
765 dcon::load_record loaded = state.world.make_serialize_record_store_full_save();
766 std::byte* start = reinterpret_cast<std::byte*>(ptr_in);
767 state.world.serialize(start, loaded);
768
769 return reinterpret_cast<uint8_t*>(start);
770}
772 size_t sz = 0;
773
774 // hand-written contribution
775
778 sz += sizeof(state.local_player_nation);
779 sz += sizeof(state.current_date);
780 sz += sizeof(state.game_seed);
781 sz += sizeof(state.current_crisis_state);
783 sz += sizeof(state.crisis_temperature);
784 sz += sizeof(state.primary_crisis_attacker);
785 sz += sizeof(state.primary_crisis_defender);
786 sz += sizeof(state.crisis_state_instance);
787 sz += sizeof(state.crisis_last_checked_gp);
788 sz += sizeof(state.crisis_war);
789 sz += sizeof(state.last_crisis_end_date);
792 sz += sizeof(state.inflation);
798 sz += sizeof(state.pending_messages);
799 sz += sizeof(state.player_data_cache);
802
803 { // national definitions
805 }
806 { // military definitions
809 }
810
811 // data container contribution
812 dcon::load_record loaded = state.world.make_serialize_record_store_full_save();
813 sz += state.world.serialize_size(loaded);
814
815 return sz;
816}
817
820 header.count = count;
821 header.timestamp = uint64_t(std::time(nullptr));
822
823 auto scenario_space = sizeof_scenario_section(state);
824 size_t save_space = sizeof_save_section(state);
825
827 state.scenario_time_stamp = header.timestamp;
828
829
830 // this is an upper bound, since compacting the data may require less space
831 size_t total_size =
833
834 uint8_t* temp_buffer = new uint8_t[total_size];
835 uint8_t* buffer_position = temp_buffer;
836
837 buffer_position = write_scenario_header(buffer_position, header);
838 buffer_position = write_mod_path(buffer_position, simple_fs::extract_state(state.common_fs));
839
840 uint8_t* temp_scenario_buffer = new uint8_t[scenario_space.total_size];
841 auto last_written = write_scenario_section(temp_scenario_buffer, state);
842 auto last_written_count = last_written - temp_scenario_buffer;
843 assert(size_t(last_written_count) == scenario_space.total_size);
844 // calculate checksum
845 checksum_key* checksum = &reinterpret_cast<scenario_header*>(temp_buffer + sizeof(uint32_t))->checksum;
846 blake2b(checksum, sizeof(*checksum), temp_scenario_buffer + scenario_space.checksum_offset, scenario_space.total_size - scenario_space.checksum_offset, nullptr, 0);
847 state.scenario_checksum = *checksum;
848
849 buffer_position = write_compressed_section(buffer_position, temp_scenario_buffer, uint32_t(scenario_space.total_size));
850 delete[] temp_scenario_buffer;
851
852 uint8_t* temp_save_buffer = new uint8_t[save_space];
853 auto last_save_written = write_save_section(temp_save_buffer, state);
854 auto last_save_written_count = last_save_written - temp_save_buffer;
855 assert(size_t(last_save_written_count) == save_space);
856 buffer_position = write_compressed_section(buffer_position, temp_save_buffer, uint32_t(save_space));
857 delete[] temp_save_buffer;
858
859 auto total_size_used = buffer_position - temp_buffer;
860
861 simple_fs::write_file(simple_fs::get_or_create_scenario_directory(), name, reinterpret_cast<char*>(temp_buffer),
862 uint32_t(total_size_used));
863
864 delete[] temp_buffer;
865}
868 auto save_file = open_file(dir, name);
869 if(save_file) {
871 header.version = 0;
872
873 auto contents = simple_fs::view_contents(*save_file);
874 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
875 auto file_end = buffer_pos + contents.file_size;
876
877 if(contents.file_size > sizeof_scenario_header(header)) {
878 buffer_pos = read_scenario_header(buffer_pos, header);
879 }
880
881 if(header.version != sys::scenario_file_version) {
882 return false;
883 }
884
886 state.scenario_time_stamp = header.timestamp;
887 state.scenario_checksum = header.checksum;
890
891 buffer_pos = load_mod_path(buffer_pos, state);
892
893 buffer_pos = with_decompressed_section(buffer_pos,
894 [&](uint8_t const* ptr_in, uint32_t length) { read_scenario_section(ptr_in, ptr_in + length, state); });
895
896 return true;
897 } else {
898 return false;
899 }
900}
901
904 auto save_file = open_file(dir, name);
905 if(save_file) {
907 header.version = 0;
908
909 auto contents = simple_fs::view_contents(*save_file);
910 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
911 auto file_end = buffer_pos + contents.file_size;
912
913 if(contents.file_size > sizeof_scenario_header(header)) {
914 buffer_pos = read_scenario_header(buffer_pos, header);
915 }
916
917 if(header.version != sys::scenario_file_version) {
918 return false;
919 }
920
922 state.scenario_time_stamp = header.timestamp;
923 state.scenario_checksum = header.checksum;
924
927
928 buffer_pos = load_mod_path(buffer_pos, state);
929
930 buffer_pos = with_decompressed_section(buffer_pos,
931 [&](uint8_t const* ptr_in, uint32_t length) { read_scenario_section(ptr_in, ptr_in + length, state); });
932 buffer_pos = with_decompressed_section(buffer_pos,
933 [&](uint8_t const* ptr_in, uint32_t length) { read_save_section(ptr_in, ptr_in + length, state); });
934
935 state.game_seed = uint32_t(std::random_device()());
936
938
939 return true;
940 } else {
941 return false;
942 }
943}
944
947 auto save_file = open_file(dir, name);
948 if(save_file) {
950 header.version = 0;
951
952 auto contents = simple_fs::view_contents(*save_file);
953 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
954 auto file_end = buffer_pos + contents.file_size;
955
956 if(contents.file_size > sizeof_scenario_header(header)) {
957 buffer_pos = read_scenario_header(buffer_pos, header);
958 }
959
960 if(header.version != sys::scenario_file_version) {
961 return false;
962 }
963
965 return false;
966
968
969 buffer_pos = load_mod_path(buffer_pos, state);
970
971 buffer_pos = with_decompressed_section(buffer_pos,
972 [&](uint8_t const* ptr_in, uint32_t length) {
973 // DO NOTHING -- this skips over reading the scenario section
974 });
975 buffer_pos = with_decompressed_section(buffer_pos,
976 [&](uint8_t const* ptr_in, uint32_t length) {
977 read_save_section(ptr_in, ptr_in + length, state);
978 });
979
980 state.game_seed = uint32_t(std::random_device()());
981
982 return true;
983 } else {
984 return false;
985 }
986}
987
988std::string make_time_string(uint64_t value) {
989 std::string result;
990 for(int32_t i = 64 / 4; i --> 0; ) {
991 result += char('a' + (0x0F & (value >> (i * 4))));
992 }
993 return result;
994}
995
996void write_save_file(sys::state& state, save_type type, std::string const& name) {
999 //header.timestamp = state.scenario_time_stamp;
1000 auto time_stamp = std::time(nullptr);
1001 header.timestamp = int64_t(time_stamp);
1002 header.checksum = state.scenario_checksum;
1003 header.tag = state.world.nation_get_identity_from_identity_holder(state.local_player_nation);
1004 header.cgov = state.world.nation_get_government_type(state.local_player_nation);
1006
1007 memcpy(header.save_name, name.c_str(), std::min(name.length(), size_t(31)));
1008 if(name.length() < 31) {
1009 header.save_name[name.length()] = 0;
1010 } else {
1011 header.save_name[31] = 0;
1012 }
1013
1014 size_t save_space = sizeof_save_section(state);
1015
1016 // this is an upper bound, since compacting the data may require less space
1017 size_t total_size = sizeof_save_header(header) + ZSTD_compressBound(save_space) + sizeof(uint32_t) * 2;
1018
1019 uint8_t* temp_buffer = new uint8_t[total_size];
1020 uint8_t* buffer_position = temp_buffer;
1021
1022 buffer_position = write_save_header(buffer_position, header);
1023
1024 uint8_t* temp_save_buffer = new uint8_t[save_space];
1025 write_save_section(temp_save_buffer, state);
1026
1027 buffer_position = write_compressed_section(buffer_position, temp_save_buffer, uint32_t(save_space));
1028 delete[] temp_save_buffer;
1029
1030 auto total_size_used = buffer_position - temp_buffer;
1031
1033
1034 if(type == sys::save_type::autosave) {
1035 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));
1037 } else if(type == sys::save_type::bookmark) {
1038 auto ymd_date = state.current_date.to_ymd(state.start_date);
1039 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";
1040 simple_fs::write_file(sdir, simple_fs::utf8_to_native(base_str), reinterpret_cast<char*>(temp_buffer), uint32_t(total_size_used));
1041 } else {
1042 auto ymd_date = state.current_date.to_ymd(state.start_date);
1043 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";
1044 simple_fs::write_file(sdir, simple_fs::utf8_to_native(base_str), reinterpret_cast<char*>(temp_buffer), uint32_t(total_size_used));
1045 }
1046 delete[] temp_buffer;
1047
1048 state.save_list_updated.store(true, std::memory_order::release); // update for ui
1049
1050
1052 auto data_dumps_directory = simple_fs::get_or_create_data_dumps_directory();
1053
1055 data_dumps_directory,
1056 NATIVE("economy_dump.txt"),
1059 );
1061 data_dumps_directory,
1062 NATIVE("prices_dump.txt"),
1065 );
1067 data_dumps_directory,
1068 NATIVE("demand_dump.txt"),
1071 );
1072 }
1073}
1076 auto save_file = open_file(dir, name);
1077 if(save_file) {
1079 header.version = 0;
1080
1081 auto contents = simple_fs::view_contents(*save_file);
1082 uint8_t const* buffer_pos = reinterpret_cast<uint8_t const*>(contents.data);
1083 auto file_end = buffer_pos + contents.file_size;
1084
1085 if(contents.file_size > sizeof_save_header(header)) {
1086 buffer_pos = read_save_header(buffer_pos, header);
1087 }
1088
1089 if(header.version != sys::save_file_version) {
1090 return false;
1091 }
1092
1093 //if(state.scenario_counter != header.count)
1094 // return false;
1095 //if(state.scenario_time_stamp != header.timestamp)
1096 // return false;
1097 if(!state.scenario_checksum.is_equal(header.checksum))
1098 return false;
1099
1100 state.loaded_save_file = name;
1101
1102 buffer_pos = with_decompressed_section(buffer_pos,
1103 [&](uint8_t const* ptr_in, uint32_t length) { read_save_section(ptr_in, ptr_in + length, state); });
1104
1105 return true;
1106 } else {
1107 return false;
1108 }
1109}
1110
1111} // 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:166
std::vector< uint8_t > diagonal_borders
Definition: map.hpp:163
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:160
uint32_t size_y
Definition: map.hpp:173
uint32_t size_x
Definition: map.hpp:172
std::vector< uint32_t > province_area
Definition: map.hpp:162
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:14
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:152
dcon::cb_type_id uninstall_communist_gov
Definition: military.hpp:158
dcon::unit_type_id base_army_unit
Definition: military.hpp:149
dcon::unit_type_id irregular
Definition: military.hpp:164
tagged_vector< unit_definition, dcon::unit_type_id > unit_base_definitions
Definition: military.hpp:142
dcon::cb_type_id standard_status_quo
Definition: military.hpp:155
dcon::cb_type_id crisis_liberate
Definition: military.hpp:161
dcon::cb_type_id crisis_colony
Definition: military.hpp:160
dcon::cb_type_id standard_great_war
Definition: military.hpp:153
dcon::unit_type_id base_naval_unit
Definition: military.hpp:150
dcon::leader_trait_id first_background_trait
Definition: military.hpp:144
std::vector< fixed_event > on_surrender
Definition: nations.hpp:143
std::vector< fixed_event > on_colony_to_state
Definition: nations.hpp:147
std::vector< fixed_event > on_lost_great_nation
Definition: nations.hpp:145
dcon::modifier_id overseas
Definition: nations.hpp:91
std::vector< fixed_event > on_yearly_pulse
Definition: nations.hpp:139
dcon::modifier_id total_occupation
Definition: nations.hpp:121
dcon::modifier_id total_blockaded
Definition: nations.hpp:122
std::vector< fixed_event > on_civilize
Definition: nations.hpp:153
std::vector< fixed_event > on_debtor_default_small
Definition: nations.hpp:151
std::vector< fixed_event > on_state_conquest
Definition: nations.hpp:148
std::vector< fixed_event > on_election_started
Definition: nations.hpp:156
dcon::modifier_id land_province
Definition: nations.hpp:96
dcon::modifier_id easy_ai
Definition: nations.hpp:86
tagged_vector< dcon::text_key, dcon::national_variable_id > variable_names
Definition: nations.hpp:77
dcon::modifier_id very_hard_ai
Definition: nations.hpp:88
dcon::modifier_id base_values
Definition: nations.hpp:106
dcon::modifier_id generalised_debt_default
Definition: nations.hpp:120
dcon::modifier_id coastal_sea
Definition: nations.hpp:94
dcon::national_identity_id rebel_id
Definition: nations.hpp:79
dcon::modifier_id very_hard_player
Definition: nations.hpp:84
dcon::modifier_id hard_ai
Definition: nations.hpp:87
std::vector< fixed_event > on_election_finished
Definition: nations.hpp:157
dcon::modifier_id nationalism
Definition: nations.hpp:102
std::vector< fixed_province_event > on_battle_won
Definition: nations.hpp:141
dcon::modifier_id debt_default_to
Definition: nations.hpp:112
dcon::modifier_id badboy
Definition: nations.hpp:111
dcon::modifier_id coastal
Definition: nations.hpp:92
tagged_vector< dcon::text_key, dcon::global_flag_id > global_flag_variable_names
Definition: nations.hpp:76
std::vector< fixed_event > on_colony_to_state_free_slaves
Definition: nations.hpp:149
dcon::modifier_id hard_player
Definition: nations.hpp:83
dcon::modifier_id very_easy_ai
Definition: nations.hpp:85
dcon::modifier_id unciv_nation
Definition: nations.hpp:117
std::vector< fixed_event > on_quarterly_pulse
Definition: nations.hpp:140
dcon::modifier_id non_coastal
Definition: nations.hpp:93
dcon::modifier_id in_bankrupcy
Definition: nations.hpp:123
dcon::modifier_id disarming
Definition: nations.hpp:109
dcon::modifier_id easy_player
Definition: nations.hpp:82
dcon::modifier_id bad_debter
Definition: nations.hpp:113
tagged_vector< dcon::text_key, dcon::national_flag_id > flag_variable_names
Definition: nations.hpp:75
dcon::modifier_id civ_nation
Definition: nations.hpp:116
dcon::national_focus_id flashpoint_focus
Definition: nations.hpp:129
dcon::modifier_id plurality
Definition: nations.hpp:119
dcon::modifier_id no_adjacent_controlled
Definition: nations.hpp:98
std::vector< fixed_event > on_debtor_default
Definition: nations.hpp:150
std::vector< fixed_event > on_crisis_declare_interest
Definition: nations.hpp:155
dcon::modifier_id sea_zone
Definition: nations.hpp:95
dcon::modifier_id blockaded
Definition: nations.hpp:97
dcon::modifier_id peace
Definition: nations.hpp:108
std::vector< triggered_modifier > triggered_modifiers
Definition: nations.hpp:71
std::vector< fixed_event > on_my_factories_nationalized
Definition: nations.hpp:154
dcon::modifier_id great_power
Definition: nations.hpp:114
std::vector< fixed_election_event > on_election_tick
Definition: nations.hpp:146
dcon::modifier_id war_exhaustion
Definition: nations.hpp:110
dcon::modifier_id infrastructure
Definition: nations.hpp:103
dcon::modifier_id average_literacy
Definition: nations.hpp:118
dcon::modifier_id second_power
Definition: nations.hpp:115
dcon::modifier_id occupied
Definition: nations.hpp:101
dcon::modifier_id very_easy_player
Definition: nations.hpp:81
dcon::modifier_id has_siege
Definition: nations.hpp:100
dcon::modifier_id core
Definition: nations.hpp:99
std::vector< fixed_event > on_new_great_nation
Definition: nations.hpp:144
std::vector< fixed_event > on_debtor_default_second
Definition: nations.hpp:152
std::vector< fixed_province_event > on_battle_lost
Definition: nations.hpp:142
std::vector< dcon::bitfield_type > global_flag_variables
Definition: nations.hpp:72
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 demand_dump_buffer
bool is_equal(const checksum_key &a) noexcept
Holds important data about the game world, state, and other data regarding windowing,...
uint64_t scenario_time_stamp
text::font_manager font_collection
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
dcon::state_instance_id crisis_state_instance
std::vector< uint16_t > effect_data
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
crisis_state current_crisis_state
cheat_data_s cheat_data
std::vector< sys::full_wg > crisis_defender_wargoals
uint32_t scenario_counter
std::vector< great_nation > great_nations
dcon::war_id crisis_war
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::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< sys::full_wg > crisis_attacker_wargoals
std::vector< uint16_t > trigger_data
float crisis_temperature
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)