diff --git a/source/World/RegionFile.cpp b/source/World/RegionFile.cpp new file mode 100644 index 0000000..72c169d --- /dev/null +++ b/source/World/RegionFile.cpp @@ -0,0 +1,166 @@ +#include "RegionFile.hpp" + +#define SECTOR_BYTES (4096) + +static void void_sub(int a, int b) +{ +} + +#define WRITE(data, elemsize, elemcnt, file) void_sub(int(fwrite(data, elemsize, elemcnt, file)), elemcnt) +#define READ( data, elemsize, elemcnt, file) void_sub(int(fread (data, elemsize, elemcnt, file)), elemcnt) + +RegionFile::RegionFile(const std::string fileName) +{ + m_fileName = fileName + "/" + "chunks.dat"; + + field_20 = new int[1024]; + field_24 = new int[1024]; + memset(field_20, 0, 1024 * sizeof(int)); +} + +RegionFile::~RegionFile() +{ + close(); + if (field_20) delete[] field_20; + if (field_24) delete[] field_24; +} + +void RegionFile::close() +{ + if (m_pFile) + { + fclose(m_pFile); + m_pFile = nullptr; + } +} + +bool RegionFile::open() +{ + close(); + memset(field_20, 0, 1024 * sizeof(int)); + + m_pFile = fopen(m_fileName.c_str(), "r+b"); + if (m_pFile) + { + READ(field_20, sizeof(int), 1024, m_pFile); + + field_28[0] = false; + + for (int i = 0; i < 1024; i++) + { + if (field_20[i]) + { + for (int j = 0; j < uint8_t(field_20[i]); j++) + { + field_28[j + (field_20[i] >> 8)] = false; + } + } + } + + return m_pFile != nullptr; + } + + m_pFile = fopen(m_fileName.c_str(), "w+b"); + if (!m_pFile) + return false; + + WRITE(field_20, sizeof(int), 1024, m_pFile); + field_28[0] = false; +} + +bool RegionFile::readChunk(int x, int z, RakNet::BitStream** pBitStream) +{ + int idx = field_20[32 * z + x]; + if (!idx) + return false; + + int length = 0; + fseek(m_pFile, (idx >> 8) * SECTOR_BYTES, SEEK_SET); + fread(&length, sizeof(int), 1, m_pFile); + + assert(length < ((offset & 0xff) * SECTOR_BYTES)); + + length -= 4; + + uint8_t* data = new uint8_t[length]; + READ(data, 1, length, m_pFile); + + *pBitStream = new RakNet::BitStream(data, length, false); + return true; +} + +bool RegionFile::write(int index, RakNet::BitStream& bitStream) +{ + fseek(m_pFile, index * SECTOR_BYTES, 0); + int length = sizeof(int) + bitStream.GetNumberOfBytesUsed(); + + WRITE(&length, sizeof(length), 1, m_pFile); + WRITE(bitStream.GetData(), 1, bitStream.GetNumberOfBytesUsed(), m_pFile); + + return true; +} + +bool RegionFile::writeChunk(int x, int z, RakNet::BitStream& bitStream) +{ + int length = bitStream.GetNumberOfBytesUsed(); + int field20i = field_20[32 * z + x]; + int lowerIndex = (length + 4) / SECTOR_BYTES; + if (lowerIndex > 256) + return false; + + int field20iU = field20i >> 8, field20iL = field20i & 0xff; + + if (field20iU && lowerIndex == field20iL) + { + write(field20iU, bitStream); + return true; + } + + for (int i = 0; i < field20iL; i++) + { + field_28[i + field20iU] = true; + } + + bool bNeedWrite = false; + int v22 = 0, i = 0; + while (i < lowerIndex) + { + if (field_28.find(i + v22) == field_28.end()) + { + bNeedWrite = true; + break; + } + + if (field_28[i + v22]) + { + i++; + } + else + { + v22 += i + 1; + i = 0; + } + } + + if (bNeedWrite) + { + fseek(m_pFile, 0, SEEK_END); + for (int j = 0; lowerIndex - i > j; j++) + { + fwrite(field_24, sizeof(int), 1024, m_pFile); + field_28[j + v22] = true; + } + } + + field_20[32 * z + x] = (v22 << 8) | lowerIndex; + for (int k = 0; k < lowerIndex; k++) + { + field_28[k + v22] = false; + } + + write(v22, bitStream); + fseek(m_pFile, sizeof(int) * (x + 32 * z), SEEK_SET); + fwrite(&field_20[x + 32 * z], sizeof(int), 1, m_pFile); + + return true; +} diff --git a/source/World/RegionFile.hpp b/source/World/RegionFile.hpp new file mode 100644 index 0000000..0b873f2 --- /dev/null +++ b/source/World/RegionFile.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include "BitStream.h" + +class RegionFile +{ +public: + RegionFile(const std::string fileName); + ~RegionFile(); + void close(); + bool open(); + bool readChunk(int x, int z, RakNet::BitStream**); + bool write(int index, RakNet::BitStream&); + bool writeChunk(int x, int z, RakNet::BitStream&); + +public: + FILE* m_pFile = nullptr; + std::string m_fileName; + int* field_20; + int* field_24; + std::map field_28; +}; + diff --git a/windows_vs/minecraftcpp.vcxproj b/windows_vs/minecraftcpp.vcxproj index 4d0638b..8acb945 100644 --- a/windows_vs/minecraftcpp.vcxproj +++ b/windows_vs/minecraftcpp.vcxproj @@ -137,6 +137,7 @@ + @@ -454,6 +455,7 @@ + diff --git a/windows_vs/minecraftcpp.vcxproj.filters b/windows_vs/minecraftcpp.vcxproj.filters index 1c93f6a..94636be 100644 --- a/windows_vs/minecraftcpp.vcxproj.filters +++ b/windows_vs/minecraftcpp.vcxproj.filters @@ -1059,6 +1059,9 @@ Source Files\App + + Source Files\World + @@ -1925,6 +1928,9 @@ Header Files + + Header Files\World +