mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-11 20:11:18 +03:00
* Add RegionFile class.
This commit is contained in:
166
source/World/RegionFile.cpp
Normal file
166
source/World/RegionFile.cpp
Normal file
@@ -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;
|
||||
}
|
||||
27
source/World/RegionFile.hpp
Normal file
27
source/World/RegionFile.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#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<int, bool> field_28;
|
||||
};
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
<ClInclude Include="..\source\World\Particle\Particle.hpp" />
|
||||
<ClInclude Include="..\source\World\Particle\ParticleEngine.hpp" />
|
||||
<ClInclude Include="..\source\World\Region.hpp" />
|
||||
<ClInclude Include="..\source\World\RegionFile.hpp" />
|
||||
<ClInclude Include="..\source\World\Renderer\Chunk.hpp" />
|
||||
<ClInclude Include="..\source\World\Renderer\Culler.hpp" />
|
||||
<ClInclude Include="..\source\World\Renderer\EntityRenderDispatcher.hpp" />
|
||||
@@ -454,6 +455,7 @@
|
||||
<ClCompile Include="..\source\World\Particle\SmokeParticle.cpp" />
|
||||
<ClCompile Include="..\source\World\Particle\TerrainParticle.cpp" />
|
||||
<ClCompile Include="..\source\World\Region.cpp" />
|
||||
<ClCompile Include="..\source\World\RegionFile.cpp" />
|
||||
<ClCompile Include="..\source\World\Renderer\Chunk.cpp" />
|
||||
<ClCompile Include="..\source\World\Renderer\Culler.cpp" />
|
||||
<ClCompile Include="..\source\World\Renderer\EntityRenderDispatcher.cpp" />
|
||||
|
||||
@@ -1059,6 +1059,9 @@
|
||||
<ClCompile Include="..\platforms\windows\SoundSystem_windows.cpp">
|
||||
<Filter>Source Files\App</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\source\World\RegionFile.cpp">
|
||||
<Filter>Source Files\World</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\source\Options.hpp">
|
||||
@@ -1925,6 +1928,9 @@
|
||||
<ClInclude Include="..\GameMods.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\source\World\RegionFile.hpp">
|
||||
<Filter>Header Files\World</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\thirdparty\raknet\CMakeLists.txt">
|
||||
|
||||
Reference in New Issue
Block a user