summaryrefslogtreecommitdiffstats
path: root/Tools/AnvilStats/Statistics.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Tools/AnvilStats/Statistics.cpp1046
1 files changed, 523 insertions, 523 deletions
diff --git a/Tools/AnvilStats/Statistics.cpp b/Tools/AnvilStats/Statistics.cpp
index 2f30e158a..b5b3cb176 100644
--- a/Tools/AnvilStats/Statistics.cpp
+++ b/Tools/AnvilStats/Statistics.cpp
@@ -1,523 +1,523 @@
-
-// Statistics.cpp
-
-// Implements the various statistics-collecting classes
-
-#include "Globals.h"
-#include "Statistics.h"
-#include "../../source/WorldStorage/FastNBT.h"
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStatistics::cStats:
-
-cStatistics::cStats::cStats(void) :
- m_TotalChunks(0),
- m_BiomeNumChunks(0),
- m_BlockNumChunks(0),
- m_NumEntities(0),
- m_NumTileEntities(0),
- m_NumTileTicks(0),
- m_MinChunkX(0x7fffffff),
- m_MaxChunkX(0x80000000),
- m_MinChunkZ(0x7fffffff),
- m_MaxChunkZ(0x80000000)
-{
- memset(m_BiomeCounts, 0, sizeof(m_BiomeCounts));
- memset(m_BlockCounts, 0, sizeof(m_BlockCounts));
- memset(m_SpawnerEntity, 0, sizeof(m_SpawnerEntity));
-}
-
-
-
-
-
-void cStatistics::cStats::Add(const cStatistics::cStats & a_Stats)
-{
- for (int i = 0; i <= 255; i++)
- {
- m_BiomeCounts[i] += a_Stats.m_BiomeCounts[i];
- }
- for (int i = 0; i <= 255; i++)
- {
- for (int j = 0; j <= 255; j++)
- {
- m_BlockCounts[i][j] += a_Stats.m_BlockCounts[i][j];
- }
- }
- for (int i = 0; i < ARRAYCOUNT(m_SpawnerEntity); i++)
- {
- m_SpawnerEntity[i] += a_Stats.m_SpawnerEntity[i];
- }
- m_BiomeNumChunks += a_Stats.m_BiomeNumChunks;
- m_BlockNumChunks += a_Stats.m_BlockNumChunks;
- m_TotalChunks += a_Stats.m_TotalChunks;
- m_NumEntities += a_Stats.m_NumEntities;
- m_NumTileEntities += a_Stats.m_NumTileEntities;
- m_NumTileTicks += a_Stats.m_NumTileTicks;
- UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ);
- UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ);
-}
-
-
-
-
-
-void cStatistics::cStats::UpdateCoordsRange(int a_ChunkX, int a_ChunkZ)
-{
- if (a_ChunkX < m_MinChunkX)
- {
- m_MinChunkX = a_ChunkX;
- }
- if (a_ChunkX > m_MaxChunkX)
- {
- m_MaxChunkX = a_ChunkX;
- }
- if (a_ChunkZ < m_MinChunkZ)
- {
- m_MinChunkZ = a_ChunkZ;
- }
- if (a_ChunkZ > m_MaxChunkZ)
- {
- m_MaxChunkZ = a_ChunkZ;
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStatistics:
-
-cStatistics::cStatistics(void)
-{
-}
-
-
-
-
-
-bool cStatistics::OnNewChunk(int a_ChunkX, int a_ChunkZ)
-{
- m_Stats.m_TotalChunks++;
- m_Stats.UpdateCoordsRange(a_ChunkX, a_ChunkZ);
- m_IsBiomesValid = false;
- m_IsFirstSectionInChunk = true;
- return false;
-}
-
-
-
-
-
-bool cStatistics::OnBiomes(const unsigned char * a_BiomeData)
-{
- for (int i = 0; i < 16 * 16; i++)
- {
- m_Stats.m_BiomeCounts[a_BiomeData[i]] += 1;
- }
- m_Stats.m_BiomeNumChunks += 1;
- memcpy(m_BiomeData, a_BiomeData, sizeof(m_BiomeData));
- m_IsBiomesValid = true;
- return false;
-}
-
-
-
-
-
-
-bool cStatistics::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
-)
-{
- if (!m_IsBiomesValid)
- {
- // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays
- return true;
- }
-
- for (int y = 0; y < 16; y++)
- {
- for (int z = 0; z < 16; z++)
- {
- for (int x = 0; x < 16; x++)
- {
- unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype
- unsigned char BlockType = cChunkDef::GetBlock(a_BlockTypes, x, y, z);
- m_Stats.m_BlockCounts[Biome][BlockType] += 1;
- }
- }
- }
-
- m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0;
- m_IsFirstSectionInChunk = false;
-
- return false;
-}
-
-
-
-
-
-bool cStatistics::OnEmptySection(unsigned char a_Y)
-{
- if (!m_IsBiomesValid)
- {
- // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays
- return true;
- }
-
- // Add air to all columns:
- for (int z = 0; z < 16; z++)
- {
- for (int x = 0; x < 16; x++)
- {
- unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype
- m_Stats.m_BlockCounts[Biome][0] += 16; // 16 blocks in a column, all air
- }
- }
-
- m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0;
- m_IsFirstSectionInChunk = false;
-
- return false;
-}
-
-
-
-
-
-bool cStatistics::OnEntity(
- const AString & a_EntityType,
- double a_PosX, double a_PosY, double a_PosZ,
- double a_SpeedX, double a_SpeedY, double a_SpeedZ,
- float a_Yaw, float a_Pitch,
- float a_FallDistance,
- short a_FireTicksLeft,
- short a_AirTicks,
- char a_IsOnGround,
- cParsedNBT & a_NBT,
- int a_NBTTag
-)
-{
- m_Stats.m_NumEntities += 1;
-
- // TODO
-
- return false;
-}
-
-
-
-
-
-bool cStatistics::OnTileEntity(
- const AString & a_EntityType,
- int a_PosX, int a_PosY, int a_PosZ,
- cParsedNBT & a_NBT,
- int a_NBTTag
-)
-{
- m_Stats.m_NumTileEntities += 1;
-
- if (a_EntityType == "MobSpawner")
- {
- OnSpawner(a_NBT, a_NBTTag);
- }
-
- return false;
-}
-
-
-
-
-
-bool cStatistics::OnTileTick(
- int a_BlockType,
- int a_TicksLeft,
- int a_PosX, int a_PosY, int a_PosZ
-)
-{
- m_Stats.m_NumTileTicks += 1;
- return false;
-}
-
-
-
-
-
-void cStatistics::OnSpawner(cParsedNBT & a_NBT, int a_TileEntityTag)
-{
- int EntityIDTag = a_NBT.FindChildByName(a_TileEntityTag, "EntityId");
- if ((EntityIDTag < 0) || (a_NBT.GetType(EntityIDTag) != TAG_String))
- {
- return;
- }
- eEntityType Ent = GetEntityType(a_NBT.GetString(EntityIDTag));
- if (Ent < ARRAYCOUNT(m_Stats.m_SpawnerEntity))
- {
- m_Stats.m_SpawnerEntity[Ent] += 1;
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStatisticsFactory:
-
-cStatisticsFactory::cStatisticsFactory(void) :
- m_BeginTick(clock())
-{
-}
-
-
-
-
-
-cStatisticsFactory::~cStatisticsFactory()
-{
- // Join the results together:
- LOG("cStatistics:");
- LOG(" Joining results...");
- JoinResults();
- LOG(" Total %llu chunks went through", m_CombinedStats.m_TotalChunks);
- LOG(" Biomes processed for %llu chunks", m_CombinedStats.m_BiomeNumChunks);
-
- // Check the number of blocks processed
- UInt64 TotalBlocks = 0;
- for (int i = 0; i <= 255; i++)
- {
- for (int j = 0; j < 255; j++)
- {
- TotalBlocks += m_CombinedStats.m_BlockCounts[i][j];
- }
- }
- UInt64 ExpTotalBlocks = m_CombinedStats.m_BlockNumChunks * 16LL * 16LL * 256LL;
- LOG(" BlockIDs processed for %llu chunks, %llu blocks (exp %llu; %s)", m_CombinedStats.m_BlockNumChunks, TotalBlocks, ExpTotalBlocks, (TotalBlocks == ExpTotalBlocks) ? "match" : "failed");
-
- // Save statistics:
- LOG(" Saving statistics into files:");
- LOG(" Statistics.txt");
- SaveStatistics();
- LOG(" Biomes.xls");
- SaveBiomes();
- LOG(" BlockTypes.xls");
- SaveBlockTypes();
- LOG(" BiomeBlockTypes.xls");
- SaveBiomeBlockTypes();
- LOG(" Spawners.xls");
- SaveSpawners();
-}
-
-
-
-
-
-void cStatisticsFactory::JoinResults(void)
-{
- for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr)
- {
- m_CombinedStats.Add(((cStatistics *)(*itr))->GetStats());
- } // for itr - m_Callbacks[]
-}
-
-
-
-
-
-void cStatisticsFactory::SaveBiomes(void)
-{
- cFile f;
- if (!f.Open("Biomes.xls", cFile::fmWrite))
- {
- LOG("Cannot write to file Biomes.xls. Statistics not written.");
- return;
- }
- double TotalColumns = (double)(m_CombinedStats.m_BiomeNumChunks) * 16 * 16 / 100; // Total number of columns processed; convert into percent
- if (TotalColumns < 1)
- {
- // Avoid division by zero
- TotalColumns = 1;
- }
- for (int i = 0; i <= 255; i++)
- {
- AString Line;
- Printf(Line, "%s\t%d\t%llu\t%.05f\n", GetBiomeString(i), i, m_CombinedStats.m_BiomeCounts[i], ((double)(m_CombinedStats.m_BiomeCounts[i])) / TotalColumns);
- f.Write(Line.c_str(), Line.length());
- }
-}
-
-
-
-
-
-void cStatisticsFactory::SaveBlockTypes(void)
-{
- cFile f;
- if (!f.Open("BlockTypes.xls", cFile::fmWrite))
- {
- LOG("Cannot write to file Biomes.xls. Statistics not written.");
- return;
- }
- double TotalBlocks = ((double)(m_CombinedStats.m_BlockNumChunks)) * 16 * 16 * 256 / 100; // Total number of blocks processed; convert into percent
- if (TotalBlocks < 1)
- {
- // Avoid division by zero
- TotalBlocks = 1;
- }
- for (int i = 0; i <= 255; i++)
- {
- UInt64 Count = 0;
- for (int Biome = 0; Biome <= 255; ++Biome)
- {
- Count += m_CombinedStats.m_BlockCounts[Biome][i];
- }
- AString Line;
- Printf(Line, "%s\t%d\t%llu\t%.08f\n", GetBlockTypeString(i), i, Count, ((double)Count) / TotalBlocks);
- f.Write(Line.c_str(), Line.length());
- }
-}
-
-
-
-
-
-void cStatisticsFactory::SaveBiomeBlockTypes(void)
-{
- // Export as two tables: biomes 0-127 and 128-255, because OpenOffice doesn't support more than 256 columns
- cFile f;
- if (!f.Open("BiomeBlockTypes.xls", cFile::fmWrite))
- {
- LOG("Cannot write to file BiomeBlockTypes.xls. Statistics not written.");
- return;
- }
-
- AString FileHeader("Biomes 0-127:\n");
- f.Write(FileHeader.c_str(), FileHeader.length());
-
- AString Header("BlockType\tBlockType");
- for (int Biome = 0; Biome <= 127; Biome++)
- {
- const char * BiomeName = GetBiomeString(Biome);
- if ((BiomeName != NULL) && (BiomeName[0] != 0))
- {
- AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome);
- }
- else
- {
- AppendPrintf(Header, "\t%d", Biome);
- }
- }
- Header.append("\n");
- f.Write(Header.c_str(), Header.length());
-
- for (int BlockType = 0; BlockType <= 255; BlockType++)
- {
- AString Line;
- Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType);
- for (int Biome = 0; Biome <= 127; Biome++)
- {
- AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]);
- }
- Line.append("\n");
- f.Write(Line.c_str(), Line.length());
- }
-
- Header.assign("\n\nBiomes 127-255:\nBlockType\tBlockType");
- for (int Biome = 0; Biome <= 127; Biome++)
- {
- const char * BiomeName = GetBiomeString(Biome);
- if ((BiomeName != NULL) && (BiomeName[0] != 0))
- {
- AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome);
- }
- else
- {
- AppendPrintf(Header, "\t%d", Biome);
- }
- }
- Header.append("\n");
- f.Write(Header.c_str(), Header.length());
-
- for (int BlockType = 0; BlockType <= 255; BlockType++)
- {
- AString Line;
- Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType);
- for (int Biome = 128; Biome <= 255; Biome++)
- {
- AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]);
- }
- Line.append("\n");
- f.Write(Line.c_str(), Line.length());
- }
-}
-
-
-
-
-
-
-void cStatisticsFactory::SaveStatistics(void)
-{
- cFile f;
- if (!f.Open("Statistics.txt", cFile::fmWrite))
- {
- LOG("Cannot write to file Statistics.txt. Statistics not written.");
- return;
- }
-
- int Elapsed = (clock() - m_BeginTick) / CLOCKS_PER_SEC;
- f.Printf("Time elapsed: %d seconds (%d hours, %d minutes and %d seconds)\n", Elapsed, Elapsed / 3600, (Elapsed / 60) % 60, Elapsed % 60);
- f.Printf("Total chunks processed: %llu\n", m_CombinedStats.m_TotalChunks);
- if (Elapsed > 0)
- {
- f.Printf("Chunk processing speed: %.02f chunks per second\n", (double)(m_CombinedStats.m_TotalChunks) / Elapsed);
- }
- f.Printf("Biomes counted for %llu chunks.\n", m_CombinedStats.m_BiomeNumChunks);
- f.Printf("Blocktypes counted for %llu chunks.\n", m_CombinedStats.m_BlockNumChunks);
- f.Printf("Total blocks counted: %llu\n", m_CombinedStats.m_BlockNumChunks * 16 * 16 * 256);
- f.Printf("Total biomes counted: %llu\n", m_CombinedStats.m_BiomeNumChunks * 16 * 16);
- f.Printf("Total entities counted: %llu\n", m_CombinedStats.m_NumEntities);
- f.Printf("Total tile entities counted: %llu\n", m_CombinedStats.m_NumTileEntities);
- f.Printf("Total tile ticks counted: %llu\n", m_CombinedStats.m_NumTileTicks);
- f.Printf("Chunk coord ranges:\n");
- f.Printf("\tX: %d .. %d\n", m_CombinedStats.m_MinChunkX, m_CombinedStats.m_MaxChunkX);
- f.Printf("\tZ: %d .. %d\n", m_CombinedStats.m_MinChunkZ, m_CombinedStats.m_MaxChunkZ);
-}
-
-
-
-
-
-void cStatisticsFactory::SaveSpawners(void)
-{
- cFile f;
- if (!f.Open("Spawners.xls", cFile::fmWrite))
- {
- LOG("Cannot write to file Spawners.xls. Statistics not written.");
- return;
- }
-
- f.Printf("Entity type\tTotal count\tCount per chunk\n");
- for (int i = 0; i < entMax; i++)
- {
- f.Printf("%s\t%llu\t%0.4f\n", GetEntityTypeString((eEntityType)i), m_CombinedStats.m_SpawnerEntity[i], (double)(m_CombinedStats.m_SpawnerEntity[i]) / m_CombinedStats.m_BlockNumChunks);
- }
-}
-
-
-
-
+
+// Statistics.cpp
+
+// Implements the various statistics-collecting classes
+
+#include "Globals.h"
+#include "Statistics.h"
+#include "../../source/WorldStorage/FastNBT.h"
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStatistics::cStats:
+
+cStatistics::cStats::cStats(void) :
+ m_TotalChunks(0),
+ m_BiomeNumChunks(0),
+ m_BlockNumChunks(0),
+ m_NumEntities(0),
+ m_NumTileEntities(0),
+ m_NumTileTicks(0),
+ m_MinChunkX(0x7fffffff),
+ m_MaxChunkX(0x80000000),
+ m_MinChunkZ(0x7fffffff),
+ m_MaxChunkZ(0x80000000)
+{
+ memset(m_BiomeCounts, 0, sizeof(m_BiomeCounts));
+ memset(m_BlockCounts, 0, sizeof(m_BlockCounts));
+ memset(m_SpawnerEntity, 0, sizeof(m_SpawnerEntity));
+}
+
+
+
+
+
+void cStatistics::cStats::Add(const cStatistics::cStats & a_Stats)
+{
+ for (int i = 0; i <= 255; i++)
+ {
+ m_BiomeCounts[i] += a_Stats.m_BiomeCounts[i];
+ }
+ for (int i = 0; i <= 255; i++)
+ {
+ for (int j = 0; j <= 255; j++)
+ {
+ m_BlockCounts[i][j] += a_Stats.m_BlockCounts[i][j];
+ }
+ }
+ for (int i = 0; i < ARRAYCOUNT(m_SpawnerEntity); i++)
+ {
+ m_SpawnerEntity[i] += a_Stats.m_SpawnerEntity[i];
+ }
+ m_BiomeNumChunks += a_Stats.m_BiomeNumChunks;
+ m_BlockNumChunks += a_Stats.m_BlockNumChunks;
+ m_TotalChunks += a_Stats.m_TotalChunks;
+ m_NumEntities += a_Stats.m_NumEntities;
+ m_NumTileEntities += a_Stats.m_NumTileEntities;
+ m_NumTileTicks += a_Stats.m_NumTileTicks;
+ UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ);
+ UpdateCoordsRange(a_Stats.m_MinChunkX, a_Stats.m_MinChunkZ);
+}
+
+
+
+
+
+void cStatistics::cStats::UpdateCoordsRange(int a_ChunkX, int a_ChunkZ)
+{
+ if (a_ChunkX < m_MinChunkX)
+ {
+ m_MinChunkX = a_ChunkX;
+ }
+ if (a_ChunkX > m_MaxChunkX)
+ {
+ m_MaxChunkX = a_ChunkX;
+ }
+ if (a_ChunkZ < m_MinChunkZ)
+ {
+ m_MinChunkZ = a_ChunkZ;
+ }
+ if (a_ChunkZ > m_MaxChunkZ)
+ {
+ m_MaxChunkZ = a_ChunkZ;
+ }
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStatistics:
+
+cStatistics::cStatistics(void)
+{
+}
+
+
+
+
+
+bool cStatistics::OnNewChunk(int a_ChunkX, int a_ChunkZ)
+{
+ m_Stats.m_TotalChunks++;
+ m_Stats.UpdateCoordsRange(a_ChunkX, a_ChunkZ);
+ m_IsBiomesValid = false;
+ m_IsFirstSectionInChunk = true;
+ return false;
+}
+
+
+
+
+
+bool cStatistics::OnBiomes(const unsigned char * a_BiomeData)
+{
+ for (int i = 0; i < 16 * 16; i++)
+ {
+ m_Stats.m_BiomeCounts[a_BiomeData[i]] += 1;
+ }
+ m_Stats.m_BiomeNumChunks += 1;
+ memcpy(m_BiomeData, a_BiomeData, sizeof(m_BiomeData));
+ m_IsBiomesValid = true;
+ return false;
+}
+
+
+
+
+
+
+bool cStatistics::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
+)
+{
+ if (!m_IsBiomesValid)
+ {
+ // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays
+ return true;
+ }
+
+ for (int y = 0; y < 16; y++)
+ {
+ for (int z = 0; z < 16; z++)
+ {
+ for (int x = 0; x < 16; x++)
+ {
+ unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype
+ unsigned char BlockType = cChunkDef::GetBlock(a_BlockTypes, x, y, z);
+ m_Stats.m_BlockCounts[Biome][BlockType] += 1;
+ }
+ }
+ }
+
+ m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0;
+ m_IsFirstSectionInChunk = false;
+
+ return false;
+}
+
+
+
+
+
+bool cStatistics::OnEmptySection(unsigned char a_Y)
+{
+ if (!m_IsBiomesValid)
+ {
+ // The current biome data is not valid, we don't have the means for sorting the BlockTypes into per-biome arrays
+ return true;
+ }
+
+ // Add air to all columns:
+ for (int z = 0; z < 16; z++)
+ {
+ for (int x = 0; x < 16; x++)
+ {
+ unsigned char Biome = m_BiomeData[x + 16 * z]; // Cannot use cChunkDef, different datatype
+ m_Stats.m_BlockCounts[Biome][0] += 16; // 16 blocks in a column, all air
+ }
+ }
+
+ m_Stats.m_BlockNumChunks += m_IsFirstSectionInChunk ? 1 : 0;
+ m_IsFirstSectionInChunk = false;
+
+ return false;
+}
+
+
+
+
+
+bool cStatistics::OnEntity(
+ const AString & a_EntityType,
+ double a_PosX, double a_PosY, double a_PosZ,
+ double a_SpeedX, double a_SpeedY, double a_SpeedZ,
+ float a_Yaw, float a_Pitch,
+ float a_FallDistance,
+ short a_FireTicksLeft,
+ short a_AirTicks,
+ char a_IsOnGround,
+ cParsedNBT & a_NBT,
+ int a_NBTTag
+)
+{
+ m_Stats.m_NumEntities += 1;
+
+ // TODO
+
+ return false;
+}
+
+
+
+
+
+bool cStatistics::OnTileEntity(
+ const AString & a_EntityType,
+ int a_PosX, int a_PosY, int a_PosZ,
+ cParsedNBT & a_NBT,
+ int a_NBTTag
+)
+{
+ m_Stats.m_NumTileEntities += 1;
+
+ if (a_EntityType == "MobSpawner")
+ {
+ OnSpawner(a_NBT, a_NBTTag);
+ }
+
+ return false;
+}
+
+
+
+
+
+bool cStatistics::OnTileTick(
+ int a_BlockType,
+ int a_TicksLeft,
+ int a_PosX, int a_PosY, int a_PosZ
+)
+{
+ m_Stats.m_NumTileTicks += 1;
+ return false;
+}
+
+
+
+
+
+void cStatistics::OnSpawner(cParsedNBT & a_NBT, int a_TileEntityTag)
+{
+ int EntityIDTag = a_NBT.FindChildByName(a_TileEntityTag, "EntityId");
+ if ((EntityIDTag < 0) || (a_NBT.GetType(EntityIDTag) != TAG_String))
+ {
+ return;
+ }
+ eEntityType Ent = GetEntityType(a_NBT.GetString(EntityIDTag));
+ if (Ent < ARRAYCOUNT(m_Stats.m_SpawnerEntity))
+ {
+ m_Stats.m_SpawnerEntity[Ent] += 1;
+ }
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStatisticsFactory:
+
+cStatisticsFactory::cStatisticsFactory(void) :
+ m_BeginTick(clock())
+{
+}
+
+
+
+
+
+cStatisticsFactory::~cStatisticsFactory()
+{
+ // Join the results together:
+ LOG("cStatistics:");
+ LOG(" Joining results...");
+ JoinResults();
+ LOG(" Total %llu chunks went through", m_CombinedStats.m_TotalChunks);
+ LOG(" Biomes processed for %llu chunks", m_CombinedStats.m_BiomeNumChunks);
+
+ // Check the number of blocks processed
+ UInt64 TotalBlocks = 0;
+ for (int i = 0; i <= 255; i++)
+ {
+ for (int j = 0; j < 255; j++)
+ {
+ TotalBlocks += m_CombinedStats.m_BlockCounts[i][j];
+ }
+ }
+ UInt64 ExpTotalBlocks = m_CombinedStats.m_BlockNumChunks * 16LL * 16LL * 256LL;
+ LOG(" BlockIDs processed for %llu chunks, %llu blocks (exp %llu; %s)", m_CombinedStats.m_BlockNumChunks, TotalBlocks, ExpTotalBlocks, (TotalBlocks == ExpTotalBlocks) ? "match" : "failed");
+
+ // Save statistics:
+ LOG(" Saving statistics into files:");
+ LOG(" Statistics.txt");
+ SaveStatistics();
+ LOG(" Biomes.xls");
+ SaveBiomes();
+ LOG(" BlockTypes.xls");
+ SaveBlockTypes();
+ LOG(" BiomeBlockTypes.xls");
+ SaveBiomeBlockTypes();
+ LOG(" Spawners.xls");
+ SaveSpawners();
+}
+
+
+
+
+
+void cStatisticsFactory::JoinResults(void)
+{
+ for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr)
+ {
+ m_CombinedStats.Add(((cStatistics *)(*itr))->GetStats());
+ } // for itr - m_Callbacks[]
+}
+
+
+
+
+
+void cStatisticsFactory::SaveBiomes(void)
+{
+ cFile f;
+ if (!f.Open("Biomes.xls", cFile::fmWrite))
+ {
+ LOG("Cannot write to file Biomes.xls. Statistics not written.");
+ return;
+ }
+ double TotalColumns = (double)(m_CombinedStats.m_BiomeNumChunks) * 16 * 16 / 100; // Total number of columns processed; convert into percent
+ if (TotalColumns < 1)
+ {
+ // Avoid division by zero
+ TotalColumns = 1;
+ }
+ for (int i = 0; i <= 255; i++)
+ {
+ AString Line;
+ Printf(Line, "%s\t%d\t%llu\t%.05f\n", GetBiomeString(i), i, m_CombinedStats.m_BiomeCounts[i], ((double)(m_CombinedStats.m_BiomeCounts[i])) / TotalColumns);
+ f.Write(Line.c_str(), Line.length());
+ }
+}
+
+
+
+
+
+void cStatisticsFactory::SaveBlockTypes(void)
+{
+ cFile f;
+ if (!f.Open("BlockTypes.xls", cFile::fmWrite))
+ {
+ LOG("Cannot write to file Biomes.xls. Statistics not written.");
+ return;
+ }
+ double TotalBlocks = ((double)(m_CombinedStats.m_BlockNumChunks)) * 16 * 16 * 256 / 100; // Total number of blocks processed; convert into percent
+ if (TotalBlocks < 1)
+ {
+ // Avoid division by zero
+ TotalBlocks = 1;
+ }
+ for (int i = 0; i <= 255; i++)
+ {
+ UInt64 Count = 0;
+ for (int Biome = 0; Biome <= 255; ++Biome)
+ {
+ Count += m_CombinedStats.m_BlockCounts[Biome][i];
+ }
+ AString Line;
+ Printf(Line, "%s\t%d\t%llu\t%.08f\n", GetBlockTypeString(i), i, Count, ((double)Count) / TotalBlocks);
+ f.Write(Line.c_str(), Line.length());
+ }
+}
+
+
+
+
+
+void cStatisticsFactory::SaveBiomeBlockTypes(void)
+{
+ // Export as two tables: biomes 0-127 and 128-255, because OpenOffice doesn't support more than 256 columns
+ cFile f;
+ if (!f.Open("BiomeBlockTypes.xls", cFile::fmWrite))
+ {
+ LOG("Cannot write to file BiomeBlockTypes.xls. Statistics not written.");
+ return;
+ }
+
+ AString FileHeader("Biomes 0-127:\n");
+ f.Write(FileHeader.c_str(), FileHeader.length());
+
+ AString Header("BlockType\tBlockType");
+ for (int Biome = 0; Biome <= 127; Biome++)
+ {
+ const char * BiomeName = GetBiomeString(Biome);
+ if ((BiomeName != NULL) && (BiomeName[0] != 0))
+ {
+ AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome);
+ }
+ else
+ {
+ AppendPrintf(Header, "\t%d", Biome);
+ }
+ }
+ Header.append("\n");
+ f.Write(Header.c_str(), Header.length());
+
+ for (int BlockType = 0; BlockType <= 255; BlockType++)
+ {
+ AString Line;
+ Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType);
+ for (int Biome = 0; Biome <= 127; Biome++)
+ {
+ AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]);
+ }
+ Line.append("\n");
+ f.Write(Line.c_str(), Line.length());
+ }
+
+ Header.assign("\n\nBiomes 127-255:\nBlockType\tBlockType");
+ for (int Biome = 0; Biome <= 127; Biome++)
+ {
+ const char * BiomeName = GetBiomeString(Biome);
+ if ((BiomeName != NULL) && (BiomeName[0] != 0))
+ {
+ AppendPrintf(Header, "\t%s (%d)", BiomeName, Biome);
+ }
+ else
+ {
+ AppendPrintf(Header, "\t%d", Biome);
+ }
+ }
+ Header.append("\n");
+ f.Write(Header.c_str(), Header.length());
+
+ for (int BlockType = 0; BlockType <= 255; BlockType++)
+ {
+ AString Line;
+ Printf(Line, "%s\t%d", GetBlockTypeString(BlockType), BlockType);
+ for (int Biome = 128; Biome <= 255; Biome++)
+ {
+ AppendPrintf(Line, "\t%llu", m_CombinedStats.m_BlockCounts[Biome][BlockType]);
+ }
+ Line.append("\n");
+ f.Write(Line.c_str(), Line.length());
+ }
+}
+
+
+
+
+
+
+void cStatisticsFactory::SaveStatistics(void)
+{
+ cFile f;
+ if (!f.Open("Statistics.txt", cFile::fmWrite))
+ {
+ LOG("Cannot write to file Statistics.txt. Statistics not written.");
+ return;
+ }
+
+ int Elapsed = (clock() - m_BeginTick) / CLOCKS_PER_SEC;
+ f.Printf("Time elapsed: %d seconds (%d hours, %d minutes and %d seconds)\n", Elapsed, Elapsed / 3600, (Elapsed / 60) % 60, Elapsed % 60);
+ f.Printf("Total chunks processed: %llu\n", m_CombinedStats.m_TotalChunks);
+ if (Elapsed > 0)
+ {
+ f.Printf("Chunk processing speed: %.02f chunks per second\n", (double)(m_CombinedStats.m_TotalChunks) / Elapsed);
+ }
+ f.Printf("Biomes counted for %llu chunks.\n", m_CombinedStats.m_BiomeNumChunks);
+ f.Printf("Blocktypes counted for %llu chunks.\n", m_CombinedStats.m_BlockNumChunks);
+ f.Printf("Total blocks counted: %llu\n", m_CombinedStats.m_BlockNumChunks * 16 * 16 * 256);
+ f.Printf("Total biomes counted: %llu\n", m_CombinedStats.m_BiomeNumChunks * 16 * 16);
+ f.Printf("Total entities counted: %llu\n", m_CombinedStats.m_NumEntities);
+ f.Printf("Total tile entities counted: %llu\n", m_CombinedStats.m_NumTileEntities);
+ f.Printf("Total tile ticks counted: %llu\n", m_CombinedStats.m_NumTileTicks);
+ f.Printf("Chunk coord ranges:\n");
+ f.Printf("\tX: %d .. %d\n", m_CombinedStats.m_MinChunkX, m_CombinedStats.m_MaxChunkX);
+ f.Printf("\tZ: %d .. %d\n", m_CombinedStats.m_MinChunkZ, m_CombinedStats.m_MaxChunkZ);
+}
+
+
+
+
+
+void cStatisticsFactory::SaveSpawners(void)
+{
+ cFile f;
+ if (!f.Open("Spawners.xls", cFile::fmWrite))
+ {
+ LOG("Cannot write to file Spawners.xls. Statistics not written.");
+ return;
+ }
+
+ f.Printf("Entity type\tTotal count\tCount per chunk\n");
+ for (int i = 0; i < entMax; i++)
+ {
+ f.Printf("%s\t%llu\t%0.4f\n", GetEntityTypeString((eEntityType)i), m_CombinedStats.m_SpawnerEntity[i], (double)(m_CombinedStats.m_SpawnerEntity[i]) / m_CombinedStats.m_BlockNumChunks);
+ }
+}
+
+
+
+