summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AnvilStats/AnvilStats.cpp7
-rw-r--r--AnvilStats/AnvilStats.vcproj8
-rw-r--r--AnvilStats/BiomeMap.cpp172
-rw-r--r--AnvilStats/BiomeMap.h69
4 files changed, 255 insertions, 1 deletions
diff --git a/AnvilStats/AnvilStats.cpp b/AnvilStats/AnvilStats.cpp
index 1682f76f0..7a7c34f98 100644
--- a/AnvilStats/AnvilStats.cpp
+++ b/AnvilStats/AnvilStats.cpp
@@ -4,8 +4,9 @@
// Implements the main app entrypoint
#include "Globals.h"
-#include "Statistics.h"
#include "Processor.h"
+#include "Statistics.h"
+#include "BiomeMap.h"
@@ -16,6 +17,9 @@ int main(int argc, char * argv[])
if (argc < 2)
{
LOG("Usage: %s <method number> [<world folder>]", argv[0]);
+ LOG("Available methods:");
+ LOG(" 0 - statistics");
+ LOG(" 1 - biome map");
LOG("\nNo method number present, aborting.");
return -1;
}
@@ -34,6 +38,7 @@ int main(int argc, char * argv[])
switch (atol(argv[1]))
{
case 0: Factory = new cStatisticsFactory; break;
+ case 1: Factory = new cBiomeMapFactory; break;
default:
{
LOG("Unknown method \"%s\", aborting.", argv[1]);
diff --git a/AnvilStats/AnvilStats.vcproj b/AnvilStats/AnvilStats.vcproj
index 4bc494bf7..7919f8105 100644
--- a/AnvilStats/AnvilStats.vcproj
+++ b/AnvilStats/AnvilStats.vcproj
@@ -183,6 +183,14 @@
>
</File>
<File
+ RelativePath=".\BiomeMap.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\BiomeMap.h"
+ >
+ </File>
+ <File
RelativePath=".\Callback.h"
>
</File>
diff --git a/AnvilStats/BiomeMap.cpp b/AnvilStats/BiomeMap.cpp
new file mode 100644
index 000000000..eca235c5f
--- /dev/null
+++ b/AnvilStats/BiomeMap.cpp
@@ -0,0 +1,172 @@
+
+// BiomeMap.cpp
+
+// Implements the cBiomeMap class representing a cCallback descendant that draws a map of biomes for the world
+
+#include "Globals.h"
+#include "BiomeMap.h"
+
+
+
+
+
+static const int g_BiomePalette[] =
+{
+ // ARGB:
+ 0xff0000ff, /* Ocean */
+ 0xff00cf3f, /* Plains */
+ 0xffffff00, /* Desert */
+ 0xff7f7f7f, /* Extreme Hills */
+ 0xff00cf00, /* Forest */
+ 0xff007f3f, /* Taiga */
+ 0xff3f7f00, /* Swampland */
+ 0xff003fff, /* River */
+ 0xff7f0000, /* Hell */
+ 0xff007fff, /* Sky */
+ 0xff3f3fff, /* Frozen Ocean */
+ 0xff3f3fff, /* Frozen River */
+ 0xff7fffcf, /* Ice Plains */
+ 0xff3fcf7f, /* Ice Mountains */
+ 0xffcf00cf, /* Mushroom Island */
+ 0xff7f00ff, /* Mushroom Island Shore */
+ 0xffffff3f, /* Beach */
+ 0xffcfcf00, /* Desert Hills */
+ 0xff00cf3f, /* Forest Hills */
+ 0xff006f1f, /* Taiga Hills */
+ 0xff7f8f7f, /* Extreme Hills Edge */
+ 0xff004f00, /* Jungle */
+ 0xff003f00, /* Jungle Hills */
+} ;
+
+
+
+
+
+static const unsigned char g_BMPHeader[] =
+{
+ 0x42, 0x4D, 0x36, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+} ;
+
+
+
+
+
+cBiomeMap::cBiomeMap(void) :
+ m_CurrentRegionX(0),
+ m_CurrentRegionZ(0),
+ m_IsCurrentRegionValid(false)
+{
+}
+
+
+
+
+
+void cBiomeMap::Finish(void)
+{
+ if (m_IsCurrentRegionValid)
+ {
+ StartNewRegion(0, 0);
+ }
+}
+
+
+
+
+
+bool cBiomeMap::OnNewChunk(int a_ChunkX, int a_ChunkZ)
+{
+ int RegionX = (a_ChunkX < 0) ? (a_ChunkX - 31) / 32 : a_ChunkX / 32;
+ int RegionZ = (a_ChunkZ < 0) ? (a_ChunkZ - 31) / 32 : a_ChunkZ / 32;
+ if ((RegionX != m_CurrentRegionX) || (RegionZ != m_CurrentRegionZ))
+ {
+ if (m_IsCurrentRegionValid)
+ {
+ StartNewRegion(RegionX, RegionZ);
+ }
+ m_CurrentRegionX = RegionX;
+ m_CurrentRegionZ = RegionZ;
+ }
+ m_IsCurrentRegionValid = true;
+ m_CurrentChunkX = a_ChunkX;
+ m_CurrentChunkZ = a_ChunkZ;
+ m_CurrentChunkOffX = m_CurrentChunkX - m_CurrentRegionX * 32;
+ m_CurrentChunkOffZ = m_CurrentChunkZ - m_CurrentRegionZ * 32;
+ return false;
+}
+
+
+
+
+
+bool cBiomeMap::OnBiomes(const unsigned char * a_BiomeData)
+{
+ ASSERT(m_CurrentChunkOffX >= 0);
+ ASSERT(m_CurrentChunkOffX < 32);
+ ASSERT(m_CurrentChunkOffZ >= 0);
+ ASSERT(m_CurrentChunkOffZ < 32);
+ char * BaseBiomes = m_Biomes + m_CurrentChunkOffZ * 16 * 512 + m_CurrentChunkOffX * 16;
+ for (int z = 0; z < 16; z++)
+ {
+ char * Row = BaseBiomes + z * 512;
+ memcpy(Row, a_BiomeData + z * 16, 16);
+ } // for z
+ return true;
+}
+
+
+
+
+
+void cBiomeMap::StartNewRegion(int a_RegionX, int a_RegionZ)
+{
+ AString FileName;
+ Printf(FileName, "Biomes.%d.%d.bmp", m_CurrentRegionX, m_CurrentRegionZ);
+ cFile f;
+ if (!f.Open(FileName, cFile::fmWrite))
+ {
+ LOG("Cannot open file \"%s\" for writing the biome map. Data for this region lost.", FileName.c_str());
+ }
+ else
+ {
+ f.Write(g_BMPHeader, sizeof(g_BMPHeader));
+ for (int z = 0; z < 512; z++)
+ {
+ int RowData[512];
+ unsigned char * BiomeRow = (unsigned char *)m_Biomes + z * 512;
+ for (int x = 0; x < 512; x++)
+ {
+ RowData[x] = g_BiomePalette[BiomeRow[x]];
+ }
+ f.Write(RowData, sizeof(RowData));
+ } // for z
+ }
+
+ memset(m_Biomes, 0, sizeof(m_Biomes));
+ m_CurrentRegionX = a_RegionX;
+ m_CurrentRegionZ = a_RegionZ;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cBiomeMapFactory:
+
+cBiomeMapFactory::~cBiomeMapFactory()
+{
+ // Force all threads to save their last regions:
+ for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr)
+ {
+ ((cBiomeMap *)(*itr))->Finish();
+ }
+ // TODO: Join all the files into one giant image file
+}
+
+
+
+
diff --git a/AnvilStats/BiomeMap.h b/AnvilStats/BiomeMap.h
new file mode 100644
index 000000000..170216f46
--- /dev/null
+++ b/AnvilStats/BiomeMap.h
@@ -0,0 +1,69 @@
+
+// BiomeMap.h
+
+// Interfaces to the cBiomeMap class representing a cCallback descendant that draws a map of biomes for the world
+
+
+
+
+
+#pragma once
+
+#include "Callback.h"
+
+
+
+
+
+class cBiomeMap :
+ public cCallback
+{
+public:
+ cBiomeMap(void);
+
+ /// Saves the last region that it was processing
+ void Finish(void);
+
+protected:
+ int m_CurrentChunkX; // Absolute chunk coords
+ int m_CurrentChunkZ;
+ int m_CurrentChunkOffX; // Chunk offset from the start of the region
+ int m_CurrentChunkOffZ;
+ int m_CurrentRegionX;
+ int m_CurrentRegionZ;
+ bool m_IsCurrentRegionValid;
+ char m_Biomes[16 * 32 * 16 * 32]; // Biome map of the entire current region [x + 16 * 32 * z]
+
+ // 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;
+
+ void StartNewRegion(int a_RegionX, int a_RegionZ);
+} ;
+
+
+
+
+
+class cBiomeMapFactory :
+ public cCallbackFactory
+{
+public:
+ virtual ~cBiomeMapFactory();
+
+ virtual cCallback * CreateNewCallback(void)
+ {
+ return new cBiomeMap;
+ }
+
+} ;
+
+
+
+