summaryrefslogtreecommitdiffstats
path: root/src/Simulator/IncrementalRedstoneSimulator/RedstoneSimulatorChunkData.h
blob: f8e7eb46662b16000022c17e474bd56627bc1134 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

#pragma once

#include <stack>

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





struct PoweringData
{
public:
	PoweringData(BLOCKTYPE a_PoweringBlock, unsigned char a_PowerLevel) :
		PoweringBlock(a_PoweringBlock),
		PowerLevel(a_PowerLevel)
	{
	}

	PoweringData(void) :
		PoweringBlock(E_BLOCK_AIR),
		PowerLevel(0)
	{
	}

	BLOCKTYPE PoweringBlock;
	unsigned char PowerLevel;

	inline friend bool operator < (const PoweringData & Lhs, const PoweringData & Rhs)
	{
		return (
			(Lhs.PowerLevel < Rhs.PowerLevel) ||
			(
				(Lhs.PowerLevel == Rhs.PowerLevel) &&
				((Lhs.PoweringBlock == E_BLOCK_REDSTONE_WIRE) && (Rhs.PoweringBlock != E_BLOCK_REDSTONE_WIRE))
			)
		);
	}

	inline friend bool operator == (const PoweringData & Lhs, const PoweringData & Rhs)
	{
		return (Lhs.PowerLevel == Rhs.PowerLevel);
	}

	inline friend bool operator != (const PoweringData & Lhs, const PoweringData & Rhs)
	{
		return !operator ==(Lhs, Rhs);
	}
};





class cIncrementalRedstoneSimulatorChunkData final : public cRedstoneSimulatorChunkData
{
public:

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

	auto & GetActiveBlocks()
	{
		return m_ActiveBlocks;
	}

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

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

	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);
	}

	PoweringData ExchangeUpdateOncePowerData(const Vector3i & a_Position, PoweringData a_PoweringData)
	{
		auto Result = m_CachedPowerLevels.find(a_Position);
		if (Result == m_CachedPowerLevels.end())
		{
			m_CachedPowerLevels[a_Position] = a_PoweringData;
			return PoweringData();
		}
		std::swap(Result->second, a_PoweringData);
		return a_PoweringData;
	}

	/** 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, short, VectorHasher<int>> WireStates;

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

	/** 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, PoweringData, VectorHasher<int>> m_CachedPowerLevels;

	friend class cRedstoneHandlerFactory;

};