the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#pragma once
2using namespace std;
3
4#include "System.h"
5
6// The first 4 bytes is the location of the header (the header itself is at the end of the file)
7// Then 4 bytes for the size of the header
8// Then 2 bytes for the version number at which this save was first generated
9// Then 2 bytes for the version number that the save should now be at
10// ( the rest of the header is actually a footer )
11#define SAVE_FILE_HEADER_SIZE 12
12
13enum ESaveVersions
14{
15 // Pre-release version
16 SAVE_FILE_VERSION_PRE_LAUNCH = 1,
17
18 // This is the version at which we launched the Xbox360 version
19 SAVE_FILE_VERSION_LAUNCH = 2,
20
21 // This is the version at which we had made changes that broke older saves
22 SAVE_FILE_VERSION_POST_LAUNCH = 3,
23
24 // This is the version at which we introduced the End, and any saves older than this will have their End data deleted
25 SAVE_FILE_VERSION_NEW_END = 4,
26
27 // This is the version at which we change the stronghold generation, and any saves older than this should should the original version
28 SAVE_FILE_VERSION_MOVED_STRONGHOLD = 5,
29
30 // This is the version at which we changed the playeruid format for PS3
31 SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE = 6,
32
33 // This is the version at which we changed the playeruid format for Xbox One
34 SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE = 7,
35
36 // This is the version at which we changed the chunk format to directly save the compressed storage formats
37 SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE,
38
39 // This is the version at which we added inhabited time to chunk (1.6.4)
40 SAVE_FILE_VERSION_CHUNK_INHABITED_TIME,
41
42
43 // 4J Stu - If you add a new version here, the save conversion tool will also need updated to be able to read this new format
44
45 SAVE_FILE_VERSION_NEXT,
46};
47
48// This is the version at which we changed the playeruid format for Xbox One
49#define SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE 7
50
51enum ESavePlatform
52{
53 SAVE_FILE_PLATFORM_NONE = MAKE_FOURCC('N', 'O', 'N', 'E') ,
54 SAVE_FILE_PLATFORM_X360 = MAKE_FOURCC('X', '3', '6', '0') ,
55 SAVE_FILE_PLATFORM_XBONE = MAKE_FOURCC('X', 'B', '1', '_') ,
56 SAVE_FILE_PLATFORM_PS3 = MAKE_FOURCC('P', 'S', '3', '_') ,
57 SAVE_FILE_PLATFORM_PS4 = MAKE_FOURCC('P', 'S', '4', '_') ,
58 SAVE_FILE_PLATFORM_PSVITA = MAKE_FOURCC('P', 'S', 'V', '_') ,
59 SAVE_FILE_PLATFORM_WIN64 = MAKE_FOURCC('W', 'I', 'N', '_') ,
60
61#if defined _XBOX
62 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_X360
63#elif defined _DURANGO
64 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_XBONE
65#elif defined __PS3__
66 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PS3
67#elif defined __ORBIS__
68 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PS4
69#elif defined __PSVITA__
70 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PSVITA
71#elif defined _WINDOWS64
72 SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_WIN64
73#endif
74};
75#define SAVE_FILE_VERSION_NUMBER (SAVE_FILE_VERSION_NEXT - 1)
76
77struct FileEntrySaveDataV1
78{
79public:
80 wchar_t filename[64]; // 64 * 2B
81 unsigned int length; // In bytes // 4B
82
83 // This is only valid once the save file has been written/loaded at least once
84 unsigned int startOffset; // 4B
85};
86
87// It's important that we keep the order and size of the data here to smooth updating
88// 4J Stu - As of writing the tutorial level uses a V1 save file
89struct FileEntrySaveDataV2
90{
91public:
92 wchar_t filename[64]; // 64 * 2B
93 unsigned int length; // In bytes // 4B
94
95 union
96 {
97 // This is only valid once the save file has been written/loaded at least once
98 unsigned int startOffset; // 4B
99 // For region files stored via ConsolveSaveFileSplit, these aren't stored within the normal save file, identified by not having a name (filename[0] is 0).
100 // Note: These won't be read or written as part of a file header, and should only exist wrapped up in a FileEntry class
101 unsigned int regionIndex; // 4B
102
103 };
104
105 __int64 lastModifiedTime; // 8B
106};
107
108typedef FileEntrySaveDataV2 FileEntrySaveData;
109
110class FileEntry
111{
112public:
113 FileEntrySaveData data;
114
115 unsigned int currentFilePointer;
116
117 FileEntry() { ZeroMemory(&data, sizeof(FileEntrySaveData)); }
118
119 FileEntry( wchar_t name[64], unsigned int length, unsigned int startOffset )
120 {
121 data.length = length;
122 data.startOffset = startOffset;
123 memset( &data.filename, 0, sizeof( wchar_t ) * 64 );
124 memcpy( &data.filename, name, sizeof( wchar_t ) * 64 );
125
126 data.lastModifiedTime = 0;
127
128 currentFilePointer = data.startOffset;
129 }
130
131 unsigned int getFileSize() { return data.length; }
132 bool isRegionFile() { return data.filename[0] == 0; } // When using ConsoleSaveFileSplit only
133 unsigned int getRegionFileIndex() { return data.regionIndex; } // When using ConsoleSaveFileSplit only
134
135 void updateLastModifiedTime() { data.lastModifiedTime = System::currentRealTimeMillis(); }
136
137 /*
138 Comparison function object that returns true if the first argument goes before the second argument in the specific strict weak ordering it defines, and false otherwise.
139 Used in a call to std::sort in DirectoryLevelStorage.cpp
140 */
141 static bool newestFirst( FileEntry *a, FileEntry *b ) { return a->data.lastModifiedTime > b->data.lastModifiedTime; }
142};
143
144// A class the represents the header of the save file
145class FileHeader
146{
147 friend class ConsoleSaveFileOriginal;
148 friend class ConsoleSaveFileSplit;
149private:
150 vector<FileEntry *> fileTable;
151 ESavePlatform m_savePlatform;
152 ByteOrder m_saveEndian;
153#if defined(__PS3__) || defined(_XBOX)
154 static const ByteOrder m_localEndian = BIGENDIAN;
155#else
156 static const ByteOrder m_localEndian = LITTLEENDIAN;
157#endif
158
159 short m_saveVersion;
160 short m_originalSaveVersion;
161
162public:
163 FileEntry *lastFile;
164
165public:
166 FileHeader();
167 ~FileHeader();
168
169protected:
170 FileEntry *AddFile( const wstring &name, unsigned int length = 0 );
171 void RemoveFile( FileEntry * );
172 void WriteHeader( LPVOID saveMem );
173 void ReadHeader( LPVOID saveMem, ESavePlatform plat = SAVE_FILE_PLATFORM_LOCAL );
174
175 unsigned int GetStartOfNextData();
176
177 unsigned int GetFileSize();
178
179 void AdjustStartOffsets(FileEntry *file, DWORD nNumberOfBytesToWrite, bool subtract = false);
180
181 bool fileExists( const wstring &name );
182
183 vector<FileEntry *> *getFilesWithPrefix(const wstring &prefix);
184
185 vector<FileEntry *> *getValidPlayerDatFiles();
186
187#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__)
188 wstring getPlayerDataFilenameForLoad(const PlayerUID& pUID);
189 wstring getPlayerDataFilenameForSave(const PlayerUID& pUID);
190 vector<FileEntry *> *getDatFilesWithOnlineID(const PlayerUID& pUID);
191 vector<FileEntry *> *getDatFilesWithMacAndUserID(const PlayerUID& pUID);
192 vector<FileEntry *> *getDatFilesWithPrimaryUser();
193#endif
194
195 void setSaveVersion(int version) { m_saveVersion = version; }
196 int getSaveVersion() { return m_saveVersion; }
197 void setOriginalSaveVersion(int version) { m_originalSaveVersion = version; }
198 int getOriginalSaveVersion() { return m_originalSaveVersion; }
199 ESavePlatform getSavePlatform() { return m_savePlatform; }
200 void setPlatform(ESavePlatform plat) { m_savePlatform = plat; }
201 bool isSaveEndianDifferent() { return m_saveEndian != m_localEndian; }
202 void setLocalPlatform() { m_savePlatform = SAVE_FILE_PLATFORM_LOCAL; m_saveEndian = m_localEndian; }
203 ByteOrder getSaveEndian() { return m_saveEndian; }
204 static ByteOrder getLocalEndian() { return m_localEndian; }
205 void setEndian(ByteOrder endian) { m_saveEndian = endian; }
206 static ByteOrder getEndian(ESavePlatform plat);
207 bool isLocalEndianDifferent(ESavePlatform plat){return m_localEndian != getEndian(plat); }
208
209};