#pragma once #include "BlockHandler.h" class cBlockFluidHandler: public cBlockHandler { using Super = cBlockHandler; public: cBlockFluidHandler(BLOCKTYPE a_BlockType): Super(a_BlockType) { } virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override { // No pickups return {}; } virtual bool DoesIgnoreBuildCollision(cChunkInterface & a_ChunkInterface, Vector3i a_Pos, cPlayer & a_Player, NIBBLETYPE a_Meta) override { return true; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); if (IsBlockWater(m_BlockType)) { return 12; } ASSERT(!"Unhandled blocktype in fluid/water handler!"); return 0; } virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override { return ( (a_Plant == E_BLOCK_BEETROOTS) || (a_Plant == E_BLOCK_CROPS) || (a_Plant == E_BLOCK_CARROTS) || (a_Plant == E_BLOCK_POTATOES) || (a_Plant == E_BLOCK_MELON_STEM) || (a_Plant == E_BLOCK_PUMPKIN_STEM) ); } } ; class cBlockLavaHandler: public cBlockFluidHandler { using Super = cBlockFluidHandler; public: cBlockLavaHandler(BLOCKTYPE a_BlockType): Super(a_BlockType) { } virtual void OnUpdate( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, const Vector3i a_RelPos ) override { if (a_Chunk.GetWorld()->ShouldLavaSpawnFire()) { // Try to start up to 5 fires: for (int i = 0; i < 5; i++) { TryStartFireNear(a_RelPos, a_Chunk); } } } /** Tries to start a fire near the lava at given coords. Returns true if fire started. */ static bool TryStartFireNear(const Vector3i a_RelPos, cChunk & a_Chunk) { // Pick a random 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 auto Pos = a_RelPos + Vector3i(x, y, z); // Check if it's fuel: BLOCKTYPE BlockType; if ( !cChunkDef::IsValidHeight(Pos.y) || !a_Chunk.UnboundedRelGetBlockType(Pos, BlockType) || !cFireSimulator::IsFuel(BlockType) ) { return false; } // Try to set it on fire: static Vector3i CrossCoords[] = { {-1, 0, 0}, { 1, 0, 0}, { 0, -1, 0}, { 0, 1, 0}, { 0, 0, -1}, { 0, 0, 1}, } ; for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++) { auto NeighborPos = Pos + CrossCoords[i]; if ( cChunkDef::IsValidHeight(NeighborPos.y) && a_Chunk.UnboundedRelGetBlockType(NeighborPos, BlockType) && (BlockType == E_BLOCK_AIR) ) { // This is an air block next to a fuel next to lava, light the fuel block up: a_Chunk.UnboundedRelSetBlock(NeighborPos, E_BLOCK_FIRE, 0); return true; } } // for i - CrossCoords[] return false; } virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override { UNUSED(a_Meta); return 4; } virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override { return false; } } ;