mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-25 16:03:42 +00:00
# Conflicts: # Minecraft.Client/Network/PlayerChunkMap.cpp # Minecraft.Client/Network/PlayerList.cpp # Minecraft.Client/Network/ServerChunkCache.cpp # Minecraft.Client/Platform/Common/Consoles_App.cpp # Minecraft.Client/Platform/Common/DLC/DLCManager.cpp # Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp # Minecraft.Client/Platform/Common/GameRules/LevelRuleset.cpp # Minecraft.Client/Platform/Common/Tutorial/Tutorial.cpp # Minecraft.Client/Platform/Common/Tutorial/TutorialTask.cpp # Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp # Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp # Minecraft.Client/Platform/Common/UI/UIController.cpp # Minecraft.Client/Platform/Common/UI/UIController.h # Minecraft.Client/Platform/Extrax64Stubs.cpp # Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Input.h # Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Storage.h # Minecraft.Client/Player/EntityTracker.cpp # Minecraft.Client/Player/ServerPlayer.cpp # Minecraft.Client/Rendering/EntityRenderers/PlayerRenderer.cpp # Minecraft.Client/Textures/Packs/DLCTexturePack.cpp # Minecraft.Client/Textures/Stitching/StitchedTexture.cpp # Minecraft.Client/Textures/Stitching/TextureMap.cpp # Minecraft.Client/Textures/Textures.cpp # Minecraft.World/Blocks/NotGateTile.cpp # Minecraft.World/Blocks/PressurePlateTile.cpp # Minecraft.World/Blocks/TileEntities/PotionBrewing.cpp # Minecraft.World/Enchantments/EnchantmentHelper.cpp # Minecraft.World/Entities/HangingEntity.cpp # Minecraft.World/Entities/LeashFenceKnotEntity.cpp # Minecraft.World/Entities/LivingEntity.cpp # Minecraft.World/Entities/Mobs/Boat.cpp # Minecraft.World/Entities/Mobs/Minecart.cpp # Minecraft.World/Entities/Mobs/Witch.cpp # Minecraft.World/Entities/SyncedEntityData.cpp # Minecraft.World/Items/LeashItem.cpp # Minecraft.World/Items/PotionItem.cpp # Minecraft.World/Level/BaseMobSpawner.cpp # Minecraft.World/Level/CustomLevelSource.cpp # Minecraft.World/Level/Level.cpp # Minecraft.World/Level/Storage/DirectoryLevelStorage.cpp # Minecraft.World/Level/Storage/McRegionLevelStorage.cpp # Minecraft.World/Level/Storage/RegionFileCache.cpp # Minecraft.World/Player/Player.cpp # Minecraft.World/WorldGen/Biomes/BiomeCache.cpp # Minecraft.World/WorldGen/Features/RandomScatteredLargeFeature.cpp # Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp
153 lines
4.5 KiB
C++
153 lines
4.5 KiB
C++
#include "../Platform/stdafx.h"
|
|
|
|
#include "../../Minecraft.World/Util/StringHelpers.h"
|
|
#include "../../Minecraft.World/Util/PortableFileIO.h"
|
|
#include "../../Minecraft.World/IO/Streams/Compression.h"
|
|
|
|
#include "ArchiveFile.h"
|
|
|
|
void ArchiveFile::_readHeader(DataInputStream* dis) {
|
|
int numberOfFiles = dis->readInt();
|
|
|
|
for (int i = 0; i < numberOfFiles; i++) {
|
|
MetaData* meta = new MetaData();
|
|
meta->filename = dis->readUTF();
|
|
meta->ptr = dis->readInt();
|
|
meta->filesize = dis->readInt();
|
|
|
|
// Filenames preceeded by an asterisk have been compressed.
|
|
if (meta->filename[0] == '*') {
|
|
meta->filename = meta->filename.substr(1);
|
|
meta->isCompressed = true;
|
|
} else
|
|
meta->isCompressed = false;
|
|
|
|
m_index.insert(
|
|
std::pair<std::wstring, PMetaData>(meta->filename, meta));
|
|
}
|
|
}
|
|
|
|
ArchiveFile::ArchiveFile(File file) {
|
|
m_cachedData = nullptr;
|
|
m_sourcefile = file;
|
|
app.DebugPrintf("Loading archive file...\n");
|
|
#if !defined(_CONTENT_PACKAGE)
|
|
char buf[256];
|
|
wcstombs(buf, file.getPath().c_str(), 256);
|
|
app.DebugPrintf("archive file - %s\n", buf);
|
|
#endif
|
|
|
|
if (!file.exists()) {
|
|
app.DebugPrintf("Failed to load archive file!\n"); //,file.getPath());
|
|
app.FatalLoadError();
|
|
}
|
|
|
|
FileInputStream fis(file);
|
|
|
|
#if defined(_WINDOWS64)
|
|
byteArray readArray(file.length());
|
|
fis.read(readArray, 0, file.length());
|
|
|
|
ByteArrayInputStream bais(readArray);
|
|
DataInputStream dis(&bais);
|
|
|
|
m_cachedData = readArray.data;
|
|
#else
|
|
DataInputStream dis(&fis);
|
|
#endif
|
|
|
|
_readHeader(&dis);
|
|
|
|
dis.close();
|
|
fis.close();
|
|
#if defined(_WINDOWS64)
|
|
bais.reset();
|
|
#endif
|
|
app.DebugPrintf("Finished loading archive file\n");
|
|
}
|
|
|
|
ArchiveFile::~ArchiveFile() { delete m_cachedData; }
|
|
|
|
std::vector<std::wstring>* ArchiveFile::getFileList() {
|
|
std::vector<std::wstring>* out = new std::vector<std::wstring>();
|
|
|
|
for (auto it = m_index.begin(); it != m_index.end(); it++)
|
|
|
|
out->push_back(it->first);
|
|
|
|
return out;
|
|
}
|
|
|
|
bool ArchiveFile::hasFile(const std::wstring& filename) {
|
|
return m_index.find(filename) != m_index.end();
|
|
}
|
|
|
|
int ArchiveFile::getFileSize(const std::wstring& filename) {
|
|
return hasFile(filename) ? m_index.at(filename)->filesize : -1;
|
|
}
|
|
|
|
byteArray ArchiveFile::getFile(const std::wstring& filename) {
|
|
byteArray out;
|
|
auto it = m_index.find(filename);
|
|
|
|
if (it == m_index.end()) {
|
|
app.DebugPrintf("Couldn't find file in archive\n");
|
|
app.DebugPrintf("Failed to find file '%ls' in archive\n",
|
|
filename.c_str());
|
|
#if !defined(_CONTENT_PACKAGE)
|
|
__debugbreak();
|
|
#endif
|
|
app.FatalLoadError();
|
|
} else {
|
|
PMetaData data = it->second;
|
|
|
|
#if defined(_WINDOWS64)
|
|
out = byteArray(data->filesize);
|
|
|
|
memcpy(out.data, m_cachedData + data->ptr, data->filesize);
|
|
#else
|
|
const unsigned int fileSize = static_cast<unsigned int>(data->filesize);
|
|
std::uint8_t* pbData = new std::uint8_t[fileSize == 0 ? 1 : fileSize];
|
|
out = byteArray(pbData, fileSize);
|
|
const PortableFileIO::BinaryReadResult readResult =
|
|
PortableFileIO::ReadBinaryFileSegment(
|
|
m_sourcefile.getPath(), static_cast<std::size_t>(data->ptr),
|
|
out.data, static_cast<std::size_t>(data->filesize));
|
|
|
|
if (readResult.status != PortableFileIO::BinaryReadStatus::ok) {
|
|
app.DebugPrintf("Failed to read archive file segment\n");
|
|
app.FatalLoadError();
|
|
}
|
|
#endif
|
|
|
|
// Compressed filenames are preceeded with an asterisk.
|
|
if (data->isCompressed && out.data != nullptr) {
|
|
/* 4J-JEV:
|
|
* If a compressed file is accessed before compression object is
|
|
* initialized it will crash here (Compression::getCompression).
|
|
*/
|
|
/// 4 279 553 556
|
|
|
|
ByteArrayInputStream bais(out);
|
|
DataInputStream dis(&bais);
|
|
unsigned int decompressedSize = dis.readInt();
|
|
dis.close();
|
|
|
|
std::uint8_t* uncompressedBuffer =
|
|
new std::uint8_t[decompressedSize];
|
|
Compression::getCompression()->Decompress(
|
|
uncompressedBuffer, &decompressedSize, out.data + 4,
|
|
out.length - 4);
|
|
|
|
delete[] out.data;
|
|
|
|
out.data = uncompressedBuffer;
|
|
out.length = decompressedSize;
|
|
}
|
|
|
|
assert(out.data != nullptr); // THERE IS NO FILE WITH THIS NAME!
|
|
}
|
|
|
|
return out;
|
|
}
|