AnvilStats: Added module for counting water and lava springs.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1267 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
d2573b84dd
commit
cf3f09e9c1
@ -9,6 +9,7 @@
|
||||
#include "BiomeMap.h"
|
||||
#include "HeightMap.h"
|
||||
#include "ChunkExtract.h"
|
||||
#include "SpringStats.h"
|
||||
|
||||
|
||||
|
||||
@ -24,6 +25,7 @@ int main(int argc, char * argv[])
|
||||
LOG(" 1 - biome map");
|
||||
LOG(" 2 - height map");
|
||||
LOG(" 3 - extract chunks");
|
||||
LOG(" 4 - count lava- and water- springs");
|
||||
LOG("\nNo method number present, aborting.");
|
||||
return -1;
|
||||
}
|
||||
@ -45,6 +47,7 @@ int main(int argc, char * argv[])
|
||||
case 1: Factory = new cBiomeMapFactory; break;
|
||||
case 2: Factory = new cHeightMapFactory; break;
|
||||
case 3: Factory = new cChunkExtractFactory(WorldFolder); break;
|
||||
case 4: Factory = new cSpringStatsFactory; break;
|
||||
default:
|
||||
{
|
||||
LOG("Unknown method \"%s\", aborting.", argv[1]);
|
||||
|
@ -329,6 +329,14 @@
|
||||
RelativePath=".\Processor.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SpringStats.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\SpringStats.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Statistics.cpp"
|
||||
>
|
||||
|
@ -507,7 +507,7 @@ 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;
|
||||
|
279
AnvilStats/SpringStats.cpp
Normal file
279
AnvilStats/SpringStats.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
|
||||
// SpringStats.cpp
|
||||
|
||||
// Implements the cSpringStats class representing a cCallback descendant that collects statistics on lava and water springs
|
||||
|
||||
#include "Globals.h"
|
||||
#include "SpringStats.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSpringStats::cStats
|
||||
|
||||
cSpringStats::cStats::cStats(void) :
|
||||
m_TotalChunks(0)
|
||||
{
|
||||
memset(m_LavaSprings, 0, sizeof(m_LavaSprings));
|
||||
memset(m_WaterSprings, 0, sizeof(m_WaterSprings));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSpringStats::cStats::Add(const cSpringStats::cStats & a_Other)
|
||||
{
|
||||
m_TotalChunks += a_Other.m_TotalChunks;
|
||||
for (int Biome = 0; Biome < 256; Biome++)
|
||||
{
|
||||
for (int Height = 0; Height < 256; Height++)
|
||||
{
|
||||
m_LavaSprings[Biome][Height] += a_Other.m_LavaSprings[Biome][Height];
|
||||
m_WaterSprings[Biome][Height] += a_Other.m_WaterSprings[Biome][Height];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSpringStats:
|
||||
|
||||
cSpringStats::cSpringStats(void) :
|
||||
m_AreBiomesValid(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cSpringStats::OnNewChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
memset(m_BlockTypes, 0, sizeof(m_BlockTypes));
|
||||
m_AreBiomesValid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cSpringStats::OnBiomes(const unsigned char * a_BiomeData)
|
||||
{
|
||||
memcpy(m_Biomes, a_BiomeData, sizeof(m_Biomes));
|
||||
m_AreBiomesValid = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cSpringStats::OnSection(
|
||||
unsigned char a_Y,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockAdditional,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
const NIBBLETYPE * a_BlockSkyLight
|
||||
)
|
||||
{
|
||||
memcpy(m_BlockTypes + ((int)a_Y) * 16 * 16 * 16, a_BlockTypes, 16 * 16 * 16);
|
||||
memcpy(m_BlockMetas + ((int)a_Y) * 16 * 16 * 16 / 2, a_BlockMeta, 16 * 16 * 16 / 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cSpringStats::OnSectionsFinished(void)
|
||||
{
|
||||
if (!m_AreBiomesValid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calc the spring stats:
|
||||
for (int y = 1; y < 255; y++)
|
||||
{
|
||||
int BaseY = y * 16 * 16;
|
||||
for (int z = 1; z < 15; z++)
|
||||
{
|
||||
int Base = BaseY + z * 16;
|
||||
for (int x = 1; x < 15; x++)
|
||||
{
|
||||
if (cChunkDef::GetNibble(m_BlockMetas, Base + x) != 0)
|
||||
{
|
||||
// Not a source block
|
||||
continue;
|
||||
}
|
||||
switch (m_BlockTypes[Base + x])
|
||||
{
|
||||
case E_BLOCK_WATER:
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
{
|
||||
TestSpring(x, y, z, m_Stats.m_WaterSprings);
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_LAVA:
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
{
|
||||
TestSpring(x, y, z, m_Stats.m_LavaSprings);
|
||||
break;
|
||||
}
|
||||
} // switch (BlockType)
|
||||
} // for x
|
||||
} // for z
|
||||
} // for y
|
||||
m_Stats.m_TotalChunks += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSpringStats::TestSpring(int a_RelX, int a_RelY, int a_RelZ, cSpringStats::cStats::SpringStats & a_Stats)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
int x, y, z;
|
||||
} Coords[] =
|
||||
{
|
||||
{-1, 0, 0},
|
||||
{ 1, 0, 0},
|
||||
{ 0, -1, 0},
|
||||
{ 0, 1, 0},
|
||||
{ 0, 0, -1},
|
||||
{ 0, 0, 1},
|
||||
} ;
|
||||
bool HasFluidNextToIt = false;
|
||||
for (int i = 0; i < ARRAYCOUNT(Coords); i++)
|
||||
{
|
||||
switch (cChunkDef::GetBlock(m_BlockTypes, a_RelX + Coords[i].x, a_RelY + Coords[i].y, a_RelZ + Coords[i].z))
|
||||
{
|
||||
case E_BLOCK_WATER:
|
||||
case E_BLOCK_STATIONARY_WATER:
|
||||
case E_BLOCK_LAVA:
|
||||
case E_BLOCK_STATIONARY_LAVA:
|
||||
{
|
||||
if (cChunkDef::GetNibble(m_BlockMetas, a_RelX + Coords[i].x, a_RelY + Coords[i].y, a_RelZ + Coords[i].z) == 0)
|
||||
{
|
||||
// There is another source block next to this, so this is not a spring
|
||||
return;
|
||||
}
|
||||
HasFluidNextToIt = true;
|
||||
}
|
||||
} // switch (BlockType)
|
||||
} // for i - Coords[]
|
||||
|
||||
if (!HasFluidNextToIt)
|
||||
{
|
||||
// Surrounded by solids on all sides, this is probably not a spring,
|
||||
// but rather a bedrocked lake or something similar. Dont want.
|
||||
return;
|
||||
}
|
||||
|
||||
// No source blocks next to the specified block, so it is a spring. Add it to stats:
|
||||
a_Stats[a_RelY][((unsigned char *)m_Biomes)[a_RelX + 16 * a_RelZ]] += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSpringStatsFactory:
|
||||
|
||||
cSpringStatsFactory::~cSpringStatsFactory()
|
||||
{
|
||||
LOG("cSpringStats:");
|
||||
LOG(" Joining results...");
|
||||
JoinResults();
|
||||
LOG(" Total %llu chunks went through", m_CombinedStats.m_TotalChunks);
|
||||
|
||||
// Save statistics:
|
||||
LOG(" Saving statistics into files:");
|
||||
LOG(" Springs.xls");
|
||||
SaveTotals("Springs.xls");
|
||||
LOG(" BiomeWaterSprings.xls");
|
||||
SaveStatistics(m_CombinedStats.m_WaterSprings, "BiomeWaterSprings.xls");
|
||||
LOG(" BiomeLavaSprings.xls");
|
||||
SaveStatistics(m_CombinedStats.m_LavaSprings, "BiomeLavaSprings.xls");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSpringStatsFactory::JoinResults(void)
|
||||
{
|
||||
for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr)
|
||||
{
|
||||
m_CombinedStats.Add(((cSpringStats *)(*itr))->GetStats());
|
||||
} // for itr - m_Callbacks[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSpringStatsFactory::SaveTotals(const AString & a_FileName)
|
||||
{
|
||||
cFile f(a_FileName, cFile::fmWrite);
|
||||
if (!f.IsOpen())
|
||||
{
|
||||
LOG("Cannot open file \"%s\" for writing!", a_FileName.c_str());
|
||||
return;
|
||||
}
|
||||
f.Printf("Height\tWater\tLava\n");
|
||||
for (int Height = 0; Height < 256; Height++)
|
||||
{
|
||||
UInt64 TotalW = 0;
|
||||
UInt64 TotalL = 0;
|
||||
for (int Biome = 0; Biome < 256; Biome++)
|
||||
{
|
||||
TotalW += m_CombinedStats.m_WaterSprings[Height][Biome];
|
||||
TotalL += m_CombinedStats.m_LavaSprings[Height][Biome];
|
||||
}
|
||||
f.Printf("%d\t%llu\t%llu\n", Height, TotalW, TotalL);
|
||||
}
|
||||
f.Printf("\n# Chunks\t%llu", m_CombinedStats.m_TotalChunks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cSpringStatsFactory::SaveStatistics(const cSpringStats::cStats::SpringStats & a_Stats, const AString & a_FileName)
|
||||
{
|
||||
cFile f(a_FileName, cFile::fmWrite);
|
||||
if (!f.IsOpen())
|
||||
{
|
||||
LOG("Cannot open file \"%s\" for writing!", a_FileName.c_str());
|
||||
return;
|
||||
}
|
||||
for (int Height = 0; Height < 256; Height++)
|
||||
{
|
||||
AString Line;
|
||||
Line.reserve(2000);
|
||||
Printf(Line, "%d\t", Height);
|
||||
for (int Biome = 0; Biome < 256; Biome++)
|
||||
{
|
||||
AppendPrintf(Line, "%llu\t", a_Stats[Height][Biome]);
|
||||
}
|
||||
Line.append("\n");
|
||||
f.Write(Line.c_str(), Line.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
102
AnvilStats/SpringStats.h
Normal file
102
AnvilStats/SpringStats.h
Normal file
@ -0,0 +1,102 @@
|
||||
|
||||
// SpringStats.h
|
||||
|
||||
// Declares the cSpringStats class representing a cCallback descendant that collects statistics on lava and water springs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Callback.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cSpringStats :
|
||||
public cCallback
|
||||
{
|
||||
public:
|
||||
class cStats
|
||||
{
|
||||
public:
|
||||
/// Per-height, per-biome frequencies of springs
|
||||
typedef UInt64 SpringStats[256][256];
|
||||
|
||||
SpringStats m_LavaSprings;
|
||||
SpringStats m_WaterSprings;
|
||||
|
||||
UInt64 m_TotalChunks; ///< Total number of chunks that are fully processed through this callback(OnSectionsFinished())
|
||||
|
||||
cStats(void);
|
||||
void Add(const cStats & a_Other);
|
||||
} ;
|
||||
|
||||
cSpringStats(void);
|
||||
|
||||
const cStats & GetStats(void) const { return m_Stats; }
|
||||
|
||||
protected:
|
||||
|
||||
BLOCKTYPE m_BlockTypes[16 * 16 * 256];
|
||||
NIBBLETYPE m_BlockMetas[16 * 16 * 256 / 2];
|
||||
char m_Biomes[16 * 16];
|
||||
bool m_AreBiomesValid;
|
||||
|
||||
cStats m_Stats;
|
||||
|
||||
// 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 { return false; }
|
||||
virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; }
|
||||
virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; }
|
||||
virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; }
|
||||
virtual bool OnTerrainPopulated(bool a_Populated) override { return !a_Populated; } // If not populated, we don't want it!
|
||||
virtual bool OnBiomes(const unsigned char * a_BiomeData) override;
|
||||
virtual bool OnHeightMap(const int * a_HeightMap) override { return false; }
|
||||
virtual bool OnSection(
|
||||
unsigned char a_Y,
|
||||
const BLOCKTYPE * a_BlockTypes,
|
||||
const NIBBLETYPE * a_BlockAdditional,
|
||||
const NIBBLETYPE * a_BlockMeta,
|
||||
const NIBBLETYPE * a_BlockLight,
|
||||
const NIBBLETYPE * a_BlockSkyLight
|
||||
) override;
|
||||
virtual bool OnSectionsFinished(void) override;
|
||||
|
||||
/// Tests the specified block, if it appears to be a spring, it is added to a_Stats
|
||||
void TestSpring(int a_RelX, int a_RelY, int a_RelZ, cStats::SpringStats & a_Stats);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cSpringStatsFactory :
|
||||
public cCallbackFactory
|
||||
{
|
||||
public:
|
||||
virtual ~cSpringStatsFactory();
|
||||
|
||||
virtual cCallback * CreateNewCallback(void) override
|
||||
{
|
||||
return new cSpringStats;
|
||||
}
|
||||
|
||||
cSpringStats::cStats m_CombinedStats;
|
||||
|
||||
void JoinResults(void);
|
||||
|
||||
/// Saves total per-height data (summed through biomes) for both spring types to the file
|
||||
void SaveTotals(const AString & a_FileName);
|
||||
|
||||
/// Saves complete per-height, per-biome statistics for the springs to the file
|
||||
void SaveStatistics(const cSpringStats::cStats::SpringStats & a_Stats, const AString & a_FileName);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user