From 7fd77ddc55836e9a0f1ae1969edde0ec13628f8a Mon Sep 17 00:00:00 2001 From: Soggy_Pancake <54160598+Soggy-Pancake@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:01:45 -0700 Subject: [PATCH] FileTexturePack is now functional and loads from a zip file in ./resourcepacks --- Minecraft.Client/FileTexturePack.cpp | 153 +++++++++++++++++++++++++-- Minecraft.Client/FileTexturePack.h | 19 +++- 2 files changed, 160 insertions(+), 12 deletions(-) diff --git a/Minecraft.Client/FileTexturePack.cpp b/Minecraft.Client/FileTexturePack.cpp index af58dc1e..7f260d1d 100644 --- a/Minecraft.Client/FileTexturePack.cpp +++ b/Minecraft.Client/FileTexturePack.cpp @@ -1,12 +1,44 @@ #include "stdafx.h" #include "FileTexturePack.h" +#include "TexturePackRepository.h" +#include "..\Minecraft.World\StringHelpers.h" FileTexturePack::FileTexturePack(DWORD id, File *file, TexturePack *fallback) : AbstractTexturePack(id, file, file->getName(), fallback) { // 4J Stu - These calls need to be in the most derived version of the class + loadZipFile(file); + if (!zipFile) { + return; + } + + if (id) + this->id = id; + + loadColourTable(); loadIcon(); - loadName(); + loadName(file); loadDescription(); + checkTexSize(); +} + + +DLCPack* FileTexturePack::getDLCPack() +{ + return NULL; +} + +bool FileTexturePack::hasAudio() { // todo - add audio replacement support + return false; +} + +bool FileTexturePack::hasData() +{ + return !_iconData.empty() && zipFile != nullptr; +} + +bool FileTexturePack::isLoadingData() +{ + return false; } void FileTexturePack::unload(Textures *textures) @@ -24,8 +56,35 @@ void FileTexturePack::unload(Textures *textures) #endif } -InputStream *FileTexturePack::getResourceImplementation(const wstring &name) //throws IOException -{ +wstring FileTexturePack::getAnimationString(const wstring& textureName, const wstring& path, bool allowFallback) { + // copy paste of base class method, except I return null and check for existence in getResource + // so it is fine to skip checking if the file exists and this allows a decent speedup + + std::wstring result = L""; + InputStream* fileStream = getResource(L"\\" + path + textureName + L".txt", true); + + if (fileStream) { + InputStreamReader isr(fileStream); + BufferedReader br(&isr); + + wstring line = br.readLine(); + while (!line.empty()) + { + line = trimString(line); + if (line.length() > 0) + { + result.append(L","); + result.append(line); + } + line = br.readLine(); + } + delete fileStream; + } + + return result; +} + +InputStream *FileTexturePack::getResourceImplementation(const wstring &name) { #if 0 loadZipFile(); @@ -36,7 +95,13 @@ InputStream *FileTexturePack::getResourceImplementation(const wstring &name) //t return zipFile.getInputStream(entry); #endif - return NULL; + app.DebugPrintf("ZIP: resource - %ls\n", name.c_str()); + + auto entry = zipFile->getEntry(&name); + if (entry) { + return zipFile->getInputStream(entry.get()); + } + return nullptr; } bool FileTexturePack::hasFile(const wstring &name) @@ -49,19 +114,89 @@ bool FileTexturePack::hasFile(const wstring &name) } catch (Exception e) { return false; } +#endif +#if (defined _WIN64) + + + return zipFile->hasFile(&name); #endif return false; } -void FileTexturePack::loadZipFile() //throws IOException +BufferedImage* FileTexturePack::getImageResource(const wstring& file, bool filenameHasExtension, bool bTitleUpdateTexture, const wstring& drive){ + app.DebugPrintf("ZIP: image - %ls\n", file.c_str()); + + if (file == L"terrain.png" && terrainAtlas.get() != nullptr) + return terrainAtlas.release(); + + if (file == L"items.png" && itemAtlas.get() != nullptr) + return itemAtlas.release(); + + std::wstring f = file; + auto it = AbstractTexturePack::INDEXED_TO_JAVA_MAP.find(L"res/" + file); + if (it != INDEXED_TO_JAVA_MAP.end()) { + f = L"assets/minecraft/textures/" + it->second; + } + + auto folderSep = file.find_last_of(L"/") + 1; + auto find = file.find(L"res/"); + if (folderSep != file.npos && file.find(L"res/") == 0) + f = file.substr(folderSep, file.length() - folderSep); + + //f = L"assets/minecraft/textures/" + f; + auto imageData = zipFile->extract(&f); + if (!imageData.empty()) { + auto image = new BufferedImage(imageData.data(), imageData.size()); + return image; + } + + app.DebugPrintf("ZIP: failed to find %ls fetching from default\n", file.c_str()); + + TexturePackRepository* repo = Minecraft::GetInstance()->skins; + return repo->getDefault()->getImageResource(file, filenameHasExtension, bTitleUpdateTexture); +} + +void FileTexturePack::loadIcon() { + if (zipFile->hasFile("pack.png")) { + app.DebugPrintf("Found pack.png in zip file, loading as icon\n"); + // auto zipFileEntry = zipFile->getEntry(&std::wstring(L"pack.png")); + _iconData = zipFile->extract(&std::wstring(L"pack.png")); + if (!_iconData.empty()) { + iconImage = new BufferedImage(_iconData.data(), _iconData.size()); + m_iconData = _iconData.data(); + m_iconSize = _iconData.size(); + } else + app.DebugPrintf("Failed to load pack.png from zip file\n"); + } +} + +PBYTE FileTexturePack::getPackIcon(DWORD& dwImageBytes) { + if (_iconData.empty()) loadIcon(); + if (!_iconData.empty()) { + dwImageBytes = m_iconSize; + return _iconData.data(); + } + return NULL; +} + +void FileTexturePack::loadName(File *file) { + std::wstring name = file->getName(); + int pathSep = max(name.find_last_of('/'), name.find_last_of('\\')) + 1; + int extSep = name.find_last_of('.'); + if (extSep < 0) { + extSep = name.length(); + } + name = name.substr(pathSep, extSep - pathSep); + texname = name; +} + +void FileTexturePack::loadZipFile(File* file) //throws IOException { -#if 0 - if (zipFile != null) { + if (file == NULL || file->getName() == L"") { return; } - zipFile = new ZipFile(file); -#endif + zipFile = std::make_unique(file); } bool FileTexturePack::isTerrainUpdateCompatible() diff --git a/Minecraft.Client/FileTexturePack.h b/Minecraft.Client/FileTexturePack.h index 85221d11..c7927f3d 100644 --- a/Minecraft.Client/FileTexturePack.h +++ b/Minecraft.Client/FileTexturePack.h @@ -1,5 +1,6 @@ #pragma once #include "AbstractTexturePack.h" +#include "../Minecraft.World/ZipFile.h" //class ZipFile; class BufferedImage; class File; @@ -9,23 +10,35 @@ using namespace std; class FileTexturePack : public AbstractTexturePack { private: - //ZipFile *zipFile; + std::unique_ptr zipFile; + std::vector _iconData; + DWORD id; + bool _hasAudio; public: FileTexturePack(DWORD id, File *file, TexturePack *fallback); //@Override void unload(Textures *textures); + DLCPack* getDLCPack(); + bool hasAudio(); + bool hasData(); + void loadIcon(); + PBYTE getPackIcon(DWORD& dwImageBytes); + void loadName(File *file); + bool isLoadingData(); + wstring getAnimationString(const wstring& textureName, const wstring& path, bool allowFallback); protected: - InputStream *getResourceImplementation(const wstring &name); //throws IOException + InputStream* getResourceImplementation(const wstring& name); public: //@Override bool hasFile(const wstring &name); + BufferedImage* getImageResource(const wstring& File, bool filenameHasExtension = false, bool bTitleUpdateTexture = false, const wstring& drive = L""); private: - void loadZipFile(); //throws IOException + void loadZipFile(File* file); public: bool isTerrainUpdateCompatible();