Skip to content

Commit 865b37d

Browse files
committed
Experiment
Signed-off-by: Kevadroz <kevinfdezdominguez@gmail.com>
1 parent bd71395 commit 865b37d

6 files changed

Lines changed: 142 additions & 60 deletions

File tree

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ else()
88
endif()
99
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
1010

11+
# set(ARC_FEATURE_NET ON CACHE BOOL "" FORCE)
12+
# set(ARC_FEATURE_TIME ON CACHE BOOL "" FORCE)
13+
# set(ARC_FEATURE_SIGNAL ON CACHE BOOL "" FORCE)
14+
# set(ARC_FEATURE_DEBUG ON CACHE BOOL "" FORCE)
15+
1116
project(PracticeCheckpointPermanence VERSION 1.0.0)
1217

1318
# Add all source files inside src (recursively)

src/Hooks/PlayLayer.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,29 @@
77
using namespace geode::prelude;
88
using namespace persistenceAPI;
99

10+
// Copied from PlatformerSaves
11+
#if defined(GEODE_IS_WINDOWS)
12+
#define UNIQUE_ID_OFFSET 0x6ba158
13+
#elif defined(GEODE_IS_ANDROID64)
14+
#define UNIQUE_ID_OFFSET 0x11fe018
15+
#elif defined(GEODE_IS_ANDROID32)
16+
#define UNIQUE_ID_OFFSET 0xa9f00c
17+
#elif defined(GEODE_IS_ARM_MAC)
18+
#define UNIQUE_ID_OFFSET 0x8aa39c
19+
#elif defined(GEODE_IS_INTEL_MAC)
20+
#define UNIQUE_ID_OFFSET 0x985500
21+
#elif defined(GEODE_IS_IOS)
22+
#define UNIQUE_ID_OFFSET 0x83f2e8
23+
#endif
24+
25+
enum class DiskOperation { None, Serializing, Deserializing };
26+
1027
class $modify(ModPlayLayer, PlayLayer) {
1128
struct Fields {
29+
DiskOperation m_currentDiskOperation = DiskOperation::None;
30+
bool m_serializationQueued = false;
31+
bool m_deserializationQueued = false;
32+
1233
bool m_startedLoadingObjects = false;
1334
LoadError m_loadError = LoadError::None;
1435
bool m_hasAttemptedToLoadCheckpoints = false;
@@ -53,6 +74,7 @@ class $modify(ModPlayLayer, PlayLayer) {
5374
// Data
5475
void serializeCheckpoints();
5576
void deserializeCheckpoints(bool ignoreVerification = false);
77+
void diskOperationFinished();
5678
void unloadPersistentCheckpoints();
5779
void resave();
5880

@@ -94,3 +116,9 @@ class $modify(ModPlayLayer, PlayLayer) {
94116
log::warn("Failed to set PlayLayer::setupHasCompleted hook priority!");
95117
}
96118
};
119+
120+
class DeserializationFinishedEvent
121+
: public Event<DeserializationFinishedEvent, void()> {
122+
public:
123+
using Event::Event;
124+
};

src/Hooks/PlayLayerCheckpoints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ void ModPlayLayer::markPersistentCheckpoint() {
122122
checkpoint->storeData(createCheckpoint(), this);
123123
unsigned int newCheckpointIndex =
124124
storePersistentCheckpoint(checkpoint, true) + 1;
125-
serializeCheckpoints();
126125

127126
if (m_isPracticeMode) {
128127
switchGhostCheckpoint(newCheckpointIndex);
@@ -135,6 +134,7 @@ void ModPlayLayer::markPersistentCheckpoint() {
135134
if (m_fields->m_persistentCheckpointArray->count() == 1)
136135
updateSaveLayerCount();
137136

137+
serializeCheckpoints();
138138
updateModUI();
139139
}
140140

src/Hooks/PlayLayerData.cpp

Lines changed: 98 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
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

47
void 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

5076
void 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

121167
void ModPlayLayer::unloadPersistentCheckpoints() {

src/Hooks/PlayLayerSaveLayers.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ void ModPlayLayer::previousSaveLayer() {
2323
}
2424

2525
void ModPlayLayer::switchCurrentSaveLayer(unsigned int saveLayer) {
26+
if (m_fields->m_currentDiskOperation == DiskOperation::Serializing)
27+
return;
28+
2629
updateSaveLayerCount();
2730

2831
m_fields->m_activeSaveLayer =
2932
std::clamp(saveLayer, (unsigned int)0, m_fields->m_saveLayerCount);
3033

3134
deserializeCheckpoints();
32-
updateModUI();
3335
}
3436

3537
void ModPlayLayer::removeCurrentSaveLayer() {
@@ -58,7 +60,6 @@ void ModPlayLayer::removeCurrentSaveLayer() {
5860

5961
updateSaveLayerCount();
6062
deserializeCheckpoints();
61-
updateModUI();
6263
}
6364

6465
void ModPlayLayer::swapSaveLayers(unsigned int left, unsigned int right) {

src/UI/CheckpointManager.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ bool CheckpointManager::init() {
4040
CCSprite::createWithSpriteFrameName("GJ_deleteBtn_001.png");
4141
m_deleteButton = CCMenuItemExt::createSpriteExtra(
4242
deleteSprite, [this, playLayer](CCMenuItemSpriteExtra* deleteButton) {
43-
if (playLayer->m_fields->m_persistentCheckpointArray->count() > 0 ||
44-
playLayer->m_fields->m_loadError != LoadError::None)
43+
if ((playLayer->m_fields->m_persistentCheckpointArray->count() > 0 ||
44+
playLayer->m_fields->m_loadError != LoadError::None) &&
45+
playLayer->m_fields->m_currentDiskOperation == DiskOperation::None)
4546
geode::createQuickPopup(
4647
"Delete All",
4748
"Delete all saved checkpoints for this layer?\n"
@@ -214,6 +215,10 @@ bool CheckpointManager::init() {
214215
m_buttonMenu->addChildAtPosition(m_forceLoadButton, geode::Anchor::Bottom);
215216
m_buttonMenu->addChildAtPosition(m_errorButton, geode::Anchor::TopRight);
216217

218+
addEventListener(DeserializationFinishedEvent(), [this]() {
219+
updateUIElements();
220+
});
221+
217222
return true;
218223
}
219224

@@ -580,9 +585,6 @@ void CheckpointManager::forceLoadPopup() {
580585

581586
playLayer->deserializeCheckpoints(true);
582587
playLayer->serializeCheckpoints();
583-
584-
updateUIElements();
585-
playLayer->updateModUI();
586588
}
587589
}
588590
);

0 commit comments

Comments
 (0)