summaryrefslogtreecommitdiffstats
path: root/AnvilStats/Callback.h
blob: 66d6bcfae5976726c3798be9f4c4062250b15665 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

// Callback.h

// Interfaces to the cCallback base class used as the base class for all statistical callbacks





#pragma once





/** The base class for all chunk-processor callbacks, declares the interface.
The processor calls each virtual function in the order they are declared here with the specified args.
If the function returns true, the processor moves on to next chunk and starts calling the callbacks again from start with
the new chunk data.
So if a statistics collector doesn't need data decompression at all, it can stop the processor from doing so early-enough
and still get meaningful data.
A callback is guaranteed to run in a single thread and always the same thread.
A callback is guaranteed to run on all chunks in a region and one region is guaranteed to be handled by only callback.
*/
class cCallback abstract
{
public:
	virtual ~cCallback() {}  // Force a virtual destructor in each descendant
	
	/// Called to inform the stats module of the chunk coords for newly processing chunk
	virtual bool OnNewChunk(int a_ChunkX, int a_ChunkZ) = 0;
	
	/// Called to inform about the chunk's data offset in the file (chunk mini-header), the number of sectors it uses and the timestamp field value
	virtual bool OnHeader(int a_FileOffset, unsigned char a_NumSectors, int a_Timestamp) { return true; }
	
	/// Called to inform of the compressed chunk data size and position in the file (offset from file start to the actual data)
	virtual bool OnCompressedDataSizePos(int a_CompressedDataSize, int a_DataOffset, char a_CompressionMethod) { return true; }
	
	/// Just in case you wanted to process the NBT yourself ;)
	virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) { return true; }
	
	/// The chunk's NBT should specify chunk coords, these are sent here:
	virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) { return true; }
	
	/// The chunk contains a LastUpdate value specifying the last tick in which it was saved.
	virtual bool OnLastUpdate(Int64 a_LastUpdate) { return true; }
	
	virtual bool OnTerrainPopulated(bool a_Populated) { return true; }
	
	virtual bool OnBiomes(const unsigned char * a_BiomeData) { return true; }
	
	virtual bool OnHeightMap(const int * a_HeightMap) { return true; }
	
	/** If there is data for the section, this callback is called; otherwise OnEmptySection() is called instead.
	All OnSection() callbacks are called first, and only then all the remaining sections are reported in OnEmptySection().
	*/
	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
	) { return true; }
	
	/** If there is no data for a section, this callback is called; otherwise OnSection() is called instead. 
	OnEmptySection() callbacks are called after all OnSection() callbacks.
	*/
	virtual bool OnEmptySection(unsigned char a_Y) { return false; }
	
	// TODO: entities, tile-entities, tile-ticks
} ;

typedef std::vector<cCallback *> cCallbacks;





/** The base class for a factory that creates callback objects for separate threads.
The processor creates a callback for each thread on which it runs using this factory.
The factory is guaranteed to be called from a single thread.
The factory keeps track of all the callbacks that it has created and deletes them when destructed
*/
class cCallbackFactory
{
public:
	virtual ~cCallbackFactory()
	{
		for (cCallbacks::iterator itr = m_Callbacks.begin(), end = m_Callbacks.end(); itr != end; ++itr)
		{
			delete *itr;
		}
	}
	
	/// Descendants override this method to return the correct callback type
	virtual cCallback * CreateNewCallback(void) = 0;
	
	/// cProcessor uses this method to request a new callback
	cCallback * GetNewCallback(void)
	{
		cCallback * Callback = CreateNewCallback();
		if (Callback != NULL)
		{
			m_Callbacks.push_back(Callback);
		}
		return Callback;
	}
	
protected:
	cCallbacks m_Callbacks;
} ;