int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { if (a_RelY > 0) { BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ); if (IsForever(BlockBelow)) { // Is burning atop of netherrack, burn forever (re-check in 10 sec) return 10000; } if (IsFuel(BlockBelow)) { return m_BurnStepTimeFuel; } } if ((a_RelY < cChunkDef::Height - 1) && IsFuel(a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ))) { return m_BurnStepTimeFuel; } for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta)) { if (IsFuel(BlockType)) { return m_BurnStepTimeFuel; } } } // for i - gCrossCoords[] return m_BurnStepTimeNonfuel; }
bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta)) { // The chunk is not accessible return false; } if (BlockType != E_BLOCK_AIR) { // Only an air block can be replaced by a fire block return false; } for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++) { if (!a_NearChunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta)) { // Neighbor inaccessible, skip it while evaluating continue; } if (IsFuel(BlockType)) { return true; } } // for i - Coords[] return false; }
void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++) { BLOCKTYPE BlockType; int X = a_RelX + gNeighborCoords[i].x; int Z = a_RelZ + gNeighborCoords[i].z; cChunkPtr Neighbour = a_Chunk->GetRelNeighborChunkAdjustCoords(X, Z); if (Neighbour == NULL) { continue; } BlockType = Neighbour->GetBlock(X, a_RelY + gNeighborCoords[i].y, Z); if (!IsFuel(BlockType)) { continue; } if (BlockType == E_BLOCK_TNT) { int AbsX = X + Neighbour->GetPosX() * cChunkDef::Width; int AbsZ = Z + Neighbour->GetPosZ() * cChunkDef::Width; m_World.SpawnPrimedTNT(AbsX, a_RelY + gNeighborCoords[i].y, AbsZ, 0); Neighbour->SetBlock(X, a_RelY + gNeighborCoords[i].y, Z, E_BLOCK_AIR, 0); return; } bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance); Neighbour->SetBlock(X, a_RelY + gNeighborCoords[i].y, Z, ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0); } // for i - Coords[] }
int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { bool IsBlockBelowSolid = false; if (a_RelY > 0) { BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ); if (DoesBurnForever(BlockBelow)) { // Is burning atop of netherrack, burn forever (re-check in 10 sec) return 10000; } if (IsFuel(BlockBelow)) { return static_cast<int>(m_BurnStepTimeFuel); } IsBlockBelowSolid = cBlockInfo::IsSolid(BlockBelow); } for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta)) { if (IsFuel(BlockType)) { return static_cast<int>(m_BurnStepTimeFuel); } } } // for i - gCrossCoords[] if (!IsBlockBelowSolid && (a_RelY >= 0)) { // Checked through everything, nothing was flammable // If block below isn't solid, we can't have fire, it would be a non-fueled fire // SetBlock just to make sure fire doesn't spawn a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_AIR, 0); return 0; } return static_cast<int>(m_BurnStepTimeNonfuel); }
void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++) { BLOCKTYPE BlockType; int X = a_RelX + gNeighborCoords[i].x; int Z = a_RelZ + gNeighborCoords[i].z; cChunkPtr Neighbour = a_Chunk->GetRelNeighborChunkAdjustCoords(X, Z); if (Neighbour == nullptr) { continue; } BlockType = Neighbour->GetBlock(X, a_RelY + gNeighborCoords[i].y, Z); if (!IsFuel(BlockType)) { continue; } int AbsX = (Neighbour->GetPosX() * cChunkDef::Width) + X; int Y = a_RelY + gNeighborCoords[i].y; int AbsZ = (Neighbour->GetPosZ() * cChunkDef::Width) + Z; if (BlockType == E_BLOCK_TNT) { m_World.SpawnPrimedTNT(AbsX, Y, AbsZ, 0); Neighbour->SetBlock(X, Y, Z, E_BLOCK_AIR, 0); return; } bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance); if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, AbsX, Y, AbsZ, ssFireSpread)) { Neighbour->SetBlock(X, Y, Z, E_BLOCK_FIRE, 0); } else { Neighbour->SetBlock(X, Y, Z, E_BLOCK_AIR, 0); } } // for i - Coords[] }
void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ) { for (int i = 0; i < ARRAYCOUNT(gNeighborCoords); i++) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; if (!a_Chunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta)) { // Neighbor not accessible, ignore it continue; } if (!IsFuel(BlockType)) { continue; } bool ShouldReplaceFuel = (m_World.GetTickRandomNumber(MAX_CHANCE_REPLACE_FUEL) < m_ReplaceFuelChance); a_Chunk->UnboundedRelSetBlock( a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, ShouldReplaceFuel ? E_BLOCK_FIRE : E_BLOCK_AIR, 0 ); } // for i - Coords[] }