#pragma once
#include "BlockHandler.h"
class cBlockFluidHandler :
public cBlockHandler
{
typedef cBlockHandler super;
public:
cBlockFluidHandler(BLOCKTYPE a_BlockType)
: cBlockHandler(a_BlockType)
{
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// No pickups
}
virtual bool DoesIgnoreBuildCollision(void) override
{
return true;
}
virtual void Check(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk) override
{
switch (m_BlockType)
{
case E_BLOCK_STATIONARY_LAVA:
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_LAVA, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
break;
}
case E_BLOCK_STATIONARY_WATER:
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_WATER, a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ));
break;
}
}
super::Check(a_ChunkInterface, a_RelX, a_RelY, a_RelZ, a_Chunk);
}
} ;
class cBlockLavaHandler :
public cBlockFluidHandler
{
typedef cBlockFluidHandler super;
public:
cBlockLavaHandler(BLOCKTYPE a_BlockType) :
super(a_BlockType)
{
}
/// Called to tick the block
virtual void OnUpdate(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
if (a_Chunk.GetWorld()->ShouldLavaSpawnFire())
{
// Try to start up to 5 fires:
for (int i = 0; i < 5; i++)
{
TryStartFireNear(a_RelX, a_RelY, a_RelZ, a_Chunk);
}
}
}
/// Tries to start a fire near the lava at given coords. Returns true if fire started.
static bool TryStartFireNear(int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk)
{
// Pick a block next to this lava block:
int rnd = a_Chunk.GetWorld()->GetTickRandomNumber(cChunkDef::NumBlocks * 8) / 7;
int x = (rnd % 3) - 1; // -1 .. 1
int y = ((rnd / 4) % 4) - 1; // -1 .. 2
int z = ((rnd / 16) % 3) - 1; // -1 .. 1
// Check if it's fuel:
BLOCKTYPE BlockType;
if (
!a_Chunk.UnboundedRelGetBlockType(a_RelX + x, a_RelY + y, a_RelZ + z, BlockType) ||
!cFireSimulator::IsFuel(BlockType)
)
{
return false;
}
// Try to set it on fire:
static struct
{
int x, y, z;
} CrossCoords[] =
{
{-1, 0, 0},
{ 1, 0, 0},
{ 0, -1, 0},
{ 0, 1, 0},
{ 0, 0, -1},
{ 0, 0, 1},
} ;
int RelX = a_RelX + x;
int RelY = a_RelY + y;
int RelZ = a_RelZ + z;
for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++)
{
if (
a_Chunk.UnboundedRelGetBlockType(RelX + CrossCoords[i].x, RelY + CrossCoords[i].y, RelZ + CrossCoords[i].z, BlockType) &&
(BlockType == E_BLOCK_AIR)
)
{
// This is an air block next to a fuel next to lava, light it up:
a_Chunk.UnboundedRelSetBlock(RelX + CrossCoords[i].x, RelY + CrossCoords[i].y, RelZ + CrossCoords[i].z, E_BLOCK_FIRE, 0);
return true;
}
} // for i - CrossCoords[]
return false;
}
} ;