diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/FileHeader.h | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.World/FileHeader.h')
| -rw-r--r-- | Minecraft.World/FileHeader.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/Minecraft.World/FileHeader.h b/Minecraft.World/FileHeader.h new file mode 100644 index 00000000..203ec322 --- /dev/null +++ b/Minecraft.World/FileHeader.h @@ -0,0 +1,203 @@ +#pragma once +using namespace std; + +#include "System.h" + +// The first 4 bytes is the location of the header (the header itself is at the end of the file) +// Then 4 bytes for the size of the header +// Then 2 bytes for the version number at which this save was first generated +// Then 2 bytes for the version number that the save should now be at +// ( the rest of the header is actually a footer ) +#define SAVE_FILE_HEADER_SIZE 12 + +enum ESaveVersions +{ + // Pre-release version + SAVE_FILE_VERSION_PRE_LAUNCH = 1, + + // This is the version at which we launched the Xbox360 version + SAVE_FILE_VERSION_LAUNCH = 2, + + // This is the version at which we had made changes that broke older saves + SAVE_FILE_VERSION_POST_LAUNCH = 3, + + // This is the version at which we introduced the End, and any saves older than this will have their End data deleted + SAVE_FILE_VERSION_NEW_END = 4, + + // This is the version at which we change the stronghold generation, and any saves older than this should should the original version + SAVE_FILE_VERSION_MOVED_STRONGHOLD = 5, + + // This is the version at which we changed the playeruid format for PS3 + SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE = 6, + + // This is the version at which we changed the playeruid format for Xbox One + SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE = 7, + + // This is the version at which we changed the chunk format to directly save the compressed storage formats + SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE, + + SAVE_FILE_VERSION_NEXT, +}; + +// This is the version at which we changed the playeruid format for Xbox One +#define SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE 7 + +enum ESavePlatform +{ + SAVE_FILE_PLATFORM_NONE = MAKE_FOURCC('N', 'O', 'N', 'E') , + SAVE_FILE_PLATFORM_X360 = MAKE_FOURCC('X', '3', '6', '0') , + SAVE_FILE_PLATFORM_XBONE = MAKE_FOURCC('X', 'B', '1', '_') , + SAVE_FILE_PLATFORM_PS3 = MAKE_FOURCC('P', 'S', '3', '_') , + SAVE_FILE_PLATFORM_PS4 = MAKE_FOURCC('P', 'S', '4', '_') , + SAVE_FILE_PLATFORM_PSVITA = MAKE_FOURCC('P', 'S', 'V', '_') , + SAVE_FILE_PLATFORM_WIN64 = MAKE_FOURCC('W', 'I', 'N', '_') , + +#if defined _XBOX + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_X360 +#elif defined _DURANGO + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_XBONE +#elif defined __PS3__ + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PS3 +#elif defined __ORBIS__ + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PS4 +#elif defined __PSVITA__ + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_PSVITA +#elif defined _WINDOWS64 + SAVE_FILE_PLATFORM_LOCAL = SAVE_FILE_PLATFORM_WIN64 +#endif +}; +#define SAVE_FILE_VERSION_NUMBER (SAVE_FILE_VERSION_NEXT - 1) + +struct FileEntrySaveDataV1 +{ +public: + wchar_t filename[64]; // 64 * 2B + unsigned int length; // In bytes // 4B + + // This is only valid once the save file has been written/loaded at least once + unsigned int startOffset; // 4B +}; + +// It's important that we keep the order and size of the data here to smooth updating +// 4J Stu - As of writing the tutorial level uses a V1 save file +struct FileEntrySaveDataV2 +{ +public: + wchar_t filename[64]; // 64 * 2B + unsigned int length; // In bytes // 4B + + union + { + // This is only valid once the save file has been written/loaded at least once + unsigned int startOffset; // 4B + // 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). + // Note: These won't be read or written as part of a file header, and should only exist wrapped up in a FileEntry class + unsigned int regionIndex; // 4B + + }; + + __int64 lastModifiedTime; // 8B +}; + +typedef FileEntrySaveDataV2 FileEntrySaveData; + +class FileEntry +{ +public: + FileEntrySaveData data; + + unsigned int currentFilePointer; + + FileEntry() { ZeroMemory(&data, sizeof(FileEntrySaveData)); } + + FileEntry( wchar_t name[64], unsigned int length, unsigned int startOffset ) + { + data.length = length; + data.startOffset = startOffset; + memset( &data.filename, 0, sizeof( wchar_t ) * 64 ); + memcpy( &data.filename, name, sizeof( wchar_t ) * 64 ); + + data.lastModifiedTime = 0; + + currentFilePointer = data.startOffset; + } + + unsigned int getFileSize() { return data.length; } + bool isRegionFile() { return data.filename[0] == 0; } // When using ConsoleSaveFileSplit only + unsigned int getRegionFileIndex() { return data.regionIndex; } // When using ConsoleSaveFileSplit only + + void updateLastModifiedTime() { data.lastModifiedTime = System::currentRealTimeMillis(); } + + /* + 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. + Used in a call to std::sort in DirectoryLevelStorage.cpp + */ + static bool newestFirst( FileEntry *a, FileEntry *b ) { return a->data.lastModifiedTime > b->data.lastModifiedTime; } +}; + +// A class the represents the header of the save file +class FileHeader +{ + friend class ConsoleSaveFileOriginal; + friend class ConsoleSaveFileSplit; +private: + vector<FileEntry *> fileTable; + ESavePlatform m_savePlatform; + ByteOrder m_saveEndian; +#if defined(__PS3__) || defined(_XBOX) + static const ByteOrder m_localEndian = BIGENDIAN; +#else + static const ByteOrder m_localEndian = LITTLEENDIAN; +#endif + + short m_saveVersion; + short m_originalSaveVersion; + +public: + FileEntry *lastFile; + +public: + FileHeader(); + ~FileHeader(); + +protected: + FileEntry *AddFile( const wstring &name, unsigned int length = 0 ); + void RemoveFile( FileEntry * ); + void WriteHeader( LPVOID saveMem ); + void ReadHeader( LPVOID saveMem, ESavePlatform plat = SAVE_FILE_PLATFORM_LOCAL ); + + unsigned int GetStartOfNextData(); + + unsigned int GetFileSize(); + + void AdjustStartOffsets(FileEntry *file, DWORD nNumberOfBytesToWrite, bool subtract = false); + + bool fileExists( const wstring &name ); + + vector<FileEntry *> *getFilesWithPrefix(const wstring &prefix); + + vector<FileEntry *> *getValidPlayerDatFiles(); + +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) + wstring getPlayerDataFilenameForLoad(const PlayerUID& pUID); + wstring getPlayerDataFilenameForSave(const PlayerUID& pUID); + vector<FileEntry *> *getDatFilesWithOnlineID(const PlayerUID& pUID); + vector<FileEntry *> *getDatFilesWithMacAndUserID(const PlayerUID& pUID); + vector<FileEntry *> *getDatFilesWithPrimaryUser(); +#endif + + void setSaveVersion(int version) { m_saveVersion = version; } + int getSaveVersion() { return m_saveVersion; } + void setOriginalSaveVersion(int version) { m_originalSaveVersion = version; } + int getOriginalSaveVersion() { return m_originalSaveVersion; } + ESavePlatform getSavePlatform() { return m_savePlatform; } + void setPlatform(ESavePlatform plat) { m_savePlatform = plat; } + bool isSaveEndianDifferent() { return m_saveEndian != m_localEndian; } + void setLocalPlatform() { m_savePlatform = SAVE_FILE_PLATFORM_LOCAL; m_saveEndian = m_localEndian; } + ByteOrder getSaveEndian() { return m_saveEndian; } + static ByteOrder getLocalEndian() { return m_localEndian; } + void setEndian(ByteOrder endian) { m_saveEndian = endian; } + static ByteOrder getEndian(ESavePlatform plat); + bool isLocalEndianDifferent(ESavePlatform plat){return m_localEndian != getEndian(plat); } + +}; |
