summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h
blob: f9545d99735784365cdce43851939bb045fd16ea (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

#pragma once

#include <stack>

#include "Chunk.h"
#include "BlockState.h"
#include "Simulator/RedstoneSimulator.h"





using PowerLevel = unsigned char;





class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData
{
public:

	void WakeUp(const Vector3i & a_Position)
	{
		m_ActiveBlocks.push(a_Position);
	}

	auto & GetActiveBlocks()
	{
		return m_ActiveBlocks;
	}

	PowerLevel GetCachedPowerData(const Vector3i Position) const
	{
		auto Result = m_CachedPowerLevels.find(Position);
		return (Result == m_CachedPowerLevels.end()) ? 0 : Result->second;
	}

	void SetCachedPowerData(const Vector3i Position, const PowerLevel PowerLevel)
	{
		m_CachedPowerLevels[Position] = PowerLevel;
	}

	std::pair<int, bool> * GetMechanismDelayInfo(const Vector3i Position)
	{
		auto Result = m_MechanismDelays.find(Position);
		return (Result == m_MechanismDelays.end()) ? nullptr : &Result->second;
	}

	/** Erase all cached redstone data for position. */
	void ErasePowerData(const Vector3i Position)
	{
		m_CachedPowerLevels.erase(Position);
		m_MechanismDelays.erase(Position);
		AlwaysTickedPositions.erase(Position);
		WireStates.erase(Position);
		ObserverCache.erase(Position);
	}

	PowerLevel ExchangeUpdateOncePowerData(const Vector3i & a_Position, PowerLevel Power)
	{
		auto Result = m_CachedPowerLevels.find(a_Position);

		if (Result == m_CachedPowerLevels.end())
		{
			m_CachedPowerLevels[a_Position] = Power;
			return 0;
		}

		return std::exchange(Result->second, Power);
	}

	/** Adjust From-relative coordinates into To-relative coordinates. */
	inline static Vector3i RebaseRelativePosition(const cChunk & From, const cChunk & To, const Vector3i Position)
	{
		return
		{
			Position.x + (From.GetPosX() - To.GetPosX()) * cChunkDef::Width,
			Position.y,
			Position.z + (From.GetPosZ() - To.GetPosZ()) * cChunkDef::Width
		};
	}

	/** Temporary, should be chunk data: wire block store, to avoid recomputing states every time. */
	std::unordered_map<Vector3i, BlockState, VectorHasher<int>> WireStates;

	std::unordered_set<Vector3i, VectorHasher<int>> AlwaysTickedPositions;

	/** Structure storing an observer's last seen block. */
	std::unordered_map<Vector3i, std::pair<BLOCKTYPE, NIBBLETYPE>, VectorHasher<int>> ObserverCache;

	/** Structure storing position of mechanism + it's delay ticks (countdown) & if to power on. */
	std::unordered_map<Vector3i, std::pair<int, bool>, VectorHasher<int>> m_MechanismDelays;

private:

	std::stack<Vector3i, std::vector<Vector3i>> m_ActiveBlocks;

	// TODO: map<Vector3i, int> -> Position of torch + it's heat level

	std::unordered_map<Vector3i, PowerLevel, VectorHasher<int>> m_CachedPowerLevels;

	friend class cRedstoneHandlerFactory;
};