Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c0dfd60d5 | |||
| e452788fff | |||
| 1f928fd28a | |||
| fa6861b221 | |||
| 8888cd988b | |||
| 12e01093b0 | |||
| 1ea1801271 | |||
| 91923d445a | |||
| 6ccc93e6f6 |
@@ -66,8 +66,8 @@ jobs:
|
||||
|
||||
- name: Package artifact
|
||||
run: |
|
||||
cd build/targets
|
||||
zip -r ../minecraft-client-linux.zip app --exclude "app/Minecraft.Client.p/*"
|
||||
cd build/targets/app
|
||||
zip -r ../../../minecraft-client-linux.zip . --exclude "./Minecraft.Client.p/*"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
Generated
+9
-9
@@ -3,11 +3,11 @@
|
||||
"4jlibs": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1774836469,
|
||||
"narHash": "sha256-ukp6tLThQugPlREYFDDB6IaunjGte08f0Ler/c8cvaY=",
|
||||
"lastModified": 1774845485,
|
||||
"narHash": "sha256-6lZrYkW0hX5jQDUy0lb2Qtsst3+lMfJviYUVfuNlEzk=",
|
||||
"owner": "4jcraft",
|
||||
"repo": "4jlibs",
|
||||
"rev": "ab37891dabba90cf1e568660f750cebf46ba83f6",
|
||||
"rev": "db73929667eb0607821e38b57d01e6954a7df36d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -62,11 +62,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
|
||||
"lastModified": 1775036866,
|
||||
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
|
||||
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -108,11 +108,11 @@
|
||||
"simdutf": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1773677002,
|
||||
"narHash": "sha256-kq53Jz9zm2bfs8x/74FQbzYrUc+VD7JlnBoYHnEHuSY=",
|
||||
"lastModified": 1775095916,
|
||||
"narHash": "sha256-eKMjANt0fbqemtll6iSiFHwYzGWAsuZoVqOXqXNfodc=",
|
||||
"owner": "simdutf",
|
||||
"repo": "simdutf",
|
||||
"rev": "04a9b596de943ea9e4d4c833e39740edf3c11e88",
|
||||
"rev": "1ac2c2245ce9df6a7d26550e34734882c4a16e9b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/share/4jcraft
|
||||
cp -r Minecraft.Client/. $out/share/4jcraft/
|
||||
cp -r targets/app/. $out/share/4jcraft/
|
||||
|
||||
mkdir -p $out/bin
|
||||
makeWrapper $out/share/4jcraft/Minecraft.Client $out/bin/4jcraft \
|
||||
|
||||
@@ -547,43 +547,13 @@ void UIScene_LoadOrJoinMenu::tick() {
|
||||
m_iState = e_SavesIdle;
|
||||
break;
|
||||
}
|
||||
// 4jcraft: the game literally defaulted to nothing but default buttons
|
||||
// if the game was on a non console / recognized platform.
|
||||
#else
|
||||
if (!m_bSavesDisplayed) {
|
||||
m_pSaveDetails = StorageManager.ReturnSavesInfo();
|
||||
if (m_pSaveDetails != nullptr) {
|
||||
AddDefaultButtons();
|
||||
|
||||
if (m_saveDetails != nullptr) {
|
||||
for (unsigned int i = 0; i < m_iSaveDetailsCount; ++i) {
|
||||
if (m_saveDetails[i].pbThumbnailData != nullptr)
|
||||
delete m_saveDetails[i].pbThumbnailData;
|
||||
}
|
||||
delete[] m_saveDetails;
|
||||
}
|
||||
|
||||
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
|
||||
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
|
||||
|
||||
for (unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) {
|
||||
m_buttonListSaves.addItem(
|
||||
m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
|
||||
|
||||
m_saveDetails[i].saveId = i;
|
||||
memcpy(m_saveDetails[i].UTF8SaveName,
|
||||
m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
|
||||
memcpy(m_saveDetails[i].UTF8SaveFilename,
|
||||
m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename,
|
||||
MAX_SAVEFILENAME_LENGTH);
|
||||
}
|
||||
|
||||
m_bSavesDisplayed = true;
|
||||
m_controlSavesTimer.setVisible(false);
|
||||
UpdateGamesList();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
if (!m_bSavesDisplayed) {
|
||||
AddDefaultButtons();
|
||||
m_bSavesDisplayed = true;
|
||||
m_controlSavesTimer.setVisible(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
// SAVE TRANSFERS
|
||||
}
|
||||
|
||||
@@ -8,14 +8,9 @@
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "util/StringHelpers.h" // 4jcraft TODO
|
||||
#include "platform/PlatformServices.h"
|
||||
#include "java/FileFilter.h"
|
||||
#include "platform/StdFileIO.h"
|
||||
|
||||
const wchar_t File::pathSeparator = L'/';
|
||||
|
||||
@@ -69,11 +64,11 @@ File::File(const std::wstring& pathname) {
|
||||
m_abstractPathName = fixedPath;
|
||||
|
||||
#if defined(__linux__)
|
||||
std::string request = wstringtofilename(m_abstractPathName);
|
||||
std::string request = std::filesystem::path(m_abstractPathName).string();
|
||||
while (!request.empty() && request[0] == '/') request.erase(0, 1);
|
||||
if (request.find("res/") == 0) request.erase(0, 4);
|
||||
|
||||
std::string exeDir = StdFileIO().getBasePath().string();
|
||||
std::string exeDir = PlatformFileIO.getBasePath().string();
|
||||
std::string fileName = request;
|
||||
size_t lastSlash = fileName.find_last_of('/');
|
||||
if (lastSlash != std::string::npos)
|
||||
@@ -83,24 +78,21 @@ File::File(const std::wstring& pathname) {
|
||||
"/Common/res/TitleUpdate/res/",
|
||||
"/Common/Media/",
|
||||
"/Common/res/",
|
||||
"/Common/"};
|
||||
"/Common/",
|
||||
"resources/"};
|
||||
|
||||
for (const char* base : bases) {
|
||||
std::string tryFull = exeDir + base + request;
|
||||
std::string tryFile = exeDir + base + fileName;
|
||||
if (access(tryFull.c_str(), F_OK) != -1) {
|
||||
if (PlatformFileIO.exists(tryFull)) {
|
||||
m_abstractPathName = convStringToWstring(tryFull);
|
||||
return;
|
||||
}
|
||||
if (access(tryFile.c_str(), F_OK) != -1) {
|
||||
if (PlatformFileIO.exists(tryFile)) {
|
||||
m_abstractPathName = convStringToWstring(tryFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 4jcraft: If it's not a core asset, anchor it to the executable directory
|
||||
// so save files don't break
|
||||
m_abstractPathName = convStringToWstring(exeDir + "/" + request);
|
||||
#endif
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
@@ -163,8 +155,7 @@ this->parent = nullptr;
|
||||
// deleted; false otherwise
|
||||
bool File::_delete() {
|
||||
std::error_code error;
|
||||
// 4jcraft: remove all better
|
||||
const bool result = fs::remove_all(ToFilesystemPath(getPath()), error);
|
||||
const bool result = fs::remove(ToFilesystemPath(getPath()), error);
|
||||
if (!result || error) {
|
||||
#ifndef _CONTENT_PACKAGE
|
||||
printf("File::_delete - Error code %d (%#0.8X)\n", error.value(),
|
||||
@@ -410,4 +401,4 @@ int File::hash_fnct(const File& k) {
|
||||
}
|
||||
|
||||
return (int)hashCode;
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void PendingConnection::sendPreLoginResponse() {
|
||||
std::uint8_t ugcXuidCount = 0;
|
||||
std::uint8_t hostIndex = 0;
|
||||
std::uint8_t ugcFriendsOnlyBits = 0;
|
||||
char szUniqueMapName[256]{};
|
||||
char szUniqueMapName[14];
|
||||
|
||||
StorageManager.GetSaveUniqueFilename(szUniqueMapName);
|
||||
|
||||
@@ -241,4 +241,4 @@ std::wstring PendingConnection::getName() {
|
||||
|
||||
bool PendingConnection::isServerPacketListener() { return true; }
|
||||
|
||||
bool PendingConnection::isDisconnected() { return done; }
|
||||
bool PendingConnection::isDisconnected() { return done; }
|
||||
@@ -216,13 +216,11 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
||||
unsigned char* dataIn = dataCompressed + 4;
|
||||
unsigned char* dataInLast = dataCompressed + dataCompressedSize;
|
||||
|
||||
while (dataIn < dataInLast) {
|
||||
while (dataIn != dataInLast) {
|
||||
unsigned char thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn >= dataInLast) break;
|
||||
thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn + 1 >= dataInLast) break;
|
||||
unsigned int runLength = (*dataIn++) << 8;
|
||||
runLength |= (*dataIn++);
|
||||
runLength += 256;
|
||||
@@ -239,6 +237,7 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
||||
if (fileEntry->data.length != uncompressedSize) {
|
||||
// Treat as if it was an empty region file
|
||||
fileEntry->data.length = 0;
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -247,24 +246,21 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
||||
unsigned char* dataIn = dataCompressed + 4;
|
||||
unsigned char* dataInLast = dataCompressed + dataCompressedSize;
|
||||
unsigned char* dataOut = data;
|
||||
unsigned char* dataOutLast = data + fileEntry->data.length;
|
||||
|
||||
while (dataIn < dataInLast && dataOut < dataOutLast) {
|
||||
while (dataIn != dataInLast) {
|
||||
unsigned char thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn >= dataInLast) break;
|
||||
thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn + 1 >= dataInLast) break;
|
||||
unsigned int runLength = (*dataIn++) << 8;
|
||||
runLength |= (*dataIn++);
|
||||
runLength += 256;
|
||||
for (unsigned int i = 0; i < runLength && dataOut < dataOutLast; i++) {
|
||||
for (unsigned int i = 0; i < runLength; i++) {
|
||||
*dataOut++ = 0;
|
||||
}
|
||||
} else {
|
||||
unsigned int runLength = thisByte;
|
||||
for (unsigned int i = 0; i < runLength && dataOut < dataOutLast; i++) {
|
||||
for (unsigned int i = 0; i < runLength; i++) {
|
||||
*dataOut++ = 0;
|
||||
}
|
||||
}
|
||||
@@ -278,6 +274,7 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
||||
free(data);
|
||||
fileEntry->data.length = 0;
|
||||
data = nullptr;
|
||||
assert(0);
|
||||
}
|
||||
// std::int64_t endTime = System::currentTimeMillis();
|
||||
// app.DebugPrintf("Decompressing region file from 0x%.8x %d to %d bytes -
|
||||
@@ -440,7 +437,6 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
||||
// Get details of region files. From this point on we are responsible for
|
||||
// the memory that the storage manager initially allocated for them
|
||||
unsigned int regionCount = PlatformStorage.GetSubfileCount();
|
||||
|
||||
for (unsigned int i = 0; i < regionCount; i++) {
|
||||
unsigned int regionIndex;
|
||||
unsigned char* regionDataCompressed;
|
||||
@@ -450,14 +446,8 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
||||
(void**)®ionDataCompressed,
|
||||
®ionSizeCompressed);
|
||||
|
||||
unsigned char* copiedData = nullptr;
|
||||
if (regionSizeCompressed > 0 && regionDataCompressed) {
|
||||
copiedData = (unsigned char*)malloc(regionSizeCompressed);
|
||||
memcpy(copiedData, regionDataCompressed, regionSizeCompressed);
|
||||
}
|
||||
|
||||
RegionFileReference* regionFileRef = new RegionFileReference(
|
||||
regionIndex, regionIndex, regionSizeCompressed, copiedData);
|
||||
i, regionIndex, regionSizeCompressed, regionDataCompressed);
|
||||
if (regionSizeCompressed > 0) {
|
||||
regionFileRef->Decompress();
|
||||
} else {
|
||||
@@ -503,12 +493,10 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
||||
PlatformStorage.GetSaveData(pvSaveMem, &storageLength);
|
||||
app.DebugPrintf("Filesize - %d, Adjusted size - %d\n", fileSize,
|
||||
storageLength);
|
||||
|
||||
fileSize = storageLength;
|
||||
}
|
||||
|
||||
int compressed = *(int*)pvSaveMem;
|
||||
|
||||
if (compressed == 0) {
|
||||
unsigned int decompSize = *((int*)pvSaveMem + 1);
|
||||
|
||||
@@ -1300,7 +1288,6 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) {
|
||||
|
||||
unsigned int fileSize = header.GetFileSize();
|
||||
|
||||
|
||||
// Assume that the compression will make it smaller so initially attempt to
|
||||
// allocate the current file size We add 4 bytes to the start so that we can
|
||||
// signal compressed data And another 4 bytes to store the decompressed data
|
||||
|
||||
@@ -203,7 +203,6 @@ void FileHeader::ReadHeader(
|
||||
// based PlayerUID
|
||||
// : Bumped it to 8 for Durango v1 when to save the chunks in a
|
||||
// different compressed format
|
||||
case SAVE_FILE_VERSION_CHUNK_INHABITED_TIME:
|
||||
case SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE:
|
||||
case SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE:
|
||||
case SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE:
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
platform_inc = include_directories('.')
|
||||
_threads = dependency('threads')
|
||||
|
||||
lib_platform_core = static_library(
|
||||
'platform_core',
|
||||
files('C4JThread.cpp', 'ShutdownManager.cpp'),
|
||||
include_directories: [platform_inc, include_directories('..')],
|
||||
dependencies: [_threads],
|
||||
cpp_args: global_cpp_args + global_cpp_defs,
|
||||
lib_platform_core = static_library('platform_core',
|
||||
files('C4JThread.cpp', 'ShutdownManager.cpp'),
|
||||
include_directories: [platform_inc, include_directories('..')],
|
||||
dependencies: [_threads],
|
||||
cpp_args: global_cpp_args + global_cpp_defs,
|
||||
)
|
||||
|
||||
platform_dep = declare_dependency(
|
||||
link_with: lib_platform_core,
|
||||
include_directories: platform_inc,
|
||||
link_with: lib_platform_core,
|
||||
include_directories: platform_inc,
|
||||
)
|
||||
|
||||
# SDL2-based platform implementations (formerly 4J.* modules)
|
||||
@@ -19,35 +18,34 @@ _sdl2 = dependency('sdl2')
|
||||
_defs = []
|
||||
|
||||
if get_option('renderer') == 'gles'
|
||||
_gl = dependency('glesv2', required: true)
|
||||
_defs += ['-DGLES']
|
||||
_gl = dependency('glesv2', required: true)
|
||||
_defs += ['-DGLES']
|
||||
else
|
||||
_gl = dependency('gl', required: true)
|
||||
_gl = dependency('gl', required: true)
|
||||
endif
|
||||
|
||||
sdl2_sources = files(
|
||||
'sdl2/Input.cpp',
|
||||
'sdl2/Profile.cpp',
|
||||
'sdl2/Render.cpp',
|
||||
'sdl2/Storage.cpp',
|
||||
'sdl2/render_stubs.cpp',
|
||||
'sdl2/Input.cpp',
|
||||
'sdl2/Profile.cpp',
|
||||
'sdl2/Render.cpp',
|
||||
'sdl2/render_stubs.cpp',
|
||||
'sdl2/Storage.cpp',
|
||||
)
|
||||
|
||||
lib_platform_sdl2 = static_library(
|
||||
'platform_sdl2',
|
||||
sdl2_sources,
|
||||
include_directories: [platform_inc, include_directories('sdl2')],
|
||||
dependencies: [_sdl2, _gl, _threads, glm_dep, stb_dep, java_dep],
|
||||
cpp_args: _defs + global_cpp_args + global_cpp_defs,
|
||||
lib_platform_sdl2 = static_library('platform_sdl2',
|
||||
sdl2_sources,
|
||||
include_directories: [platform_inc, include_directories('sdl2')],
|
||||
dependencies: [_sdl2, _gl, _threads, glm_dep, stb_dep],
|
||||
cpp_args: _defs + global_cpp_args + global_cpp_defs,
|
||||
)
|
||||
|
||||
# Combined dependency: interfaces + SDL2 implementations
|
||||
# Replaces the old render_dep, input_dep, profile_dep, storage_dep
|
||||
render_dep = declare_dependency(
|
||||
link_with: lib_platform_sdl2,
|
||||
include_directories: [platform_inc, include_directories('sdl2')],
|
||||
dependencies: [_sdl2, _gl, _threads, glm_dep],
|
||||
link_with: lib_platform_sdl2,
|
||||
include_directories: [platform_inc, include_directories('sdl2')],
|
||||
dependencies: [_sdl2, _gl, _threads, glm_dep],
|
||||
)
|
||||
input_dep = render_dep
|
||||
profile_dep = render_dep
|
||||
storage_dep = render_dep
|
||||
storage_dep = render_dep
|
||||
|
||||
@@ -1,59 +1,16 @@
|
||||
#include "Storage.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "StdFileIO.h"
|
||||
|
||||
C4JStorage StorageManager;
|
||||
|
||||
static XMARKETPLACE_CONTENTOFFER_INFO s_dummyOffer = {};
|
||||
static XCONTENT_DATA s_dummyContentData = {};
|
||||
|
||||
// def save state
|
||||
// TODO: find a better way
|
||||
static SAVE_DETAILS* s_SavesInfo = nullptr;
|
||||
static std::wstring s_CurrentSaveTitle = L"New World";
|
||||
static std::string s_CurrentSaveFilename = "";
|
||||
static bool s_SaveDisabled = false;
|
||||
|
||||
// Console VFS Memory Blob
|
||||
static std::uint8_t* s_SaveBuffer = nullptr;
|
||||
static unsigned int s_SaveBufferSize = 0;
|
||||
|
||||
struct SubfileData {
|
||||
std::vector<std::uint8_t> data;
|
||||
};
|
||||
|
||||
#include <mutex>
|
||||
static std::map<int, SubfileData> s_Subfiles;
|
||||
static int s_SubfileCounter = 0;
|
||||
static std::mutex s_SubfileMutex;
|
||||
|
||||
// helper functions
|
||||
static StdFileIO s_FileIO;
|
||||
|
||||
static std::filesystem::path GetSavesRoot() {
|
||||
return s_FileIO.getUserDataPath() / "Saves";
|
||||
}
|
||||
|
||||
static std::filesystem::path GetSaveDir(const std::string& saveFilename) {
|
||||
return GetSavesRoot() / saveFilename;
|
||||
}
|
||||
|
||||
static std::filesystem::path GetSaveFile(const std::string& saveFilename,
|
||||
const std::string& filename) {
|
||||
return GetSaveDir(saveFilename) / filename;
|
||||
}
|
||||
C4JStorage::C4JStorage() : m_pStringTable(nullptr) {}
|
||||
|
||||
void C4JStorage::Tick(void) {}
|
||||
@@ -64,7 +21,6 @@ C4JStorage::EMessageResult C4JStorage::RequestMessageBox(
|
||||
std::function<int(int, const C4JStorage::EMessageResult)> callback,
|
||||
C4JStringTable* pStringTable, wchar_t* pwchFormatString,
|
||||
unsigned int focusButton) {
|
||||
if (callback) callback(pad, EMessage_ResultAccept);
|
||||
return EMessage_ResultAccept;
|
||||
}
|
||||
|
||||
@@ -74,7 +30,6 @@ C4JStorage::EMessageResult C4JStorage::GetMessageBoxResult() {
|
||||
|
||||
bool C4JStorage::SetSaveDevice(std::function<int(const bool)> callback,
|
||||
bool bForceResetOfSaveDevice) {
|
||||
if (callback) callback(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,130 +37,48 @@ void C4JStorage::Init(unsigned int uiSaveVersion,
|
||||
const wchar_t* pwchDefaultSaveName, char* pszSavePackName,
|
||||
int iMinimumSaveSize,
|
||||
std::function<int(const ESavingMessage, int)> callback,
|
||||
const char* szGroupID) {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(GetSavesRoot(), ec);
|
||||
}
|
||||
|
||||
void C4JStorage::ResetSaveData() {
|
||||
s_CurrentSaveTitle = L"New World";
|
||||
s_CurrentSaveFilename = "";
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
s_SubfileCounter = 0;
|
||||
}
|
||||
if (s_SaveBuffer) {
|
||||
free(s_SaveBuffer);
|
||||
s_SaveBuffer = nullptr;
|
||||
}
|
||||
s_SaveBufferSize = 0;
|
||||
}
|
||||
|
||||
const char* szGroupID) {}
|
||||
void C4JStorage::ResetSaveData() {}
|
||||
void C4JStorage::SetDefaultSaveNameForKeyboardDisplay(
|
||||
const wchar_t* pwchDefaultSaveName) {
|
||||
if (pwchDefaultSaveName) s_CurrentSaveTitle = pwchDefaultSaveName;
|
||||
}
|
||||
|
||||
void C4JStorage::SetSaveTitle(const wchar_t* pwchDefaultSaveName) {
|
||||
if (pwchDefaultSaveName) s_CurrentSaveTitle = pwchDefaultSaveName;
|
||||
|
||||
if (s_CurrentSaveFilename.empty()) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "sv%06X",
|
||||
(unsigned int)(time(NULL) & 0xFFFFFF));
|
||||
s_CurrentSaveFilename = buf;
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(GetSaveDir(s_CurrentSaveFilename),
|
||||
ec);
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t* pwchDefaultSaveName) {}
|
||||
void C4JStorage::SetSaveTitle(const wchar_t* pwchDefaultSaveName) {}
|
||||
bool C4JStorage::GetSaveUniqueNumber(int* piVal) {
|
||||
if (piVal) *piVal = 1; // she turned a 0 to a 1 now the world explodes
|
||||
if (piVal) *piVal = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C4JStorage::GetSaveUniqueFilename(char* pszName) {
|
||||
if (pszName) {
|
||||
strncpy(pszName, s_CurrentSaveFilename.c_str(),
|
||||
MAX_SAVEFILENAME_LENGTH - 1);
|
||||
pszName[MAX_SAVEFILENAME_LENGTH - 1] = '\0';
|
||||
}
|
||||
if (pszName) pszName[0] = '\0';
|
||||
return true;
|
||||
}
|
||||
void C4JStorage::SetSaveUniqueFilename(char* szFilename) {
|
||||
if (szFilename) s_CurrentSaveFilename = szFilename;
|
||||
}
|
||||
void C4JStorage::SetSaveUniqueFilename(char* szFilename) {}
|
||||
void C4JStorage::SetState(ESaveGameControlState eControlState,
|
||||
std::function<int(const bool)> callback) {
|
||||
if (callback) callback(true);
|
||||
}
|
||||
void C4JStorage::SetSaveDisabled(bool bDisable) { s_SaveDisabled = bDisable; }
|
||||
bool C4JStorage::GetSaveDisabled(void) { return s_SaveDisabled; }
|
||||
void* C4JStorage::AllocateSaveData(unsigned int uiBytes) {
|
||||
if (s_SaveBuffer) free(s_SaveBuffer);
|
||||
s_SaveBuffer = (std::uint8_t*)malloc(uiBytes);
|
||||
s_SaveBufferSize = uiBytes;
|
||||
return s_SaveBuffer;
|
||||
}
|
||||
std::function<int(const bool)> callback) {}
|
||||
void C4JStorage::SetSaveDisabled(bool bDisable) {}
|
||||
bool C4JStorage::GetSaveDisabled(void) { return false; }
|
||||
unsigned int C4JStorage::GetSaveSize() { return 0; }
|
||||
void C4JStorage::GetSaveData(void* pvData, unsigned int* puiBytes) {
|
||||
if (puiBytes) *puiBytes = s_SaveBufferSize;
|
||||
if (pvData && s_SaveBuffer) memcpy(pvData, s_SaveBuffer, s_SaveBufferSize);
|
||||
if (puiBytes) *puiBytes = 0;
|
||||
}
|
||||
void* C4JStorage::AllocateSaveData(unsigned int uiBytes) {
|
||||
return malloc(uiBytes);
|
||||
}
|
||||
unsigned int C4JStorage::GetSaveSize() { return s_SaveBufferSize; }
|
||||
void C4JStorage::SetSaveImages(std::uint8_t* pbThumbnail,
|
||||
unsigned int thumbnailBytes,
|
||||
std::uint8_t* pbImage, unsigned int imageBytes,
|
||||
std::uint8_t* pbTextData,
|
||||
unsigned int textDataBytes) {
|
||||
if (pbThumbnail && thumbnailBytes > 0 && !s_CurrentSaveFilename.empty()) {
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(dir, ec);
|
||||
s_FileIO.writeFile(dir / "thumbnail.png", pbThumbnail, thumbnailBytes);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int textDataBytes) {}
|
||||
C4JStorage::ESaveGameState C4JStorage::SaveSaveData(
|
||||
std::function<int(const bool)> callback) {
|
||||
if (s_CurrentSaveFilename.empty()) {
|
||||
if (callback) callback(false);
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(dir, ec);
|
||||
|
||||
// vfs blob -> disk
|
||||
if (s_SaveBuffer && s_SaveBufferSize > 0)
|
||||
s_FileIO.writeFile(dir / "savegame.dat", s_SaveBuffer,
|
||||
s_SaveBufferSize);
|
||||
|
||||
// save... title.. in txt... they do that.. honestly
|
||||
// i would wrap world info in a json.
|
||||
// but i'm not rewriting the whole
|
||||
// save -> storage system sooooooo nope!
|
||||
std::string titleStr(s_CurrentSaveTitle.begin(), s_CurrentSaveTitle.end());
|
||||
s_FileIO.writeFile(dir / "title.txt", titleStr.data(), titleStr.size());
|
||||
|
||||
if (callback) callback(true);
|
||||
return ESaveGame_Save;
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
void C4JStorage::CopySaveDataToNewSave(std::uint8_t* pbThumbnail,
|
||||
unsigned int cbThumbnail,
|
||||
wchar_t* wchNewName,
|
||||
std::function<int(bool)> callback) {
|
||||
if (callback) callback(false);
|
||||
}
|
||||
|
||||
std::function<int(bool)> callback) {}
|
||||
void C4JStorage::SetSaveDeviceSelected(unsigned int uiPad, bool bSelected) {}
|
||||
bool C4JStorage::GetSaveDeviceSelected(unsigned int iPad) { return true; }
|
||||
C4JStorage::ESaveGameState C4JStorage::DoesSaveExist(bool* pbExists) {
|
||||
if (pbExists)
|
||||
*pbExists = s_FileIO.exists(GetSaveDir(s_CurrentSaveFilename));
|
||||
if (pbExists) *pbExists = false;
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
bool C4JStorage::EnoughSpaceForAMinSaveGame() { return true; }
|
||||
@@ -214,87 +87,16 @@ C4JStorage::ESaveGameState C4JStorage::GetSavesInfo(
|
||||
int iPad,
|
||||
std::function<int(SAVE_DETAILS* pSaveDetails, const bool)> callback,
|
||||
char* pszSavePackName) {
|
||||
ClearSavesInfo();
|
||||
|
||||
auto savesRoot = GetSavesRoot();
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(savesRoot, ec);
|
||||
|
||||
std::vector<std::string> saveDirs;
|
||||
|
||||
for (const auto& entry :
|
||||
std::filesystem::directory_iterator(savesRoot, ec)) {
|
||||
if (!entry.is_directory()) continue;
|
||||
|
||||
std::string name = entry.path().filename().string();
|
||||
bool hasSave = s_FileIO.exists(entry.path() / "savegame.dat") ||
|
||||
s_FileIO.exists(entry.path() / "subfile_0.dat") ||
|
||||
s_FileIO.exists(entry.path() / "title.txt");
|
||||
|
||||
if (hasSave) saveDirs.push_back(name);
|
||||
}
|
||||
|
||||
s_SavesInfo = new SAVE_DETAILS();
|
||||
s_SavesInfo->iSaveC = (int)saveDirs.size();
|
||||
|
||||
if (s_SavesInfo->iSaveC > 0) {
|
||||
s_SavesInfo->SaveInfoA = new SAVE_INFO[s_SavesInfo->iSaveC];
|
||||
for (size_t i = 0; i < saveDirs.size(); ++i) {
|
||||
SAVE_INFO& info = s_SavesInfo->SaveInfoA[i];
|
||||
memset(&info, 0, sizeof(SAVE_INFO));
|
||||
|
||||
strncpy(info.UTF8SaveFilename, saveDirs[i].c_str(),
|
||||
MAX_SAVEFILENAME_LENGTH - 1);
|
||||
|
||||
auto titleData =
|
||||
s_FileIO.readFileToVec(GetSaveFile(saveDirs[i], "title.txt"));
|
||||
if (!titleData.empty()) {
|
||||
std::string title(titleData.begin(), titleData.end());
|
||||
strncpy(info.UTF8SaveTitle, title.c_str(),
|
||||
MAX_DISPLAYNAME_LENGTH - 1);
|
||||
} else {
|
||||
strncpy(info.UTF8SaveTitle, saveDirs[i].c_str(),
|
||||
MAX_DISPLAYNAME_LENGTH - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_SavesInfo->SaveInfoA = nullptr;
|
||||
}
|
||||
|
||||
if (callback) callback(s_SavesInfo, true);
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
|
||||
PSAVE_DETAILS C4JStorage::ReturnSavesInfo() { return s_SavesInfo; }
|
||||
|
||||
void C4JStorage::ClearSavesInfo() {
|
||||
if (s_SavesInfo) {
|
||||
if (s_SavesInfo->SaveInfoA) {
|
||||
for (int i = 0; i < s_SavesInfo->iSaveC; ++i) {
|
||||
if (s_SavesInfo->SaveInfoA[i].thumbnailData)
|
||||
delete[] s_SavesInfo->SaveInfoA[i].thumbnailData;
|
||||
}
|
||||
delete[] s_SavesInfo->SaveInfoA;
|
||||
}
|
||||
delete s_SavesInfo;
|
||||
s_SavesInfo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PSAVE_DETAILS C4JStorage::ReturnSavesInfo() { return nullptr; }
|
||||
void C4JStorage::ClearSavesInfo() {}
|
||||
C4JStorage::ESaveGameState C4JStorage::LoadSaveDataThumbnail(
|
||||
PSAVE_INFO pSaveInfo,
|
||||
std::function<int(std::uint8_t* thumbnailData, unsigned int thumbnailBytes)>
|
||||
std::function<int(std::uint8_t* thumbnailData,
|
||||
unsigned int thumbnailBytes)>
|
||||
callback) {
|
||||
if (pSaveInfo) {
|
||||
auto data = s_FileIO.readFileToVec(
|
||||
GetSaveFile(pSaveInfo->UTF8SaveFilename, "thumbnail.png"));
|
||||
if (!data.empty()) {
|
||||
if (callback) callback(data.data(), (unsigned int)data.size());
|
||||
return (C4JStorage::ESaveGameState)4;
|
||||
}
|
||||
}
|
||||
if (callback) callback(nullptr, 0);
|
||||
return (C4JStorage::ESaveGameState)4;
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
void C4JStorage::GetSaveCacheFileInfo(unsigned int fileIndex,
|
||||
XCONTENT_DATA& xContentData) {
|
||||
@@ -307,63 +109,14 @@ void C4JStorage::GetSaveCacheFileInfo(unsigned int fileIndex,
|
||||
if (pImageBytes) *pImageBytes = 0;
|
||||
}
|
||||
C4JStorage::ESaveGameState C4JStorage::LoadSaveData(
|
||||
PSAVE_INFO pSaveInfo, std::function<int(const bool, const bool)> callback) {
|
||||
if (pSaveInfo) {
|
||||
s_CurrentSaveFilename = pSaveInfo->UTF8SaveFilename;
|
||||
std::string title(pSaveInfo->UTF8SaveTitle);
|
||||
s_CurrentSaveTitle = std::wstring(title.begin(), title.end());
|
||||
|
||||
auto blobData = s_FileIO.readFileToVec(
|
||||
GetSaveFile(s_CurrentSaveFilename, "savegame.dat"));
|
||||
if (!blobData.empty()) {
|
||||
if (s_SaveBuffer) free(s_SaveBuffer);
|
||||
s_SaveBufferSize = (unsigned int)blobData.size();
|
||||
s_SaveBuffer = (std::uint8_t*)malloc(s_SaveBufferSize);
|
||||
memcpy(s_SaveBuffer, blobData.data(), s_SaveBufferSize);
|
||||
|
||||
}
|
||||
|
||||
// put in mem
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
int maxIndex = -1;
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
for (const auto& entry : std::filesystem::directory_iterator(dir, ec)) {
|
||||
if (!entry.is_regular_file()) continue;
|
||||
std::string filename = entry.path().filename().string();
|
||||
if (filename.find("subfile_") == 0 && filename.find(".dat") == filename.size() - 4) {
|
||||
try {
|
||||
int i = std::stoi(filename.substr(8, filename.size() - 12));
|
||||
auto subData = s_FileIO.readFileToVec(entry.path());
|
||||
if (!subData.empty()) {
|
||||
SubfileData sd;
|
||||
sd.data = std::move(subData);
|
||||
s_Subfiles[i] = std::move(sd);
|
||||
if (i > maxIndex) maxIndex = i;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
}
|
||||
s_SubfileCounter = maxIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (callback) callback(false, true);
|
||||
return (C4JStorage::ESaveGameState)1;
|
||||
PSAVE_INFO pSaveInfo,
|
||||
std::function<int(const bool, const bool)> callback) {
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
C4JStorage::ESaveGameState C4JStorage::DeleteSaveData(
|
||||
PSAVE_INFO pSaveInfo, std::function<int(const bool)> callback) {
|
||||
bool success = false;
|
||||
if (pSaveInfo) {
|
||||
std::error_code ec;
|
||||
std::filesystem::remove_all(GetSaveDir(pSaveInfo->UTF8SaveFilename),
|
||||
ec);
|
||||
success = !ec;
|
||||
}
|
||||
if (callback) callback(success);
|
||||
return (C4JStorage::ESaveGameState)3;
|
||||
PSAVE_INFO pSaveInfo,
|
||||
std::function<int(const bool)> callback) {
|
||||
return ESaveGame_Idle;
|
||||
}
|
||||
void C4JStorage::RegisterMarketplaceCountsCallback(
|
||||
std::function<int(C4JStorage::DLC_TMS_DETAILS*, int)> callback) {}
|
||||
@@ -371,7 +124,6 @@ void C4JStorage::SetDLCPackageRoot(char* pszDLCRoot) {}
|
||||
C4JStorage::EDLCStatus C4JStorage::GetDLCOffers(
|
||||
int iPad, std::function<int(int, std::uint32_t, int)> callback,
|
||||
std::uint32_t dwOfferTypesBitmask) {
|
||||
if (callback) callback(0, dwOfferTypesBitmask, iPad);
|
||||
return EDLC_NoOffers;
|
||||
}
|
||||
unsigned int C4JStorage::CancelGetDLCOffers() { return 0; }
|
||||
@@ -438,71 +190,32 @@ unsigned int C4JStorage::CRC(unsigned char* buf, int len) {
|
||||
unsigned int crc = 0xFFFFFFFF;
|
||||
for (int i = 0; i < len; i++) {
|
||||
crc ^= buf[i];
|
||||
for (int j = 0; j < 8; j++)
|
||||
for (int j = 0; j < 8; j++) {
|
||||
crc = (crc >> 1) ^ (0xEDB88320 & (-(crc & 1)));
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
// that fucking bird that i hate
|
||||
int C4JStorage::AddSubfile(int regionIndex) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles[regionIndex] = SubfileData();
|
||||
if (regionIndex >= s_SubfileCounter) {
|
||||
s_SubfileCounter = regionIndex + 1;
|
||||
}
|
||||
return regionIndex;
|
||||
(void)regionIndex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int C4JStorage::GetSubfileCount() {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
return s_Subfiles.size();
|
||||
}
|
||||
|
||||
unsigned int C4JStorage::GetSubfileCount() { return 0; }
|
||||
void C4JStorage::GetSubfileDetails(unsigned int i, int* regionIndex,
|
||||
void** data, unsigned int* size) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
auto it = s_Subfiles.begin();
|
||||
unsigned int index = 0;
|
||||
while (it != s_Subfiles.end() && index < i) {
|
||||
++it;
|
||||
++index;
|
||||
}
|
||||
if (it != s_Subfiles.end()) {
|
||||
if (regionIndex) *regionIndex = it->first;
|
||||
if (data) *data = it->second.data.data();
|
||||
if (size) *size = (unsigned int)it->second.data.size();
|
||||
} else {
|
||||
if (regionIndex) *regionIndex = 0;
|
||||
if (data) *data = nullptr;
|
||||
if (size) *size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void C4JStorage::ResetSubfiles() {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
s_SubfileCounter = 0;
|
||||
(void)i;
|
||||
if (regionIndex) *regionIndex = 0;
|
||||
if (data) *data = 0;
|
||||
if (size) *size = 0;
|
||||
}
|
||||
void C4JStorage::ResetSubfiles() {}
|
||||
void C4JStorage::UpdateSubfile(int index, void* data, unsigned int size) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
SubfileData& sd = s_Subfiles[index]; // inserts if missing
|
||||
sd.data.resize(size);
|
||||
memcpy(sd.data.data(), data, size);
|
||||
(void)index;
|
||||
(void)data;
|
||||
(void)size;
|
||||
}
|
||||
void C4JStorage::SaveSubfiles(std::function<int(const bool)> callback) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
if (!s_CurrentSaveFilename.empty() && !s_Subfiles.empty()) {
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(dir, ec);
|
||||
|
||||
for (const auto& pair : s_Subfiles) {
|
||||
s_FileIO.writeFile(
|
||||
dir / ("subfile_" + std::to_string(pair.first) + ".dat"),
|
||||
pair.second.data.data(), pair.second.data.size());
|
||||
}
|
||||
}
|
||||
if (callback) callback(true);
|
||||
}
|
||||
C4JStorage::ESaveGameState C4JStorage::GetSaveState() { return ESaveGame_Idle; }
|
||||
|
||||
Reference in New Issue
Block a user