Skip to content

Commit 0fe5116

Browse files
committed
refactor version handling and use UE5 version
1 parent 8d5ab14 commit 0fe5116

12 files changed

Lines changed: 110 additions & 43 deletions

File tree

libsave/include/SatisfactorySave/GameTypes/FactoryGame/FGActorSaveHeaderTypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace SatisfactorySave {
1515
void serialize(Archive& ar) {
1616
ar << ClassName;
1717
ar << Reference;
18-
if (ar.getSaveVersion() >= 49) {
18+
if (ar.SaveVersion().get() >= 49) {
1919
ar << ObjectFlags;
2020
}
2121
}

libsave/include/SatisfactorySave/GameTypes/FactoryGame/FGInventoryComponent.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace SatisfactorySave {
1515

1616
void serialize(Archive& ar) {
1717
ar << ItemClass;
18-
if (ar.getSaveVersion() >= 43) {
18+
if (ar.SaveVersion().get() >= 43) {
1919
ar << ItemState;
2020
} else {
2121
ar << LegacyItemStateActor;

libsave/include/SatisfactorySave/GameTypes/FactoryGame/FGLightweightBuildableSubsystem.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ namespace SatisfactorySave {
3333
ar << CustomizationData.PatternRotation;
3434
ar << BuiltWithRecipe;
3535
ar << BlueprintProxy;
36-
if (ar.getLightweightVersion() >= 2) {
36+
if (ar.LightweightVersion().get() >= 2) {
3737
ar << TypeSpecificData;
3838
}
39-
if (ar.getLightweightVersion() >= 3) {
39+
if (ar.LightweightVersion().get() >= 3) {
4040
ar << BuiltBy;
4141
}
4242
}
@@ -49,12 +49,12 @@ namespace SatisfactorySave {
4949

5050
void serialize(Archive& ar) override {
5151
AActor::serialize(ar);
52-
if (ar.getSaveVersion() >= 48) {
52+
if (ar.SaveVersion().get() >= 48) {
5353
ar << currentLightweightVersion;
5454
} else {
5555
currentLightweightVersion = 1;
5656
}
57-
auto lightweight_version_stack_pusher = ar.pushLightweightVersion(currentLightweightVersion);
57+
auto lightweight_version_stack_pusher = ar.LightweightVersion().push(currentLightweightVersion);
5858
ar << mBuildableClassToInstanceArray;
5959
}
6060
};

libsave/include/SatisfactorySave/GameTypes/FactoryGame/Online/PlayerInfoCache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ namespace SatisfactorySave {
1212
int32_t PlayerInfoTableIndex = -1;
1313

1414
void serialize(Archive& ar) {
15-
if (ar.getSaveVersion() >= 57 && ar.getSaveVersion() < 58) {
15+
if (ar.SaveVersion().get() >= 57 && ar.SaveVersion().get() < 58) {
1616
ar << ServiceProvider;
1717
ar << PlayerInfoTableIndex;
1818
}
1919

20-
if (ar.getSaveVersion() >= 57) {
20+
if (ar.SaveVersion().get() >= 57) {
2121
ar << ServiceProvider;
2222
ar << PlayerInfoTableIndex;
2323
} else {

libsave/include/SatisfactorySave/GameTypes/UE/CoreUObject/UObject/Object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace SatisfactorySave {
1818
std::optional<FGuid> Guid;
1919

2020
virtual void serialize(Archive& ar) {
21-
if (ar.getSaveVersion() >= 53) {
21+
if (ar.UE5Version().get() >= 1011) {
2222
/*EClassSerializationControlExtension*/ uint8_t SerializationControl = 0;
2323
ar << SerializationControl;
2424
if (SerializationControl != 0) {

libsave/include/SatisfactorySave/IO/Archive/Archive.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ namespace SatisfactorySave {
4343
template<typename T>
4444
concept IsSerializable = IsSerializableTrait<T>::value;
4545

46+
class SATISFACTORYSAVE_API VersionStack {
47+
public:
48+
inline auto push(auto version) {
49+
return make_stack_guard_push(version_stack_, version);
50+
}
51+
52+
inline int32_t get() {
53+
// Empty version stack should assume "newest" version.
54+
return !version_stack_.empty() ? version_stack_.top() : std::numeric_limits<int32_t>::max();
55+
}
56+
57+
private:
58+
std::stack<int32_t> version_stack_;
59+
};
60+
4661
class SATISFACTORYSAVE_API Archive {
4762
public:
4863
template<typename T>
@@ -131,23 +146,16 @@ namespace SatisfactorySave {
131146
virtual std::size_t tell() = 0;
132147
virtual void seek(std::size_t pos) = 0;
133148

134-
inline auto pushSaveVersion(auto saveVersion) {
135-
return make_stack_guard_push(save_version_stack_, saveVersion);
136-
}
137-
138-
inline int32_t getSaveVersion() {
139-
// Empty version stack should assume "newest" version.
140-
return !save_version_stack_.empty() ? save_version_stack_.top() : std::numeric_limits<int32_t>::max();
149+
inline VersionStack& SaveVersion() {
150+
return save_version_;
141151
}
142152

143-
inline auto pushLightweightVersion(auto lightweightVersion) {
144-
return make_stack_guard_push(lightweight_version_stack_, lightweightVersion);
153+
inline VersionStack& UE5Version() {
154+
return ue5_version_;
145155
}
146156

147-
inline int32_t getLightweightVersion() {
148-
// Empty version stack should assume "newest" version.
149-
return !lightweight_version_stack_.empty() ? lightweight_version_stack_.top()
150-
: std::numeric_limits<int32_t>::max();
157+
inline VersionStack& LightweightVersion() {
158+
return lightweight_version_;
151159
}
152160

153161
inline bool IsPersistent() const {
@@ -168,8 +176,9 @@ namespace SatisfactorySave {
168176
virtual void serializeObjectReference(FObjectReferenceDisc& ref);
169177
virtual void validateReadLimit(std::size_t) {}
170178

171-
std::stack<int32_t> save_version_stack_;
172-
std::stack<int32_t> lightweight_version_stack_;
179+
VersionStack save_version_;
180+
VersionStack ue5_version_;
181+
VersionStack lightweight_version_;
173182
uint8_t ArIsPersistent : 1 = 0;
174183
};
175184
} // namespace SatisfactorySave

libsave/src/GameTypes/Arrays/StructArray.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void SatisfactorySave::StructArray::serialize(Archive& ar) {
4242

4343
int32_t count = inAr.read<int32_t>();
4444

45-
if (ar.getSaveVersion() >= 53) {
45+
if (ar.UE5Version().get() >= 1012) {
4646
if (type_param_.IsEmpty()) {
4747
throw std::runtime_error("Missing FPropertyTypeName in StructArray!");
4848
}
@@ -62,14 +62,14 @@ void SatisfactorySave::StructArray::serialize(Archive& ar) {
6262
Values.emplace_back(Struct::create(inner_tag_.StructName, inAr));
6363
}
6464
auto pos_after = inAr.tell();
65-
if (ar.getSaveVersion() < 53 && pos_after - pos_before != inner_tag_.Size) {
65+
if (ar.UE5Version().get() < 1012 && pos_after - pos_before != inner_tag_.Size) {
6666
throw std::runtime_error("Invalid StructProperty array!");
6767
}
6868
} else {
6969
auto& outAr = dynamic_cast<OStreamArchive&>(ar);
7070

7171
outAr.write(static_cast<int32_t>(Values.size()));
72-
if (ar.getSaveVersion() < 53) {
72+
if (ar.UE5Version().get() < 1012) {
7373
outAr << inner_tag_;
7474
}
7575

@@ -79,7 +79,7 @@ void SatisfactorySave::StructArray::serialize(Archive& ar) {
7979
}
8080
auto pos_after = outAr.tell();
8181

82-
if (ar.getSaveVersion() < 53) {
82+
if (ar.UE5Version().get() < 1012) {
8383
outAr.seek(inner_tag_.SizeOffset);
8484
outAr.write(static_cast<int32_t>(pos_after - pos_before));
8585
outAr.seek(pos_after);

libsave/src/GameTypes/FactoryGame/FGSaveSession.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,51 @@
77

88
void SatisfactorySave::FPerStreamingLevelSaveData::serialize(Archive& ar) {
99
if (ar.isIArchive()) {
10-
SaveVersion = ar.getSaveVersion(); // Default to SaveVersion from header
10+
SaveVersion = ar.SaveVersion().get(); // Default to SaveVersion from header
1111

1212
auto& inAr = dynamic_cast<IStreamArchive&>(ar);
1313
// The game reads TOC and data as buffers, then reads SaveVersion below and then parses the buffers.
1414
// Here, seek and read SaveVersion in advance and then directly parse object data.
15-
if (inAr.getSaveVersion() >= 51) {
15+
if (inAr.SaveVersion().get() >= 51) {
1616
auto pos_before = inAr.tell();
1717
const int64_t TOC_size = inAr.read<int64_t>();
1818
inAr.seek(ar.tell() + TOC_size);
1919
const int64_t data_size = inAr.read<int64_t>();
2020
inAr.seek(ar.tell() + data_size);
2121
inAr << SaveVersion;
22+
if (inAr.SaveVersion().get() >= 53) {
23+
std::vector<FObjectReferenceDisc> Skip_DestroyedActors;
24+
inAr << Skip_DestroyedActors;
25+
inAr << StreamableLevelObjectVersionData;
26+
}
2227
inAr.seek(pos_before);
2328
}
24-
auto save_version_stack_pusher = inAr.pushSaveVersion(SaveVersion);
29+
auto save_version_stack_pusher = inAr.SaveVersion().push(SaveVersion);
30+
std::unique_ptr<StackGuard<int32_t>> ue5_version_stack_pusher;
31+
if (StreamableLevelObjectVersionData.has_value()) {
32+
ue5_version_stack_pusher =
33+
ar.UE5Version().push(StreamableLevelObjectVersionData.value().PackageFileVersion.FileVersionUE5);
34+
}
2535
parseTOCBlob(inAr, SaveObjects, TOC_DestroyedActors);
2636
parseDataBlob(inAr, SaveObjects);
2737
} else {
2838
auto& outAr = dynamic_cast<OStreamArchive&>(ar);
29-
auto save_version_stack_pusher = outAr.pushSaveVersion(SaveVersion);
39+
auto save_version_stack_pusher = outAr.SaveVersion().push(SaveVersion);
40+
std::unique_ptr<StackGuard<int32_t>> ue5_version_stack_pusher;
41+
if (StreamableLevelObjectVersionData.has_value()) {
42+
ue5_version_stack_pusher =
43+
ar.UE5Version().push(StreamableLevelObjectVersionData.value().PackageFileVersion.FileVersionUE5);
44+
}
3045
saveTOCBlob(outAr, SaveObjects, TOC_DestroyedActors);
3146
saveDataBlob(outAr, SaveObjects);
3247
}
33-
if (ar.getSaveVersion() >= 51) {
48+
if (ar.SaveVersion().get() >= 51) {
3449
ar << SaveVersion;
3550
}
3651

3752
ar << DestroyedActors;
3853

39-
if (ar.getSaveVersion() >= 53) {
54+
if (ar.SaveVersion().get() >= 53) {
4055
ar << StreamableLevelObjectVersionData;
4156
}
4257
}

libsave/src/GameTypes/Save/Blueprint.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ SatisfactorySave::Blueprint::Blueprint(const std::filesystem::path& filepath) {
1616
const auto file_data_blob_size = file_data_blob.size();
1717
IStreamArchive ar(std::move(file_data_blob));
1818

19-
auto save_version_stack_pusher = ar.pushSaveVersion(header.SaveVersion);
19+
auto save_version_stack_pusher = ar.SaveVersion().push(header.SaveVersion);
20+
std::unique_ptr<StackGuard<int32_t>> ue5_version_stack_pusher;
21+
if (ar.SaveVersion().get() >= 53) {
22+
ue5_version_stack_pusher = ar.UE5Version().push(header.SaveObjectVersionData.PackageFileVersion.FileVersionUE5);
23+
}
2024

2125
// Validate blob size
2226
if (static_cast<int32_t>(file_data_blob_size - sizeof(int32_t)) != ar.read<int32_t>()) {
@@ -36,7 +40,7 @@ void SatisfactorySave::Blueprint::save(const std::filesystem::path& filepath) {
3640
// Serialize data to blob
3741
OStreamArchive ar;
3842

39-
auto save_version_stack_pusher = ar.pushSaveVersion(header.SaveVersion);
43+
auto save_version_stack_pusher = ar.SaveVersion().push(header.SaveVersion);
4044

4145
// Size placeholder
4246
ar.write<int32_t>(0);

libsave/src/GameTypes/Save/SaveGame.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ SatisfactorySave::SaveGame::SaveGame(const std::filesystem::path& filepath) {
4747
IStreamArchive ar(std::move(file_data_blob));
4848

4949
// Store header SaveVersion as first stack entry.
50-
auto save_version_stack_pusher = ar.pushSaveVersion(mSaveHeader.SaveVersion);
50+
auto save_version_stack_pusher = ar.SaveVersion().push(mSaveHeader.SaveVersion);
51+
// Store UE5 version as first stack entry.
52+
auto ue5_version_stack_pusher = ar.UE5Version().push(1000);
5153

5254
// Validate blob size
5355
if (file_data_blob_size - sizeof(int64_t) != ar.read<int64_t>()) {
5456
throw std::runtime_error("Bad blob size!");
5557
}
5658
TIME_MEASURE_END("toStream");
5759

58-
if (ar.getSaveVersion() >= 53) {
60+
if (ar.SaveVersion().get() >= 53) {
5961
mPersistentLevelSaveObjectVersionData = FSaveObjectVersionData();
6062
ar << mPersistentLevelSaveObjectVersionData.value();
6163
} else {
@@ -71,7 +73,13 @@ SatisfactorySave::SaveGame::SaveGame(const std::filesystem::path& filepath) {
7173
TIME_MEASURE_END("PerLevelData");
7274

7375
TIME_MEASURE_START("PersistentAndRuntimeData");
76+
std::unique_ptr<StackGuard<int32_t>> persistent_level_version_stack_pusher;
77+
if (mPersistentLevelSaveObjectVersionData.has_value()) {
78+
persistent_level_version_stack_pusher =
79+
ar.UE5Version().push(mPersistentLevelSaveObjectVersionData.value().PackageFileVersion.FileVersionUE5);
80+
}
7481
ar << mPersistentAndRuntimeData;
82+
persistent_level_version_stack_pusher.reset();
7583
TIME_MEASURE_END("PersistentAndRuntimeData");
7684

7785
// Parse unresolved data
@@ -94,27 +102,35 @@ void SatisfactorySave::SaveGame::save(const std::filesystem::path& filepath) {
94102
// Serialize data to blob
95103
OStreamArchive ar;
96104

97-
auto save_version_stack_pusher = ar.pushSaveVersion(mSaveHeader.SaveVersion);
105+
auto save_version_stack_pusher = ar.SaveVersion().push(mSaveHeader.SaveVersion);
106+
auto ue5_version_stack_pusher = ar.UE5Version().push(1000);
98107

99108
// Size placeholder
100109
ar.write<int64_t>(0);
101110

102-
if (ar.getSaveVersion() >= 53) {
111+
if (ar.SaveVersion().get() >= 53) {
103112
if (!mPersistentLevelSaveObjectVersionData.has_value()) {
104113
throw std::runtime_error("Missing mPersistentLevelSaveObjectVersionData!");
105114
}
106115
ar << mPersistentLevelSaveObjectVersionData.value();
107116
}
108117
ar << SaveGameValidationData;
109118
ar << mPerLevelDataMap;
119+
std::unique_ptr<StackGuard<int32_t>> persistent_level_version_stack_pusher;
120+
if (mPersistentLevelSaveObjectVersionData.has_value()) {
121+
persistent_level_version_stack_pusher =
122+
ar.UE5Version().push(mPersistentLevelSaveObjectVersionData.value().PackageFileVersion.FileVersionUE5);
123+
}
110124
ar << mPersistentAndRuntimeData;
125+
persistent_level_version_stack_pusher.reset();
111126
ar << mUnresolvedWorldSaveData;
112127

113128
// Store size
114129
auto blob_size = ar.tell();
115130
ar.seek(0);
116131
ar.write(static_cast<int64_t>(blob_size - sizeof(int64_t)));
117132

133+
ue5_version_stack_pusher.reset();
118134
save_version_stack_pusher.reset();
119135

120136
// Write to file

0 commit comments

Comments
 (0)