summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AnvilStats/AnvilStats.cpp9
-rw-r--r--AnvilStats/AnvilStats.vcproj16
-rw-r--r--AnvilStats/BiomeMap.h2
-rw-r--r--AnvilStats/ChunkExtract.cpp104
-rw-r--r--AnvilStats/ChunkExtract.h66
-rw-r--r--AnvilStats/HeightMap.h2
-rw-r--r--AnvilStats/Processor.cpp4
-rw-r--r--VC2008/profile_run.cmd5
-rw-r--r--source/OSSupport/File.cpp3
-rw-r--r--source/OSSupport/GZipFile.cpp4
-rw-r--r--source/OSSupport/GZipFile.h4
11 files changed, 205 insertions, 14 deletions
diff --git a/AnvilStats/AnvilStats.cpp b/AnvilStats/AnvilStats.cpp
index a72548a5d..ef4d33ca5 100644
--- a/AnvilStats/AnvilStats.cpp
+++ b/AnvilStats/AnvilStats.cpp
@@ -8,6 +8,7 @@
#include "Statistics.h"
#include "BiomeMap.h"
#include "HeightMap.h"
+#include "ChunkExtract.h"
@@ -22,6 +23,7 @@ int main(int argc, char * argv[])
LOG(" 0 - statistics");
LOG(" 1 - biome map");
LOG(" 2 - height map");
+ LOG(" 3 - extract chunks");
LOG("\nNo method number present, aborting.");
return -1;
}
@@ -39,9 +41,10 @@ int main(int argc, char * argv[])
cCallbackFactory * Factory = NULL;
switch (atol(argv[1]))
{
- case 0: Factory = new cStatisticsFactory; break;
- case 1: Factory = new cBiomeMapFactory; break;
- case 2: Factory = new cHeightMapFactory; break;
+ case 0: Factory = new cStatisticsFactory; break;
+ case 1: Factory = new cBiomeMapFactory; break;
+ case 2: Factory = new cHeightMapFactory; break;
+ case 3: Factory = new cChunkExtractFactory(WorldFolder); break;
default:
{
LOG("Unknown method \"%s\", aborting.", argv[1]);
diff --git a/AnvilStats/AnvilStats.vcproj b/AnvilStats/AnvilStats.vcproj
index e67634f9c..8e8af8dfa 100644
--- a/AnvilStats/AnvilStats.vcproj
+++ b/AnvilStats/AnvilStats.vcproj
@@ -274,6 +274,14 @@
>
</File>
<File
+ RelativePath=".\ChunkExtract.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ChunkExtract.h"
+ >
+ </File>
+ <File
RelativePath=".\Globals.cpp"
>
<FileConfiguration
@@ -402,6 +410,14 @@
>
</File>
<File
+ RelativePath="..\source\OSSupport\GZipFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\OSSupport\GZipFile.h"
+ >
+ </File>
+ <File
RelativePath="..\source\OSSupport\IsThread.cpp"
>
</File>
diff --git a/AnvilStats/BiomeMap.h b/AnvilStats/BiomeMap.h
index 170216f46..f0d306c04 100644
--- a/AnvilStats/BiomeMap.h
+++ b/AnvilStats/BiomeMap.h
@@ -57,7 +57,7 @@ class cBiomeMapFactory :
public:
virtual ~cBiomeMapFactory();
- virtual cCallback * CreateNewCallback(void)
+ virtual cCallback * CreateNewCallback(void) override
{
return new cBiomeMap;
}
diff --git a/AnvilStats/ChunkExtract.cpp b/AnvilStats/ChunkExtract.cpp
new file mode 100644
index 000000000..30bdda9f3
--- /dev/null
+++ b/AnvilStats/ChunkExtract.cpp
@@ -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;
+} \ No newline at end of file
diff --git a/AnvilStats/ChunkExtract.h b/AnvilStats/ChunkExtract.h
new file mode 100644
index 000000000..5e0ed8a9a
--- /dev/null
+++ b/AnvilStats/ChunkExtract.h
@@ -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;
+} ;
+
+
+
+
diff --git a/AnvilStats/HeightMap.h b/AnvilStats/HeightMap.h
index 3263329a9..4f9e702d5 100644
--- a/AnvilStats/HeightMap.h
+++ b/AnvilStats/HeightMap.h
@@ -69,7 +69,7 @@ class cHeightMapFactory :
public:
virtual ~cHeightMapFactory();
- virtual cCallback * CreateNewCallback(void)
+ virtual cCallback * CreateNewCallback(void) override
{
return new cHeightMap;
}
diff --git a/AnvilStats/Processor.cpp b/AnvilStats/Processor.cpp
index 02070a8fc..8b506791c 100644
--- a/AnvilStats/Processor.cpp
+++ b/AnvilStats/Processor.cpp
@@ -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)
int NumThreads = GetNumCores() + 1;
- /*
+ //*
// Limit the number of threads in DEBUG mode to 1 for easier debugging
#ifdef _DEBUG
NumThreads = 1;
#endif // _DEBUG
- */
+ //*/
for (int i = 0; i < NumThreads; i++)
{
diff --git a/VC2008/profile_run.cmd b/VC2008/profile_run.cmd
index 3b6a2f99d..47c2630d2 100644
--- a/VC2008/profile_run.cmd
+++ b/VC2008/profile_run.cmd
@@ -14,7 +14,8 @@ set app=MCServer_profiled.exe
:: outputdir is relative to appdir!
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%
:: 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
diff --git a/source/OSSupport/File.cpp b/source/OSSupport/File.cpp
index 15a37a36f..bd2670217 100644
--- a/source/OSSupport/File.cpp
+++ b/source/OSSupport/File.cpp
@@ -94,10 +94,9 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
void cFile::Close(void)
{
- ASSERT(IsOpen()); // You should not close file objects that don't have an open file.
-
if (!IsOpen())
{
+ // Closing an unopened file is a legal nop
return;
}
diff --git a/source/OSSupport/GZipFile.cpp b/source/OSSupport/GZipFile.cpp
index dbdef3a8b..c57de5198 100644
--- a/source/OSSupport/GZipFile.cpp
+++ b/source/OSSupport/GZipFile.cpp
@@ -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)
{
@@ -99,7 +99,7 @@ bool cGZipFile::Write(const AString & a_Contents)
return false;
}
- return (gzwrite(m_File, a_Contents.data(), a_Contents.size()) != 0);
+ return (gzwrite(m_File, a_Contents, a_Size) != 0);
}
diff --git a/source/OSSupport/GZipFile.h b/source/OSSupport/GZipFile.h
index 10fb447dd..f20b4d11e 100644
--- a/source/OSSupport/GZipFile.h
+++ b/source/OSSupport/GZipFile.h
@@ -37,7 +37,9 @@ public:
int ReadRestOfFile(AString & a_Contents);
/// 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:
gzFile m_File;