Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockSponge.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "BlockHandler.h"
5 
6 
7 
8 
9 
10 class cBlockSpongeHandler final :
11  public cBlockHandler
12 {
14 
15 public:
16 
17  using Super::Super;
18 
19 private:
20 
21  virtual void OnPlaced(
22  cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
23  Vector3i a_BlockPos,
24  BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
25  ) const override
26  {
27  OnNeighborChanged(a_ChunkInterface, a_BlockPos, BLOCK_FACE_NONE);
28  }
29 
30  virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
31  {
32  a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & a_Chunk) { CheckSoaked(cChunkDef::AbsoluteToRelative(a_BlockPos), a_Chunk); return true; });
33  }
34 
38  static void CheckSoaked(Vector3i a_Rel, cChunk & a_Chunk)
39  {
40  struct sSeed
41  {
42  sSeed(Vector3i pos, int d)
43  {
44  m_Pos = pos;
45  m_Depth = d;
46  }
47  Vector3i m_Pos;
48  int m_Depth;
49  };
50 
51  // Check if this is a dry sponge next to a water block.
52  NIBBLETYPE TargetMeta = a_Chunk.GetMeta(a_Rel.x, a_Rel.y, a_Rel.z);
53  if (TargetMeta != E_META_SPONGE_DRY)
54  {
55  return;
56  }
57 
58  const auto & WaterCheck = cSimulator::AdjacentOffsets;
59  const bool ShouldSoak = std::any_of(WaterCheck.cbegin(), WaterCheck.cend(), [a_Rel, &a_Chunk](Vector3i a_Offset)
60  {
61  return IsWet(a_Rel + a_Offset, a_Chunk);
62  });
63 
64  // Early return if the sponge isn't touching any water.
65  if (!ShouldSoak)
66  {
67  return;
68  }
69 
70  // Use a queue to hold blocks that we want to check, so our search is breadth-first.
71  std::queue<sSeed> Seeds;
72  int count = 0;
73  // Only go 7 blocks away from the center block.
74  const int maxDepth = 7;
75  // Start with the 6 blocks around the sponge.
76  for (unsigned int i = 0; i < 6; i++)
77  {
78  Seeds.emplace(a_Rel + WaterCheck[i], maxDepth - 1);
79  }
80 
81  // Keep checking blocks that are touching water blocks, or until 65 have been soaked up.
82  while (!Seeds.empty() && count < 65)
83  {
84  sSeed seed = Seeds.front();
85  Vector3i checkRel = seed.m_Pos;
86  if (IsWet(checkRel, a_Chunk))
87  {
88  count++;
89  DryUp(checkRel, a_Chunk);
90  if (seed.m_Depth > 0)
91  {
92  // If this block was water, and we haven't yet gone too far away,
93  // add its neighbors to the queue to check.
94  for (unsigned int i = 0; i < 6; i++)
95  {
96  Seeds.emplace(checkRel + WaterCheck[i], seed.m_Depth - 1);
97  }
98  }
99  }
100  Seeds.pop();
101  }
102 
103  a_Chunk.SetBlock(a_Rel, E_BLOCK_SPONGE, E_META_SPONGE_WET);
104  }
105 
106  static void DryUp(Vector3i a_Rel, cChunk & a_Chunk)
107  {
108  // TODO: support evaporating waterlogged blocks.
109  a_Chunk.UnboundedRelSetBlock(a_Rel.x, a_Rel.y, a_Rel.z, E_BLOCK_AIR, 0);
110  }
111 
112  static bool IsWet(Vector3i a_Rel, cChunk & a_Chunk)
113  {
114  // TODO: support detecting waterlogged blocks.
115  BLOCKTYPE Type;
116  return(a_Chunk.UnboundedRelGetBlockType(a_Rel.x, a_Rel.y, a_Rel.z, Type) && IsBlockWater(Type));
117  }
118 
119  virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
120  {
121  UNUSED(a_Meta);
122  return 18;
123  }
124 };
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
@ E_META_SPONGE_DRY
Definition: BlockType.h:840
@ E_META_SPONGE_WET
Definition: BlockType.h:841
@ E_BLOCK_SPONGE
Definition: BlockType.h:29
@ E_BLOCK_AIR
Definition: BlockType.h:10
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
@ BLOCK_FACE_NONE
Definition: Defines.h:39
Byte ColourID
Definition: Globals.h:162
#define UNUSED
Definition: Globals.h:72
constexpr cBlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockHandler.h:29
virtual void OnPlaced(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) const override
Called by cWorld::SetBlock() after the block has been set.
Definition: BlockSponge.h:21
virtual void OnNeighborChanged(cChunkInterface &a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override
Called when a direct neighbor of this block has been changed.
Definition: BlockSponge.h:30
static void DryUp(Vector3i a_Rel, cChunk &a_Chunk)
Definition: BlockSponge.h:106
static void CheckSoaked(Vector3i a_Rel, cChunk &a_Chunk)
Check blocks around the sponge to see if they are water.
Definition: BlockSponge.h:38
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
Returns the base colour ID of the block, as will be represented on a map, as per documentation: https...
Definition: BlockSponge.h:119
static bool IsWet(Vector3i a_Rel, cChunk &a_Chunk)
Definition: BlockSponge.h:112
bool DoWithChunkAt(Vector3i a_BlockPos, cFunctionRef< bool(cChunk &)> a_Callback)
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Definition: Chunk.cpp:1263
bool UnboundedRelSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Same as SetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
Definition: Chunk.cpp:1135
bool UnboundedRelGetBlockType(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType) const
Same as GetBlockType(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap...
Definition: Chunk.cpp:1029
static void AbsoluteToRelative(int &a_X, int &a_Y, int &a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords into relative (chunk + block) coords:
Definition: ChunkDef.h:147
static constexpr std::array< Vector3i, 6 > AdjacentOffsets
Contains offsets for direct adjacents of any position.
Definition: Simulator.h:34
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17