Cuberite
A lightweight, fast and extensible game server for Minecraft
DelayedFluidSimulator.cpp
Go to the documentation of this file.
1 
2 // DelayedFluidSimulator.cpp
3 
4 // Interfaces to the cDelayedFluidSimulator class representing a fluid simulator that has a configurable delay
5 // before simulating a block. Each tick it takes a consecutive delay "slot" and simulates only blocks in that slot.
6 
7 #include "Globals.h"
8 
10 #include "../World.h"
11 #include "../Chunk.h"
12 
13 
14 
15 
16 
18 // cDelayedFluidSimulatorChunkData::cSlot
19 
20 bool cDelayedFluidSimulatorChunkData::cSlot::Add(int a_RelX, int a_RelY, int a_RelZ)
21 {
22  ASSERT(a_RelZ >= 0);
23  ASSERT(a_RelZ < static_cast<int>(ARRAYCOUNT(m_Blocks)));
24 
25  cCoordWithIntVector & Blocks = m_Blocks[a_RelZ];
26  int Index = cChunkDef::MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ);
27  for (cCoordWithIntVector::const_iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr)
28  {
29  if (itr->Data == Index)
30  {
31  // Already present
32  return false;
33  }
34  } // for itr - Blocks[]
35  Blocks.push_back(cCoordWithInt(a_RelX, a_RelY, a_RelZ, Index));
36  return true;
37 }
38 
39 
40 
41 
42 
44 // cDelayedFluidSimulatorChunkData:
45 
47  m_Slots(new cSlot[a_TickDelay])
48 {
49 }
50 
51 
52 
53 
54 
56 {
57  delete[] m_Slots;
58  m_Slots = nullptr;
59 }
60 
61 
62 
63 
64 
66 // cDelayedFluidSimulator:
67 
68 cDelayedFluidSimulator::cDelayedFluidSimulator(cWorld & a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay) :
69  super(a_World, a_Fluid, a_StationaryFluid),
70  m_TickDelay(a_TickDelay),
71  m_AddSlotNum(a_TickDelay - 1),
72  m_SimSlotNum(0),
73  m_TotalBlocks(0)
74 {
75 }
76 
77 
78 
79 
80 
82 {
83  if ((a_Block.y < 0) || (a_Block.y >= cChunkDef::Height))
84  {
85  // Not inside the world (may happen when rclk with a full bucket - the client sends Y = -1)
86  return;
87  }
88 
89  if ((a_Chunk == nullptr) || !a_Chunk->IsValid())
90  {
91  return;
92  }
93 
94  int RelX = a_Block.x - a_Chunk->GetPosX() * cChunkDef::Width;
95  int RelZ = a_Block.z - a_Chunk->GetPosZ() * cChunkDef::Width;
96  BLOCKTYPE BlockType = a_Chunk->GetBlock(RelX, a_Block.y, RelZ);
97  if (BlockType != m_FluidBlock)
98  {
99  return;
100  }
101 
102  auto ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData();
103  cDelayedFluidSimulatorChunkData * ChunkData = static_cast<cDelayedFluidSimulatorChunkData *>(ChunkDataRaw);
105 
106  // Add, if not already present:
107  if (!Slot.Add(RelX, a_Block.y, RelZ))
108  {
109  return;
110  }
111 
112  ++m_TotalBlocks;
113 }
114 
115 
116 
117 
118 
120 {
122  m_SimSlotNum += 1;
123  if (m_SimSlotNum >= m_TickDelay)
124  {
125  m_SimSlotNum = 0;
126  }
127 }
128 
129 
130 
131 
132 
133 void cDelayedFluidSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
134 {
135  auto ChunkDataRaw = (m_FluidBlock == E_BLOCK_WATER) ? a_Chunk->GetWaterSimulatorData() : a_Chunk->GetLavaSimulatorData();
136  cDelayedFluidSimulatorChunkData * ChunkData = static_cast<cDelayedFluidSimulatorChunkData *>(ChunkDataRaw);
138 
139  // Simulate all the blocks in the scheduled slot:
140  for (size_t i = 0; i < ARRAYCOUNT(Slot.m_Blocks); i++)
141  {
142  cCoordWithIntVector & Blocks = Slot.m_Blocks[i];
143  if (Blocks.empty())
144  {
145  continue;
146  }
147  for (cCoordWithIntVector::iterator itr = Blocks.begin(), end = Blocks.end(); itr != end; ++itr)
148  {
149  SimulateBlock(a_Chunk, itr->x, itr->y, itr->z);
150  }
151  m_TotalBlocks -= static_cast<int>(Blocks.size());
152  Blocks.clear();
153  }
154 }
155 
156 
157 
158 
bool IsValid(void) const
Returns true iff the chunk block data is valid (loaded / generated)
Definition: Chunk.h:72
T x
Definition: Vector3.h:17
BLOCKTYPE m_FluidBlock
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
virtual void SimulateBlock(cChunk *a_Chunk, int a_RelX, int a_RelY, int a_RelZ)=0
Called from SimulateChunk() to simulate each block in one slot of blocks.
static const int Width
Definition: ChunkDef.h:134
virtual void Simulate(float a_Dt) override
Called in each tick, a_Dt is the time passed since the last tick, in msec.
cFluidSimulatorData * GetLavaSimulatorData(void)
Definition: Chunk.h:531
Definition: Chunk.h:49
static int MakeIndexNoCheck(int x, int y, int z)
Definition: ChunkDef.h:275
T y
Definition: Vector3.h:17
cSlot * m_Slots
Slots, one for each delay tick, each containing the blocks to simulate.
virtual void AddBlock(Vector3i a_Block, cChunk *a_Chunk) override
Called to simulate a new block.
T z
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
bool Add(int a_RelX, int a_RelY, int a_RelZ)
Adds the specified block unless already present; returns true if added, false if the block was alread...
Definition: World.h:65
int GetPosX(void) const
Definition: Chunk.h:150
#define ASSERT(x)
Definition: Globals.h:335
virtual void SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX, int a_ChunkZ, cChunk *a_Chunk) override
Called in each tick for each chunk, a_Dt is the time passed since the last tick, in msec; direct acce...
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:177
cCoordWithIntVector m_Blocks[16]
Array of block containers, each item stores blocks for one Z coord Int param is the block index (for ...
std::vector< cCoordWithInt > cCoordWithIntVector
Definition: ChunkDef.h:669
cFluidSimulatorData * GetWaterSimulatorData(void)
Definition: Chunk.h:530
int GetPosZ(void) const
Definition: Chunk.h:151
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:290
cDelayedFluidSimulator(cWorld &a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, int a_TickDelay)
cCoordWithData< int > cCoordWithInt
Definition: ChunkDef.h:665