#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_pFile = nullptr; m_fileName = fileName + "/" + "chunks.dat"; field_20 = new int[1024]; field_24 = new int[1024]; memset(field_24, 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++) { int v13 = this->field_20[i]; if (v13) { int v12 = v13 >> 8; int v11 = uint8_t(v13); for (int j = 0; j < v11; ++j) { field_28[j + v12] = 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; return true; } bool RegionFile::readChunk(int x, int z, RakNet::BitStream** pBitStream) { int idx = field_20[32 * z + x]; if (!idx) return false; int thing = (idx >> 8); int offset = (idx & 0xFF); int length = 0; fseek(m_pFile, thing * 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 + 1; 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; }