11#include " PlayLayer.hpp"
2- #include " sabe.persistenceapi/include/util/Stream.hpp"
2+ #include " UILayer.hpp"
3+
4+ #include < arc/future/UtilPollables.hpp>
5+ #include < sabe.persistenceapi/include/util/Stream.hpp>
36
47void ModPlayLayer::serializeCheckpoints () {
5- if (m_fields->m_loadError != LoadError::None)
8+ if (m_fields->m_currentDiskOperation != DiskOperation::None) {
9+ m_fields->m_serializationQueued = true ;
610 return ;
11+ }
712
8- unsigned int checkpointCount =
9- m_fields-> m_persistentCheckpointArray -> count () ;
13+ if (m_fields-> m_loadError != LoadError::None)
14+ return ;
1015
11- if (checkpointCount == 0 ) {
16+ if (m_fields-> m_persistentCheckpointArray -> count () == 0 ) {
1217 removeCurrentSaveLayer ();
1318 return ;
1419 }
@@ -18,9 +23,17 @@ void ModPlayLayer::serializeCheckpoints() {
1823 return ;
1924#endif
2025
26+ m_fields->m_currentDiskOperation = DiskOperation::Serializing;
27+
28+ CCArrayExt<PersistentCheckpoint*> checkpoints =
29+ CCArrayExt<PersistentCheckpoint*>(
30+ m_fields->m_persistentCheckpointArray ->shallowCopy ()
31+ );
32+
2133 char platform = PLATFORM;
2234 unsigned int saveVersion = CURRENT_VERSION;
2335 gd::string gameVersion = geode::Loader::get ()->getGameVersion ();
36+ unsigned int checkpointCount = checkpoints.size ();
2437
2538 persistenceAPI::Stream stream;
2639 stream.setFile (string::pathToString (getSavePath ()), 2 , true );
@@ -34,32 +47,50 @@ void ModPlayLayer::serializeCheckpoints() {
3447 stream << m_level->m_levelName ;
3548 stream << checkpointCount;
3649
37- for (PersistentCheckpoint* checkpoint : CCArrayExt<PersistentCheckpoint*>(
38- m_fields->m_persistentCheckpointArray
39- ))
40- checkpoint->serializeExternal (stream);
50+ async::spawn (
51+ [&stream, checkpoints] -> arc::Future<> {
52+ for (PersistentCheckpoint* checkpoint : checkpoints) {
53+ co_await arc::yield ();
54+ checkpoint->serializeExternal (stream);
55+ }
4156
42- for (PersistentCheckpoint* checkpoint : CCArrayExt<PersistentCheckpoint*>(
43- m_fields->m_persistentCheckpointArray
44- ))
45- checkpoint->serialize (stream);
57+ for (PersistentCheckpoint* checkpoint : checkpoints) {
58+ co_await arc::yield ();
59+ checkpoint->serialize (stream);
60+ }
61+
62+ stream.end ();
4663
47- stream.end ();
64+ co_return ;
65+ },
66+ []() {
67+ if (ModPlayLayer* playLayer =
68+ static_cast <ModPlayLayer*>(PlayLayer::get ())) {
69+ playLayer->diskOperationFinished ();
70+ static_cast <ModUILayer*>(playLayer->m_uiLayer )->updateSwitcher ();
71+ }
72+ }
73+ );
4874}
4975
5076void ModPlayLayer::deserializeCheckpoints (bool ignoreVerification) {
77+ if (m_fields->m_currentDiskOperation != DiskOperation::None) {
78+ m_fields->m_deserializationQueued = true ;
79+ return ;
80+ }
81+
5182#ifndef PCP_DEBUG
5283 if (m_level->m_levelType == GJLevelType::Editor)
5384 return ;
5485#endif
5586
56- unloadPersistentCheckpoints ();
57- m_fields->m_loadError = LoadError::None;
58-
5987 std::string savePath = string::pathToString (getSavePath ());
6088 if (!std::filesystem::exists (savePath))
6189 return ;
6290
91+ m_fields->m_currentDiskOperation = DiskOperation::Deserializing;
92+ static_cast <ModUILayer*>(m_uiLayer)->updateSwitcher ();
93+
6394 persistenceAPI::Stream stream;
6495 stream.setFile (savePath, 2 );
6596
@@ -68,54 +99,69 @@ void ModPlayLayer::deserializeCheckpoints(bool ignoreVerification) {
6899 if (Mod::get ()->getSettingValue <bool >(" debug-force-fallback" ))
69100 header.loadError = LoadError::ForcedFallback;
70101
71- removeAllCheckpoints ();
72-
73- m_fields->m_loadError = header.loadError ;
74-
75102 if (header.loadError != LoadError::None && !isInFallbackMode ())
76103 return ;
77104
78- for ( unsigned int i = header. checkpointCount ; i > 0 ; i--) {
79- PersistentCheckpoint* checkpoint = PersistentCheckpoint::create () ;
105+ async::spawn ([ignoreVerification, &stream, header] -> arc::Future<> {
106+ SaveHeader localHeader = header ;
80107
81- checkpoint->deserializeExternal (stream, header);
108+ CCArrayExt<PersistentCheckpoint*> checkpoints =
109+ CCArrayExt<PersistentCheckpoint*>(CCArray::create ());
82110
83- checkpoint->setupPhysicalObject ();
84- storePersistentCheckpoint (checkpoint, false );
85- }
111+ for (unsigned int i = localHeader.checkpointCount ; i > 0 ; i--) {
112+ PersistentCheckpoint* checkpoint = PersistentCheckpoint::create ();
86113
87- if (!ignoreVerification) {
88- if (header.loadError != LoadError::None) {
89- stream.end ();
114+ checkpoint->deserializeExternal (stream, localHeader);
90115
91- for (PersistentCheckpoint* checkpoint :
92- CCArrayExt<PersistentCheckpoint*>(
93- m_fields->m_persistentCheckpointArray
94- ))
116+ checkpoint->setupPhysicalObject ();
117+ checkpoints.push_back (checkpoint);
118+ }
95119
96- return ;
120+ auto test = [header, &checkpoints]() {
121+ if (ModPlayLayer* playLayer =
122+ static_cast <ModPlayLayer*>(PlayLayer::get ())) {
123+ playLayer->unloadPersistentCheckpoints ();
124+ for (PersistentCheckpoint* checkpoint : checkpoints)
125+ playLayer->storePersistentCheckpoint (checkpoint, false );
126+
127+ playLayer->m_fields ->m_loadError = header.loadError ;
128+
129+ playLayer->removeAllCheckpoints ();
130+
131+ playLayer->diskOperationFinished ();
132+ playLayer->updateModUI ();
133+ DeserializationFinishedEvent ().send ();
134+ }
135+ };
136+
137+ if (!ignoreVerification) {
138+ if (localHeader.loadError != LoadError::None) {
139+ stream.end ();
140+ geode::queueInMainThread (test);
141+ co_return ;
142+ }
143+ } else {
144+ localHeader.loadError = LoadError::None;
97145 }
98- } else {
99- header.loadError = LoadError::None;
100- }
101146
102- for (PersistentCheckpoint* checkpoint : CCArrayExt<PersistentCheckpoint*>(
103- m_fields->m_persistentCheckpointArray
104- )) {
105- // try {
106- checkpoint->deserialize (stream, header);
107- // } catch (...) { // TODO maybe implement exception logging
108- // unloadPersistentCheckpoints();
109- // log::error("Exception thrown while loading checkpoint");
147+ for (PersistentCheckpoint* checkpoint : checkpoints)
148+ checkpoint->deserialize (stream, localHeader);
110149
111- // stream.end();
150+ stream.end ();
151+ geode::queueInMainThread (test);
152+ co_return ;
153+ });
154+ }
112155
113- // m_fields->m_loadError = LoadError::Crash;
114- // return;
115- // }
156+ void ModPlayLayer::diskOperationFinished () {
157+ m_fields->m_currentDiskOperation = DiskOperation::None;
158+ if (m_fields->m_serializationQueued ) {
159+ m_fields->m_serializationQueued = false ;
160+ serializeCheckpoints ();
161+ } else if (m_fields->m_deserializationQueued ) {
162+ m_fields->m_deserializationQueued = false ;
163+ deserializeCheckpoints ();
116164 }
117-
118- stream.end ();
119165}
120166
121167void ModPlayLayer::unloadPersistentCheckpoints () {
0 commit comments