1
0
Files
cuberite-2a/source/Simulator/FireSimulator.cpp
madmaxoft@gmail.com 5b7de82a79 Initial Floody fluid simulator.
Can spread, cannot dry.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@963 0a769ca7-a7f5-676a-18bf-c427514a06d6
2012-10-14 17:06:21 +00:00

173 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "FireSimulator.h"
#include "../World.h"
#include "../BlockID.h"
#include "../Defines.h"
cFireSimulator::cFireSimulator( cWorld* a_World )
: cSimulator(a_World)
, m_Blocks(new BlockList)
, m_Buffer(new BlockList)
, m_BurningBlocks(new BlockList)
{
}
cFireSimulator::~cFireSimulator()
{
delete m_Buffer;
delete m_Blocks;
delete m_BurningBlocks;
}
void cFireSimulator::Simulate( float a_Dt )
{
m_Buffer->clear();
std::swap( m_Blocks, m_Buffer );
for( BlockList::iterator itr = m_Buffer->begin(); itr != m_Buffer->end(); ++itr )
{
Vector3i Pos = *itr;
char BlockID = m_World->GetBlock(Pos.x, Pos.y, Pos.z);
if(!IsAllowedBlock(BlockID)) //Check wheather the block is still burning
continue;
if (BurnBlockAround(Pos.x, Pos.y, Pos.z)) //Burn single block and if there was one -> next time again
{
m_Blocks->push_back(Pos);
}
else
if(!IsForeverBurnable(m_World->GetBlock(Pos.x, Pos.y - 1, Pos.z)) && !FiresForever(BlockID))
m_World->SetBlock(Pos.x, Pos.y, Pos.z, E_BLOCK_AIR, 0);
}
}
bool cFireSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
{
return (a_BlockType == E_BLOCK_FIRE) || IsBlockLava(a_BlockType);
}
void cFireSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
{
BLOCKTYPE BlockType = m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!IsAllowedBlock(BlockType))
{
return;
}
// Check for duplicates:
for (BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr )
{
Vector3i Pos = *itr;
if ((Pos.x == a_BlockX) && (Pos.y == a_BlockY) && (Pos.z == a_BlockZ))
{
return;
}
}
m_Blocks->push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
}
bool cFireSimulator::IsForeverBurnable( BLOCKTYPE a_BlockType )
{
return a_BlockType == E_BLOCK_BLOODSTONE;
}
bool cFireSimulator::IsBurnable( BLOCKTYPE a_BlockType )
{
return a_BlockType == E_BLOCK_PLANKS
|| a_BlockType == E_BLOCK_LEAVES
|| a_BlockType == E_BLOCK_LOG
|| a_BlockType == E_BLOCK_WOOL
|| a_BlockType == E_BLOCK_BOOKCASE
|| a_BlockType == E_BLOCK_FENCE
|| a_BlockType == E_BLOCK_TNT
|| a_BlockType == E_BLOCK_VINES;
}
bool cFireSimulator::FiresForever( BLOCKTYPE a_BlockType )
{
return a_BlockType != E_BLOCK_FIRE;
}
bool cFireSimulator::BurnBlockAround(int a_X, int a_Y, int a_Z)
{
return BurnBlock(a_X + 1, a_Y, a_Z)
|| BurnBlock(a_X - 1, a_Y, a_Z)
|| BurnBlock(a_X, a_Y + 1, a_Z)
|| BurnBlock(a_X, a_Y - 1, a_Z)
|| BurnBlock(a_X, a_Y, a_Z + 1)
|| BurnBlock(a_X, a_Y, a_Z - 1);
}
bool cFireSimulator::BurnBlock(int a_X, int a_Y, int a_Z)
{
char BlockID = m_World->GetBlock(a_X, a_Y, a_Z);
if(IsBurnable(BlockID))
{
m_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_FIRE, 0);
return true;
}
if(IsForeverBurnable(BlockID))
{
char BlockAbove = m_World->GetBlock(a_X, a_Y + 1, a_Z);
if(BlockAbove == E_BLOCK_AIR)
{
m_World->SetBlock(a_X, a_Y + 1, a_Z, E_BLOCK_FIRE, 0); //Doesn´t notify the simulator so it won´t go off
return true;
}
return false;
}
return false;
}