AnvilStats: Added ChunkExtract mode of operation, splitting Anvil files into individual chunks.
Both original zlibbed chunks and re-gzipped chunks are output. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1223 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
4ce0c5a983
commit
24d3d5dac4
@ -8,6 +8,7 @@
|
|||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
#include "BiomeMap.h"
|
#include "BiomeMap.h"
|
||||||
#include "HeightMap.h"
|
#include "HeightMap.h"
|
||||||
|
#include "ChunkExtract.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ int main(int argc, char * argv[])
|
|||||||
LOG(" 0 - statistics");
|
LOG(" 0 - statistics");
|
||||||
LOG(" 1 - biome map");
|
LOG(" 1 - biome map");
|
||||||
LOG(" 2 - height map");
|
LOG(" 2 - height map");
|
||||||
|
LOG(" 3 - extract chunks");
|
||||||
LOG("\nNo method number present, aborting.");
|
LOG("\nNo method number present, aborting.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -39,9 +41,10 @@ int main(int argc, char * argv[])
|
|||||||
cCallbackFactory * Factory = NULL;
|
cCallbackFactory * Factory = NULL;
|
||||||
switch (atol(argv[1]))
|
switch (atol(argv[1]))
|
||||||
{
|
{
|
||||||
case 0: Factory = new cStatisticsFactory; break;
|
case 0: Factory = new cStatisticsFactory; break;
|
||||||
case 1: Factory = new cBiomeMapFactory; break;
|
case 1: Factory = new cBiomeMapFactory; break;
|
||||||
case 2: Factory = new cHeightMapFactory; break;
|
case 2: Factory = new cHeightMapFactory; break;
|
||||||
|
case 3: Factory = new cChunkExtractFactory(WorldFolder); break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
LOG("Unknown method \"%s\", aborting.", argv[1]);
|
LOG("Unknown method \"%s\", aborting.", argv[1]);
|
||||||
|
@ -273,6 +273,14 @@
|
|||||||
RelativePath=".\Callback.h"
|
RelativePath=".\Callback.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ChunkExtract.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\ChunkExtract.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Globals.cpp"
|
RelativePath=".\Globals.cpp"
|
||||||
>
|
>
|
||||||
@ -401,6 +409,14 @@
|
|||||||
RelativePath="..\source\OSSupport\File.h"
|
RelativePath="..\source\OSSupport\File.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\OSSupport\GZipFile.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\OSSupport\GZipFile.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\source\OSSupport\IsThread.cpp"
|
RelativePath="..\source\OSSupport\IsThread.cpp"
|
||||||
>
|
>
|
||||||
|
@ -57,7 +57,7 @@ class cBiomeMapFactory :
|
|||||||
public:
|
public:
|
||||||
virtual ~cBiomeMapFactory();
|
virtual ~cBiomeMapFactory();
|
||||||
|
|
||||||
virtual cCallback * CreateNewCallback(void)
|
virtual cCallback * CreateNewCallback(void) override
|
||||||
{
|
{
|
||||||
return new cBiomeMap;
|
return new cBiomeMap;
|
||||||
}
|
}
|
||||||
|
104
AnvilStats/ChunkExtract.cpp
Normal file
104
AnvilStats/ChunkExtract.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
// ChunkExtract.cpp
|
||||||
|
|
||||||
|
// Implements the cChunkExtract class representing a cCallback descendant that extracts raw chunk data into separate .chunk files
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ChunkExtract.h"
|
||||||
|
#include "../source/OSSupport/GZipFile.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cChunkExtract::cChunkExtract(const AString & iWorldFolder) :
|
||||||
|
mWorldFolder(iWorldFolder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkExtract::OnNewChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
int AnvilX = (a_ChunkX - ((a_ChunkX > 0) ? 0 : 31)) / 32;
|
||||||
|
int AnvilZ = (a_ChunkZ - ((a_ChunkZ > 0) ? 0 : 31)) / 32;
|
||||||
|
if ((AnvilX != mCurAnvilX) || (AnvilZ != mCurAnvilZ))
|
||||||
|
{
|
||||||
|
OpenAnvilFile(AnvilX, AnvilZ);
|
||||||
|
}
|
||||||
|
mCurChunkX = a_ChunkX;
|
||||||
|
mCurChunkZ = a_ChunkZ;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkExtract::OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod)
|
||||||
|
{
|
||||||
|
if (!mAnvilFile.IsOpen())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cFile ChunkFile;
|
||||||
|
AString ChunkPath = Printf("%d.%d.zchunk", mCurChunkX, mCurChunkZ);
|
||||||
|
if (!ChunkFile.Open(ChunkPath, cFile::fmWrite))
|
||||||
|
{
|
||||||
|
LOG("Cannot open zchunk file \"%s\" for writing. Chunk [%d, %d] skipped.", ChunkPath.c_str(), mCurChunkX, mCurChunkZ);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data from mAnvilFile to ChunkFile:
|
||||||
|
mAnvilFile.Seek(a_DataOffset);
|
||||||
|
for (int BytesToCopy = a_CompressedDataSize; BytesToCopy > 0; )
|
||||||
|
{
|
||||||
|
char Buffer[64000];
|
||||||
|
int NumBytes = std::min(BytesToCopy, (int)sizeof(Buffer));
|
||||||
|
int BytesRead = mAnvilFile.Read(Buffer, NumBytes);
|
||||||
|
if (BytesRead != NumBytes)
|
||||||
|
{
|
||||||
|
LOG("Cannot copy chunk data, chunk [%d, %d] is probably corrupted. Skipping chunk.", mCurChunkX, mCurChunkZ);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ChunkFile.Write(Buffer, BytesRead);
|
||||||
|
BytesToCopy -= BytesRead;
|
||||||
|
} // for BytesToCopy
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkExtract::OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize)
|
||||||
|
{
|
||||||
|
ASSERT(mAnvilFile.IsOpen()); // If it weren't, the OnCompressedDataSizePos would've prevented this from running
|
||||||
|
AString FileName = Printf("%d.%d.gzchunk", mCurChunkX, mCurChunkZ);
|
||||||
|
cGZipFile GZipChunk;
|
||||||
|
if (!GZipChunk.Open(FileName, cGZipFile::fmWrite))
|
||||||
|
{
|
||||||
|
LOG("Cannot open gzchunk file \"%s\" for writing. Chunk [%d, %d] skipped.", FileName.c_str(), mCurChunkX, mCurChunkZ);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
GZipChunk.Write(a_DecompressedNBT, a_DataSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkExtract::OpenAnvilFile(int a_AnvilX, int a_AnvilZ)
|
||||||
|
{
|
||||||
|
mAnvilFile.Close();
|
||||||
|
AString FileName = Printf("%s/r.%d.%d.mca", mWorldFolder.c_str(), a_AnvilX, a_AnvilZ);
|
||||||
|
if (!mAnvilFile.Open(FileName, cFile::fmRead))
|
||||||
|
{
|
||||||
|
LOG("Cannot open Anvil file \"%s\" for reading", FileName.c_str());
|
||||||
|
}
|
||||||
|
mCurAnvilX = a_AnvilX;
|
||||||
|
mCurAnvilZ = a_AnvilZ;
|
||||||
|
}
|
66
AnvilStats/ChunkExtract.h
Normal file
66
AnvilStats/ChunkExtract.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
// ChunkExtract.h
|
||||||
|
|
||||||
|
// Declares the cChunkExtract class representing a cCallback descendant that extracts raw chunk data into separate .chunk files
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Callback.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cChunkExtract :
|
||||||
|
public cCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cChunkExtract(const AString & iWorldFolder);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AString mWorldFolder;
|
||||||
|
cFile mAnvilFile;
|
||||||
|
int mCurAnvilX; // X-coord of mAnvilFile, in Anvil-coords (1 Anvil-coord = 32 chunks)
|
||||||
|
int mCurAnvilZ; // Z-coord of mAnvilFile, -"-
|
||||||
|
int mCurChunkX; // X-coord of the chunk being processed
|
||||||
|
int mCurChunkZ; // Z-coord of the chunk being processed
|
||||||
|
|
||||||
|
/// Opens new anvil file into mAnvilFile, sets mCurAnvilX and mCurAnvilZ
|
||||||
|
void OpenAnvilFile(int a_AnvilX, int a_AnvilZ);
|
||||||
|
|
||||||
|
// cCallback overrides:
|
||||||
|
virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) override;
|
||||||
|
virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) override { return false; }
|
||||||
|
virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) override;
|
||||||
|
virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cChunkExtractFactory :
|
||||||
|
public cCallbackFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cChunkExtractFactory(const AString & iWorldFolder) :
|
||||||
|
mWorldFolder(iWorldFolder)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual cCallback * CreateNewCallback(void) override
|
||||||
|
{
|
||||||
|
return new cChunkExtract(mWorldFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AString mWorldFolder;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -69,7 +69,7 @@ class cHeightMapFactory :
|
|||||||
public:
|
public:
|
||||||
virtual ~cHeightMapFactory();
|
virtual ~cHeightMapFactory();
|
||||||
|
|
||||||
virtual cCallback * CreateNewCallback(void)
|
virtual cCallback * CreateNewCallback(void) override
|
||||||
{
|
{
|
||||||
return new cHeightMap;
|
return new cHeightMap;
|
||||||
}
|
}
|
||||||
|
@ -507,12 +507,12 @@ void cProcessor::ProcessWorld(const AString & a_WorldFolder, cCallbackFactory &
|
|||||||
// (One more thread can be in the file-read IO block while all other threads crunch the numbers)
|
// (One more thread can be in the file-read IO block while all other threads crunch the numbers)
|
||||||
int NumThreads = GetNumCores() + 1;
|
int NumThreads = GetNumCores() + 1;
|
||||||
|
|
||||||
/*
|
//*
|
||||||
// Limit the number of threads in DEBUG mode to 1 for easier debugging
|
// Limit the number of threads in DEBUG mode to 1 for easier debugging
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
NumThreads = 1;
|
NumThreads = 1;
|
||||||
#endif // _DEBUG
|
#endif // _DEBUG
|
||||||
*/
|
//*/
|
||||||
|
|
||||||
for (int i = 0; i < NumThreads; i++)
|
for (int i = 0; i < NumThreads; i++)
|
||||||
{
|
{
|
||||||
|
@ -14,7 +14,8 @@ set app=MCServer_profiled.exe
|
|||||||
|
|
||||||
:: outputdir is relative to appdir!
|
:: outputdir is relative to appdir!
|
||||||
set outputdir=..\Profiling
|
set outputdir=..\Profiling
|
||||||
set output=%outputdir%\profile.vsp
|
set outputname=profile.vsp
|
||||||
|
set output=%outputdir%\%outputname%
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -50,7 +51,7 @@ if errorlevel 1 goto haderror
|
|||||||
cd %outputdir%
|
cd %outputdir%
|
||||||
|
|
||||||
:: generate the report files (.csv)
|
:: generate the report files (.csv)
|
||||||
%pt%\vsperfreport /summary:all %output% /symbolpath:"srv*C:\Programovani\Symbols*http://msdl.microsoft.com/download/symbols"
|
%pt%\vsperfreport /summary:all %outputname% /symbolpath:"srv*C:\Programovani\Symbols*http://msdl.microsoft.com/download/symbols"
|
||||||
if errorlevel 1 goto haderror
|
if errorlevel 1 goto haderror
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,10 +94,9 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
|
|||||||
|
|
||||||
void cFile::Close(void)
|
void cFile::Close(void)
|
||||||
{
|
{
|
||||||
ASSERT(IsOpen()); // You should not close file objects that don't have an open file.
|
|
||||||
|
|
||||||
if (!IsOpen())
|
if (!IsOpen())
|
||||||
{
|
{
|
||||||
|
// Closing an unopened file is a legal nop
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ int cGZipFile::ReadRestOfFile(AString & a_Contents)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cGZipFile::Write(const AString & a_Contents)
|
bool cGZipFile::Write(const char * a_Contents, int a_Size)
|
||||||
{
|
{
|
||||||
if (m_File == NULL)
|
if (m_File == NULL)
|
||||||
{
|
{
|
||||||
@ -99,7 +99,7 @@ bool cGZipFile::Write(const AString & a_Contents)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (gzwrite(m_File, a_Contents.data(), a_Contents.size()) != 0);
|
return (gzwrite(m_File, a_Contents, a_Size) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +37,9 @@ public:
|
|||||||
int ReadRestOfFile(AString & a_Contents);
|
int ReadRestOfFile(AString & a_Contents);
|
||||||
|
|
||||||
/// Writes a_Contents into file, compressing it along the way. Returns true if successful. Multiple writes are supported.
|
/// Writes a_Contents into file, compressing it along the way. Returns true if successful. Multiple writes are supported.
|
||||||
bool Write(const AString & a_Contents);
|
bool Write(const AString & a_Contents) { return Write(a_Contents.data(), (int)(a_Contents.size())); }
|
||||||
|
|
||||||
|
bool Write(const char * a_Data, int a_Size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
gzFile m_File;
|
gzFile m_File;
|
||||||
|
Loading…
Reference in New Issue
Block a user