bool cFluidSimulator::IsPassableForFluid(BLOCKTYPE a_BlockType) { return ( (a_BlockType == E_BLOCK_AIR) || (a_BlockType == E_BLOCK_FIRE) || IsAllowedBlock(a_BlockType) || CanWashAway(a_BlockType) ); }
void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_NewMeta) { ASSERT(a_NewMeta <= 8); // Invalid meta values ASSERT(a_NewMeta > 0); // Source blocks aren't spread a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ); if ((a_NearChunk == NULL) || (!a_NearChunk->IsValid())) { // Chunk not available return; } const int BlockX = a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX; const int BlockZ = a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ; BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; a_NearChunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta); if (IsAllowedBlock(BlockType)) { if ((BlockMeta == a_NewMeta) || IsHigherMeta(BlockMeta, a_NewMeta)) { // Don't spread there, there's already a higher or same level there return; } } // Check water - lava interaction: if (m_FluidBlock == E_BLOCK_LAVA) { if (IsBlockWater(BlockType)) { // Lava flowing into water, change to stone / cobblestone based on direction: BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE; FLOG(" Lava flowing into water, turning water at rel {%d, %d, %d} into stone", a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str() ); a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f); return; } } else if (m_FluidBlock == E_BLOCK_WATER) { if (IsBlockLava(BlockType)) { // Water flowing into lava, change to cobblestone / obsidian based on dest block: BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE; FLOG(" Water flowing into lava, turning lava at rel {%d, %d, %d} into %s", a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str() ); a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0); a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f); return; } } else { ASSERT(!"Unknown fluid!"); } if (!IsPassableForFluid(BlockType)) { // Can't spread there return; } // Wash away the block there, if possible: if (CanWashAway(BlockType)) { cBlockHandler * Handler = BlockHandler(BlockType); if (Handler->DoesDropOnUnsuitable()) { cChunkInterface ChunkInterface(m_World.GetChunkMap()); cBlockInServerPluginInterface PluginInterface(m_World); Handler->DropBlock( ChunkInterface, m_World, PluginInterface, NULL, BlockX, a_RelY, BlockZ ); } } // if (CanWashAway) // Spread: FLOG(" Spreading to {%d, %d, %d} with meta %d", BlockX, a_RelY, BlockZ, a_NewMeta); a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta); m_World.GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, a_NearChunk); HardenBlock(a_NearChunk, a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta); }