mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-17 19:22:29 +00:00
Implement ZipFile and ZipEntry
This commit is contained in:
parent
976dcc07ef
commit
4e91d5ca4c
|
|
@ -160,20 +160,11 @@ public:
|
||||||
void dispose() {}
|
void dispose() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ZipEntry
|
class ZipEntry;
|
||||||
{
|
|
||||||
};
|
|
||||||
class InputStream;
|
class InputStream;
|
||||||
|
|
||||||
class File;
|
class File;
|
||||||
class ZipFile
|
class ZipFile;
|
||||||
{
|
|
||||||
public:
|
|
||||||
ZipFile(File *file) {}
|
|
||||||
InputStream *getInputStream(ZipEntry *entry) { return NULL; }
|
|
||||||
ZipEntry *getEntry(const wstring& name) {return NULL;}
|
|
||||||
void close() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImageIO
|
class ImageIO
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3441,6 +3441,8 @@
|
||||||
<ClInclude Include="ConsoleSaveFileIO.h" />
|
<ClInclude Include="ConsoleSaveFileIO.h" />
|
||||||
<ClInclude Include="ConsoleSaveFileOutputStream.h" />
|
<ClInclude Include="ConsoleSaveFileOutputStream.h" />
|
||||||
<ClInclude Include="ConsoleSavePath.h" />
|
<ClInclude Include="ConsoleSavePath.h" />
|
||||||
|
<ClInclude Include="ZipEntry.h" />
|
||||||
|
<ClInclude Include="ZipFile.h" />
|
||||||
<ClInclude Include="Zombie.h" />
|
<ClInclude Include="Zombie.h" />
|
||||||
<ClInclude Include="WaterAnimal.h" />
|
<ClInclude Include="WaterAnimal.h" />
|
||||||
<ClInclude Include="ZonedChunkStorage.h" />
|
<ClInclude Include="ZonedChunkStorage.h" />
|
||||||
|
|
@ -4793,6 +4795,8 @@
|
||||||
<ClCompile Include="WorkbenchTile.cpp" />
|
<ClCompile Include="WorkbenchTile.cpp" />
|
||||||
<ClCompile Include="ConsoleSaveFileInputStream.cpp" />
|
<ClCompile Include="ConsoleSaveFileInputStream.cpp" />
|
||||||
<ClCompile Include="ConsoleSaveFileOutputStream.cpp" />
|
<ClCompile Include="ConsoleSaveFileOutputStream.cpp" />
|
||||||
|
<ClCompile Include="ZipEntry.cpp" />
|
||||||
|
<ClCompile Include="ZipFile.cpp" />
|
||||||
<ClCompile Include="Zombie.cpp" />
|
<ClCompile Include="Zombie.cpp" />
|
||||||
<ClCompile Include="WaterAnimal.cpp" />
|
<ClCompile Include="WaterAnimal.cpp" />
|
||||||
<ClCompile Include="ZonedChunkStorage.cpp">
|
<ClCompile Include="ZonedChunkStorage.cpp">
|
||||||
|
|
|
||||||
|
|
@ -3197,6 +3197,12 @@
|
||||||
<ClInclude Include="FireworksMenu.h">
|
<ClInclude Include="FireworksMenu.h">
|
||||||
<Filter>net\minecraft\world\inventory</Filter>
|
<Filter>net\minecraft\world\inventory</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ZipEntry.h">
|
||||||
|
<Filter>ConsoleJavaLibs</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ZipFile.h">
|
||||||
|
<Filter>ConsoleJavaLibs</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
|
@ -5626,5 +5632,11 @@
|
||||||
<ClCompile Include="EmptyMapItem.cpp">
|
<ClCompile Include="EmptyMapItem.cpp">
|
||||||
<Filter>net\minecraft\world\item</Filter>
|
<Filter>net\minecraft\world\item</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="ZipEntry.cpp">
|
||||||
|
<Filter>ConsoleJavaLibs</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ZipFile.cpp">
|
||||||
|
<Filter>ConsoleJavaLibs</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
27
Minecraft.World/ZipEntry.cpp
Normal file
27
Minecraft.World/ZipEntry.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "ZipEntry.h"
|
||||||
|
|
||||||
|
ZipEntry::ZipEntry(bit7z::BitArchiveItemOffset itemInfo) : _itemInfo(itemInfo) {
|
||||||
|
_name = itemInfo.name();
|
||||||
|
_path = itemInfo.path();
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD ZipEntry::getSize() {
|
||||||
|
return _itemInfo.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipEntry::isDir() {
|
||||||
|
return _itemInfo.isDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ZipEntry::getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ZipEntry::path() {
|
||||||
|
return _path;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ZipEntry::getIndex() {
|
||||||
|
return (unsigned int)_itemInfo.index();
|
||||||
|
}
|
||||||
20
Minecraft.World/ZipEntry.h
Normal file
20
Minecraft.World/ZipEntry.h
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../Minecraft.Client/Common/libs/bit7z/include/bitarchivereader.hpp"
|
||||||
|
|
||||||
|
class ZipEntry {
|
||||||
|
private:
|
||||||
|
bit7z::BitArchiveItemOffset _itemInfo;
|
||||||
|
|
||||||
|
// caching for faster load times
|
||||||
|
std::string _name;
|
||||||
|
std::string _path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ZipEntry(bit7z::BitArchiveItemOffset itemInfo);
|
||||||
|
DWORD getSize();
|
||||||
|
bool isDir();
|
||||||
|
bool isFile() { return !isDir(); }
|
||||||
|
std::string getName();
|
||||||
|
std::string path();
|
||||||
|
unsigned int getIndex();
|
||||||
|
};
|
||||||
140
Minecraft.World/ZipFile.cpp
Normal file
140
Minecraft.World/ZipFile.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "ZipFile.h"
|
||||||
|
|
||||||
|
// static library
|
||||||
|
bit7z::Bit7zLibrary* ZipFile::_library;
|
||||||
|
|
||||||
|
ZipFile::ZipFile(File* file) {
|
||||||
|
if (file != NULL && file->exists()) {
|
||||||
|
open(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZipFile::ZipFile(std::string name) {
|
||||||
|
File file(convStringToWstring(name));
|
||||||
|
if (file.exists()) {
|
||||||
|
open(&file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::wstring> ZipFile::listFiles() {
|
||||||
|
std::vector<std::wstring> files;
|
||||||
|
files.reserve(_fileCache.size());
|
||||||
|
|
||||||
|
for (auto item : _fileCache) {
|
||||||
|
files.emplace_back(item.first);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns -1 if not found
|
||||||
|
std::unique_ptr<ZipEntry> ZipFile::getEntry(const std::wstring* name) {
|
||||||
|
bool path = name->find('/') != name->npos || name->find('\\') != name->npos;
|
||||||
|
std::wstring nameCopy = *name;
|
||||||
|
#ifdef _WIN64
|
||||||
|
if (path) { //
|
||||||
|
for (int i = 0; i < nameCopy.length(); i++)
|
||||||
|
if (nameCopy[i] == L'/')
|
||||||
|
nameCopy[i] = L'\\';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto it = _fileCache.find(nameCopy);
|
||||||
|
if (it != _fileCache.end()) {
|
||||||
|
auto entryInfo = _reader->itemAt(it->second);
|
||||||
|
return std::make_unique<ZipEntry>(entryInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BYTE> ZipFile::extract(const std::wstring* name) {
|
||||||
|
auto entry = getEntry(name);
|
||||||
|
if (!entry)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto size = entry->getSize();
|
||||||
|
std::vector<BYTE> buffer(size);
|
||||||
|
_reader->extractTo(buffer.data(), size, entry->getIndex());
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
catch (exception e) {
|
||||||
|
OutputDebugString(wstringtochararray(L"Error extracting file from zip: " + *name + L'\n'));
|
||||||
|
OutputDebugString(wstringtochararray(L"Exception: " + convStringToWstring(e.what()) + L'\n'));
|
||||||
|
__debugbreak();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipFile::hasFile(const std::wstring* name) {
|
||||||
|
bool path = name->find('/') != name->npos || name->find('\\') != name->npos;
|
||||||
|
std::wstring nameCopy = *name;
|
||||||
|
#ifdef _WIN64
|
||||||
|
if (path) { //
|
||||||
|
for (int i = 0; i < nameCopy.length(); i++)
|
||||||
|
if (nameCopy[i] == L'/')
|
||||||
|
nameCopy[i] = L'\\';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return _fileCache.find(nameCopy) != _fileCache.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipFile::hasFile(char* str) {
|
||||||
|
try {
|
||||||
|
std::wstring wstr = convStringToWstring(std::string(str));
|
||||||
|
return hasFile(&wstr);
|
||||||
|
}
|
||||||
|
catch (exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream* ZipFile::getInputStream(ZipEntry* entry) {
|
||||||
|
std::vector<BYTE> data(entry->getSize());
|
||||||
|
_reader->extractTo(data.data(), data.size(), entry->getIndex());
|
||||||
|
byteArray* buf = new byteArray(data.data(), data.size());
|
||||||
|
ByteArrayInputStream* stream = new ByteArrayInputStream(*buf, 0, data.size());
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream* ZipFile::getInputStream(int entryId) {
|
||||||
|
auto entry = _reader->itemAt(entryId);
|
||||||
|
std::vector<BYTE> data(entry.size());
|
||||||
|
_reader->extractTo(data.data(), data.size(), entry.index());
|
||||||
|
byteArray* buf = new byteArray(data.data(), data.size());
|
||||||
|
ByteArrayInputStream* stream = new ByteArrayInputStream(*buf, 0, data.size());
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZipFile::open(File* file) {
|
||||||
|
try {
|
||||||
|
std::wstring wpath = file->getPath();
|
||||||
|
int charCount = WideCharToMultiByte(CP_UTF8, 0, wpath.c_str(), -1, NULL, 0, NULL, NULL);
|
||||||
|
std::string path(charCount - 1, 0);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wpath.c_str(), -1, &path[0], charCount, NULL, NULL);
|
||||||
|
|
||||||
|
if (_library == nullptr) {
|
||||||
|
OutputDebugString("Initializing bit7z library");
|
||||||
|
_library = new bit7z::Bit7zLibrary("Windows64Media\\7z.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
_reader = std::make_unique<bit7z::BitArchiveReader>(*_library, path, bit7z::BitFormat::Zip);
|
||||||
|
auto _libentries = _reader->items();
|
||||||
|
_fileCache.clear();
|
||||||
|
|
||||||
|
for (auto &item : _libentries) {
|
||||||
|
if (!item.isDir()) { // We never unpack directories, this also saves time comparing against them
|
||||||
|
_fileCache[item.nativePath()] = item.index();
|
||||||
|
_fileCache[convStringToWstring(item.name())] = item.index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (exception e) {
|
||||||
|
OutputDebugString(wstringtochararray(L"Error opening zip file: " + file->getPath()));
|
||||||
|
OutputDebugString(wstringtochararray(L"\nException: " + convStringToWstring(e.what())));
|
||||||
|
__debugbreak();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
30
Minecraft.World/ZipFile.h
Normal file
30
Minecraft.World/ZipFile.h
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include "File.h"
|
||||||
|
#include "ZipEntry.h"
|
||||||
|
#include "../Minecraft.Client/Common/libs/bit7z/include/bitarchivereader.hpp"
|
||||||
|
|
||||||
|
class ZipFile {
|
||||||
|
public:
|
||||||
|
ZipFile(File* file);
|
||||||
|
ZipFile(std::string name);
|
||||||
|
std::vector<std::wstring> listFiles();
|
||||||
|
bool hasFile(const std::wstring* name);
|
||||||
|
bool hasFile(char* str);
|
||||||
|
std::unique_ptr<ZipEntry> getEntry(const std::wstring* name);
|
||||||
|
std::vector<BYTE> extract(const std::wstring* name);
|
||||||
|
InputStream* getInputStream(ZipEntry* entry);
|
||||||
|
InputStream* getInputStream(int entryId);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bit7z::Bit7zLibrary* _library;
|
||||||
|
std::unique_ptr<bit7z::BitArchiveReader> _reader;
|
||||||
|
unordered_map<std::wstring, unsigned int> _fileCache;
|
||||||
|
|
||||||
|
|
||||||
|
bool open(File* file);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue