@@ -36,7 +36,7 @@ namespace DataManager
3636 };
3737
3838 const std::unordered_map<DMMiscKey, std::string_view> MISC_KEY_TO_NAME{
39- { DMMiscKey::GD_LIST_ID, " gdListID " },
39+ { DMMiscKey::GD_LIST_ID, " gd-list-id " },
4040 };
4141
4242 struct SavedArrayInfo
@@ -56,6 +56,52 @@ namespace DataManager
5656 };
5757 }
5858
59+ namespace
60+ {
61+ const auto saveDataPath = geode::Mod::get()->getSaveDir () / "save_data";
62+
63+ GameState readGameState ()
64+ {
65+ GameState fromDisk;
66+ std::ifstream saveDataFile (saveDataPath, std::ios::binary);
67+ saveDataFile.read (reinterpret_cast <char *>(&fromDisk), sizeof (GameState));
68+
69+ // TODO: Add checksum and integrity check here or something
70+
71+ return fromDisk;
72+ }
73+
74+ GameState writeGameStateSafe (bool force_clean = false )
75+ {
76+ std::ifstream saveDataFileIn (saveDataPath, std::ios::binary);
77+ saveDataFileIn.seekg (0 , std::ios::end);
78+
79+ if (force_clean || saveDataFileIn.fail () || saveDataFileIn.tellg () != sizeof (GameState))
80+ {
81+ GameState defaultValue;
82+
83+ std::ofstream saveDataFileOut (saveDataPath, std::ios::binary);
84+ saveDataFileOut.write (reinterpret_cast <char *>(&defaultValue), sizeof (GameState));
85+
86+ return defaultValue;
87+ }
88+
89+ GameState fromDisk;
90+ saveDataFileIn.seekg (0 );
91+ saveDataFileIn.read (reinterpret_cast <char *>(&fromDisk), sizeof (GameState));
92+
93+ return fromDisk;
94+ }
95+
96+ void writeGameState (const GameState& value)
97+ {
98+ std::ofstream (saveDataPath, std::ios::binary).write (
99+ reinterpret_cast <const char *>(&value),
100+ sizeof (GameState)
101+ );
102+ }
103+ }
104+
59105 namespace traits
60106 {
61107 template <DMMiscKey K>
@@ -122,17 +168,6 @@ namespace DataManager
122168 template <DMMiscKey key>
123169 [[nodiscard]] traits::KeyTrait<key>::type get ()
124170 {
125- using value_t = typename traits::KeyTrait<key>::type;
126-
127- if constexpr (key == DMMiscKey::SAVE_DATA)
128- {
129- value_t fromDisk;
130- std::ifstream saveDataFile (geode::Mod::get ()->getSaveDir () / " save_data" , std::ios::binary);
131- saveDataFile.read (reinterpret_cast <char *>(&fromDisk), sizeof (value_t ));
132-
133- return fromDisk;
134- }
135-
136171 return setDefaultSafe<key>();
137172 }
138173
@@ -173,17 +208,9 @@ namespace DataManager
173208 void set (const typename traits::KeyTrait<key>::type& value)
174209 {
175210 if constexpr (key == DMMiscKey::SAVE_DATA)
176- {
177- std::ofstream saveDataFile (geode::Mod::get ()->getSaveDir () / " save_data" );
178- saveDataFile.write (
179- reinterpret_cast <const char *>(&value),
180- sizeof (typename traits::KeyTrait<key>::type)
181- );
182- }
211+ writeGameState (value);
183212 else
184- {
185213 geode::Mod::get ()->setSavedValue (values::MISC_KEY_TO_NAME.at (key), value);
186- }
187214 }
188215
189216
@@ -223,26 +250,7 @@ namespace DataManager
223250 using save_container_t = std::conditional_t <std::is_same_v<value_t , int >, uint64_t , value_t >;
224251
225252 if constexpr (key == DMMiscKey::SAVE_DATA)
226- {
227- std::ifstream saveDataFileIn (geode::Mod::get ()->getSaveDir () / " save_data" , std::ios::binary);
228- saveDataFileIn.seekg (0 , std::ios::end);
229-
230- if (saveDataFileIn.fail () || saveDataFileIn.tellg () != sizeof (value_t ))
231- {
232- value_t defaultValue;
233-
234- std::ofstream saveDataFileOut (geode::Mod::get ()->getSaveDir () / " save_data" , std::ios::binary);
235- saveDataFileOut.write (reinterpret_cast <char *>(&defaultValue), sizeof (value_t ));
236-
237- return defaultValue;
238- }
239-
240- value_t fromDisk;
241- saveDataFileIn.seekg (0 );
242- saveDataFileIn.read (reinterpret_cast <char *>(&fromDisk), sizeof (value_t ));
243-
244- return fromDisk;
245- }
253+ return writeGameStateSafe ();
246254 else
247255 {
248256 auto & container = geode::Mod::get ()->getSaveContainer ();
0 commit comments