12 #include "../BlockArea.h" 13 #include "../Blocks/BlockHandler.h" 14 #include "../BlockInServerPluginInterface.h" 15 #include "../Blocks/ChunkInterface.h" 23 #define FLUID_FLOG FLOGD 25 #define FLUID_FLOG(...) 38 int a_NumNeighborsForSource
40 super(a_World, a_Fluid, a_StationaryFluid, a_TickDelay),
42 m_NumNeighborsForSource(a_NumNeighborsForSource)
52 FLUID_FLOG(
"Simulating block {0}: block {1}, meta {2}",
54 a_Chunk->
GetBlock(a_RelX, a_RelY, a_RelZ),
55 a_Chunk->
GetMeta(a_RelX, a_RelY, a_RelZ)
69 if (
HardenBlock(a_Chunk, {a_RelX, a_RelY, a_RelZ}, MyBlock, MyMeta))
93 bool SpreadFurther =
true;
103 SpreadFurther =
false;
107 if (SpreadFurther && (NewMeta < 8))
109 SpreadXZ(a_Chunk, a_RelX, a_RelY, a_RelZ, NewMeta);
174 for (
size_t i = 0; i <
ARRAYCOUNT(Coords); i++)
176 if (!a_Chunk->
UnboundedRelGetBlock(a_RelX + Coords[i].
x, a_RelY, a_RelZ + Coords[i].
z, BlockType, BlockMeta))
183 FLUID_FLOG(
" Fed from {0}, type {1}, meta {2}",
208 FLUID_FLOG(
" Not fed, meta {0}, erasing altogether", a_MyMeta);
224 Vector3i relPos(a_RelX, a_RelY, a_RelZ);
226 if ((a_NearChunk ==
nullptr) || (!a_NearChunk->
IsValid()))
239 if ((BlockMeta == a_NewMeta) ||
IsHigherMeta(BlockMeta, a_NewMeta))
253 FLUID_FLOG(
" Lava flowing into water, turning water at rel {0} into {1}",
256 a_NearChunk->
SetBlock(relPos, NewBlock, 0);
259 "block.lava.extinguish",
273 FLUID_FLOG(
" Water flowing into lava, turning lava at rel {0} into {1}",
276 a_NearChunk->
SetBlock(relPos, NewBlock, 0);
279 "block.lava.extinguish",
289 ASSERT(!
"Unknown fluid!");
309 FLUID_FLOG(
" Spreading to {0} with meta {1}", absPos, a_NewMeta);
322 FLUID_FLOG(
" Checking neighbors for source creation");
324 static const Vector3i NeighborCoords[] =
333 for (
size_t i = 0; i <
ARRAYCOUNT(NeighborCoords); i++)
335 int x = a_RelX + NeighborCoords[i].
x;
336 int y = a_RelY + NeighborCoords[i].
y;
337 int z = a_RelZ + NeighborCoords[i].
z;
377 bool ShouldHarden =
false;
381 static const Vector3i neighborOffsets[] =
388 for (
const auto & ofs: neighborOffsets)
409 else if (a_Meta <= 4)
bool IsValid(void) const
Returns true iff the chunk block data is valid (loaded / generated)
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override
Returns true if the specified block type is "interesting" for this simulator.
bool IsBlockWater(BLOCKTYPE a_BlockType)
void WakeUp(Vector3i a_Block, cChunk *a_Chunk)
cChunk * GetRelNeighborChunkAdjustCoords(Vector3i &a_RelPos) const
Returns the chunk into which the relatively-specified block belongs.
void GetBlockTypeMeta(Vector3i a_RelPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
unsigned char BLOCKTYPE
The datatype used by blockdata.
static bool IsValidRelPos(Vector3i a_RelPos)
Validates a chunk relative coordinate.
bool IsPassableForFluid(BLOCKTYPE a_BlockType)
BLOCKTYPE m_StationaryFluidBlock
Vector3i RelativeToAbsolute(Vector3i a_RelBlockPosition)
Converts the coord relative to this chunk into an absolute coord.
bool HardenBlock(cChunk *a_Chunk, Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
Checks if the specified block should harden (Water / Lava interaction) and if so, converts it to a su...
bool IsHigherMeta(NIBBLETYPE a_Meta1, NIBBLETYPE a_Meta2)
Returns true if a_Meta1 is a higher fluid than a_Meta2.
void SetBlock(Vector3i a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Vector3i PositionToWorldPosition(Vector3i a_RelPos)
cSimulatorManager * GetSimulatorManager(void)
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the specified block, and spawns the appropriate pickups for it.
bool CheckTributaries(cChunk *a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_MyMeta)
Checks tributaries, if not fed, decreases the block's level and returns true.
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override
static bool CanWashAway(BLOCKTYPE a_BlockType)
int m_NumNeighborsForSource
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
cFloodyFluidSimulator(cWorld &a_World, BLOCKTYPE a_Fluid, BLOCKTYPE a_StationaryFluid, NIBBLETYPE a_Falloff, int a_TickDelay, int a_NumNeighborsForSource)
bool CheckNeighborsForSource(cChunk *a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
Checks if there are enough neighbors to create a source at the coords specified; turns into source an...
bool IsAnyFluidBlock(BLOCKTYPE a_BlockType) const
cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
virtual void SpreadXZ(cChunk *a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
Spread fluid to XZ neighbors.
bool UnboundedRelGetBlock(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
virtual bool DoesDropOnUnsuitable(void)
Returns if this block drops if it gets destroyed by an unsuitable situation.
void SpreadToNeighbor(cChunk *a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta)
Spreads into the specified block, if the blocktype there allows.
virtual void SimulateBlock(cChunk *a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
Called from SimulateChunk() to simulate each block in one slot of blocks.
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta, bool a_SendToClients=true)
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
AString ItemTypeToString(short a_ItemType)
Translates itemtype into a string.
bool IsBlockLava(BLOCKTYPE a_BlockType)