fixed `Use Remote ZIP Resource`

fixed typo
This commit is contained in:
chinosk 2025-03-20 01:20:24 +00:00
parent 4a77a4fc06
commit b38fabd65b
Signed by: chinosk
GPG Key ID: 00610B08C1BF7BE9
5 changed files with 214 additions and 7 deletions

View File

@ -1240,6 +1240,27 @@ namespace GakumasLocal::HookMain {
return ret;
}
DEFINE_HOOK(void*, WindowHandle_SetWindowLong, (int32_t nIndex, intptr_t dwNewLong, void* mtd)) {
if (nIndex == GWL_STYLE) {
// printf("GWL_STYLE\n");
HWND hwnd = FindWindowW(L"UnityWndClass", L"gakumas");
LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE);
style |= WS_OVERLAPPEDWINDOW;
SetWindowLongPtr(hwnd, GWL_STYLE, style);
dwNewLong = style;
}
return WindowHandle_SetWindowLong_Orig(nIndex, dwNewLong, mtd);
}
DEFINE_HOOK(void*, AspectRatioHandler_WindowProc, (intptr_t hWnd,
uint32_t msg,
intptr_t wParam,
intptr_t lParam, void* mtd)) {
return AspectRatioHandler_WindowProc_Orig(hWnd, msg, wParam, lParam, mtd);
}
void UpdateSwingBreastBonesData(void* initializeData) {
if (!Config::enableBreastParam) return;
@ -1634,6 +1655,11 @@ namespace GakumasLocal::HookMain {
"RenderPipeline", "EndCameraRendering"));
#ifdef GKMS_WINDOWS
ADD_HOOK(WindowHandle_SetWindowLong, Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.Common.StandAloneWindow",
"WindowHandle", "SetWindowLong"));
ADD_HOOK(AspectRatioHandler_WindowProc, Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.Common.StandAloneWindow",
"AspectRatioHandler", "WindowProc"));
g_extra_assetbundle_paths.push_back((gakumasLocalPath / "local-files/gakumasassets").string());
LoadExtraAssetBundle();
GkmsResourceUpdate::CheckUpdateFromAPI(false);

View File

@ -56,7 +56,7 @@ namespace I18nData {
{ "axisx_y", "axisX.y" },
{ "axisy_y", "axisY.y" },
{ "axisz_y", "axisZ.y" },
{ "basic_settings", "Basic Ssettings" },
{ "basic_settings", "Basic Settings" },
{ "graphic_settings", "Graphic Settings" },
{ "camera_settings", "Camera Settings" },
{ "test_mode_live", "Test Mode - LIVE" },

View File

@ -130,13 +130,16 @@ namespace GkmsResourceUpdate {
return content;
}
bool unzipFileFromURL(std::string downloadUrl, const std::string& unzipPath) {
bool unzipFileFromURL(std::string downloadUrl, const std::string& unzipPath, const std::string& targetDir = "") {
std::string tempZipFile = (gakumasLocalPath / "temp_download.zip").string();
if (std::filesystem::exists(tempZipFile)) {
std::filesystem::remove(tempZipFile);
}
if (!DownloadFile(downloadUrl, tempZipFile)) {
GakumasLocal::Log::Error("Download zip file failed.");
return false;
}
if (!UnzipFile(tempZipFile, unzipPath)) {
if (!UnzipFile(tempZipFile, unzipPath, targetDir)) {
GakumasLocal::Log::Error("Unzip file failed.");
return false;
}
@ -214,9 +217,9 @@ namespace GkmsResourceUpdate {
}).detach();
}
void checkUpdateFromURL(std::string downloadUrl) {
std::thread([&downloadUrl]() {
if (unzipFileFromURL(downloadUrl, gakumasLocalPath.string())) {
void checkUpdateFromURL(const std::string& downloadUrl) {
std::thread([downloadUrl]() {
if (unzipFileFromURL(downloadUrl, gakumasLocalPath.string(), "local-files")) {
g_reload_all_data();
GakumasLocal::Log::Info("Update completed.");
}

View File

@ -6,5 +6,5 @@ namespace GkmsResourceUpdate {
void saveProgramConfig();
std::string GetCurrentResourceVersion(bool useCache);
void CheckUpdateFromAPI(bool isManual);
void checkUpdateFromURL(std::string downloadUrl);
void checkUpdateFromURL(const std::string& downloadUrl);
}

View File

@ -147,3 +147,181 @@ static bool UnzipFile(const std::string& zipPath, const std::string& destination
unzClose(zipfile);
return true;
}
static bool UnzipFile(const std::string& zipPath, const std::string& destinationFolder, std::string_view targetDir) {
if (targetDir.empty()) {
return UnzipFile(zipPath, destinationFolder);
}
// 打开 zip 文件
unzFile zipfile = unzOpen(zipPath.c_str());
if (zipfile == nullptr) {
GakumasLocal::Log::ErrorFmt("Can't open zip file: %s", zipPath.c_str());
return false;
}
// 用于标识ZIP 根目录是否直接包含 targetDir 文件夹
bool targetAtRoot = false;
// 如果在根目录下没找到,再尝试记录哪个根目录下包含 targetDir只检查一层
std::string candidateRoot;
// 第一遍扫描:遍历所有条目,判断目标文件夹所在位置
int ret = unzGoToFirstFile(zipfile);
if (ret != UNZ_OK) {
GakumasLocal::Log::ErrorFmt("Can't read first file: %s", zipPath.c_str());
unzClose(zipfile);
return false;
}
do {
char filename[512] = { 0 };
unz_file_info fileInfo{};
ret = unzGetCurrentFileInfo(zipfile, &fileInfo,
filename, sizeof(filename),
nullptr, 0, nullptr, 0);
if (ret != UNZ_OK) {
GakumasLocal::Log::ErrorFmt("Read ZIP File Info Error");
unzClose(zipfile);
return false;
}
std::string entryName = filename;
// 将 '\' 统一替换为 '/'
std::replace(entryName.begin(), entryName.end(), '\\', '/');
// 若条目全名等于 targetDir可以带或不带结尾 '/'),且没有前缀,则认为在根目录
if ((entryName == targetDir || entryName == std::string(targetDir) + "/") &&
entryName.find('/') == entryName.size() - 1) {
targetAtRoot = true;
}
else {
// 对于含有路径分隔符的条目,提取第一级目录
if (auto pos = entryName.find('/'); pos != std::string::npos) {
std::string root = entryName.substr(0, pos);
// remainder 为 root 后面的路径
std::string remainder = entryName.substr(pos + 1);
// 仅检查第一层目录
auto pos2 = remainder.find('/');
std::string firstSubDir = (pos2 != std::string::npos) ? remainder.substr(0, pos2) : remainder;
if (firstSubDir == targetDir) {
candidateRoot = root;
}
}
}
ret = unzGoToNextFile(zipfile);
} while (ret == UNZ_OK);
// 根据扫描结果确定 extractionPrefix
// 若目标文件夹在根目录,则仅解压出 targetDir 内的条目(写入时去掉 targetDir 前缀)
// 否则,若 candidateRoot 不为空,则解压 candidateRoot 内的所有条目(写入时去除 candidateRoot 前缀)
std::string extractionPrefix;
if (targetAtRoot) {
extractionPrefix = std::string(targetDir) + "/";
}
else if (!candidateRoot.empty()) {
extractionPrefix = candidateRoot + "/";
}
else {
GakumasLocal::Log::ErrorFmt("Target directory '%.*s' not found in zip", (int)targetDir.size(), targetDir.data());
unzClose(zipfile);
return false;
}
// 重新打开 zip 文件进行解压(或重置扫描位置)
unzClose(zipfile);
zipfile = unzOpen(zipPath.c_str());
if (zipfile == nullptr) {
GakumasLocal::Log::ErrorFmt("Can't reopen zip file: %s", zipPath.c_str());
return false;
}
ret = unzGoToFirstFile(zipfile);
if (ret != UNZ_OK) {
GakumasLocal::Log::ErrorFmt("Can't read first file: %s", zipPath.c_str());
unzClose(zipfile);
return false;
}
// 第二遍扫描:仅解压属于指定根目录内的条目
do {
char filename[512] = { 0 };
unz_file_info fileInfo{};
ret = unzGetCurrentFileInfo(zipfile, &fileInfo,
filename, sizeof(filename),
nullptr, 0, nullptr, 0);
if (ret != UNZ_OK) {
GakumasLocal::Log::ErrorFmt("Read ZIP File Info Error");
unzClose(zipfile);
return false;
}
std::string entryName = filename;
std::replace(entryName.begin(), entryName.end(), '\\', '/');
// 仅处理以 extractionPrefix 开头的条目
if (entryName.rfind(extractionPrefix, 0) == 0) {
// 去除 extractionPrefix 得到相对路径
std::string relativePath = entryName.substr(extractionPrefix.size());
// 构造输出全路径
std::string fullPath = destinationFolder;
if (!fullPath.empty() && fullPath.back() != '/' && fullPath.back() != '\\')
fullPath += "/";
fullPath += relativePath;
// 如果 relativePath 为空或以 '/' 结尾,认为是目录
if (relativePath.empty() || relativePath.back() == '/') {
if (!CreateDirectoryRecursively(fullPath)) {
GakumasLocal::Log::ErrorFmt("Create Dir Failed: %s", fullPath.c_str());
unzClose(zipfile);
return false;
}
}
else {
// 确保上级目录存在
if (auto pos = fullPath.find_last_of("/\\"); pos != std::string::npos) {
std::string directory = fullPath.substr(0, pos);
if (!CreateDirectoryRecursively(directory)) {
GakumasLocal::Log::ErrorFmt("Create Dir Failed: %s", directory.c_str());
unzClose(zipfile);
return false;
}
}
ret = unzOpenCurrentFile(zipfile);
if (ret != UNZ_OK) {
GakumasLocal::Log::ErrorFmt("Open file in zip failed: %s", entryName.c_str());
unzClose(zipfile);
return false;
}
FILE* outFile = fopen(fullPath.c_str(), "wb");
if (outFile == nullptr) {
GakumasLocal::Log::ErrorFmt("Can't create output file: %s", fullPath.c_str());
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
return false;
}
constexpr int bufferSize = 8192;
std::vector<char> buffer(bufferSize);
int bytesRead = 0;
while ((bytesRead = unzReadCurrentFile(zipfile, buffer.data(), bufferSize)) > 0) {
if (fwrite(buffer.data(), 1, bytesRead, outFile) != static_cast<size_t>(bytesRead)) {
GakumasLocal::Log::ErrorFmt("Write File Error: %s", fullPath.c_str());
fclose(outFile);
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
return false;
}
}
if (bytesRead < 0) {
GakumasLocal::Log::ErrorFmt("Read File Error: %s", entryName.c_str());
fclose(outFile);
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
return false;
}
fclose(outFile);
unzCloseCurrentFile(zipfile);
}
}
ret = unzGoToNextFile(zipfile);
} while (ret == UNZ_OK);
unzClose(zipfile);
return true;
}