Floody fluid simulator now dries up correctly, too.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@964 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
5b7de82a79
commit
41a38e8d90
@ -10,6 +10,8 @@
|
|||||||
class cBlockFluidHandler :
|
class cBlockFluidHandler :
|
||||||
public cBlockHandler
|
public cBlockHandler
|
||||||
{
|
{
|
||||||
|
typedef cBlockHandler super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cBlockFluidHandler(BLOCKTYPE a_BlockType)
|
cBlockFluidHandler(BLOCKTYPE a_BlockType)
|
||||||
: cBlockHandler(a_BlockType)
|
: cBlockHandler(a_BlockType)
|
||||||
@ -23,7 +25,24 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement proper fluid physics here
|
|
||||||
|
virtual void Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||||
|
{
|
||||||
|
switch (m_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
|
{
|
||||||
|
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LAVA, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_BLOCK_STATIONARY_WATER:
|
||||||
|
{
|
||||||
|
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WATER, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super::Check(a_World, a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -387,3 +387,25 @@ bool cBlockHandler::DoesDropOnUnsuitable(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cBlockHandler::Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
|
{
|
||||||
|
if (!CanBeAt(a_World, a_BlockX, a_BlockY, a_BlockZ))
|
||||||
|
{
|
||||||
|
if (DoesDropOnUnsuitable())
|
||||||
|
{
|
||||||
|
DropBlock(a_World, a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Wake up the simulators:
|
||||||
|
a_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,6 +91,12 @@ public:
|
|||||||
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
|
/// Does this block drop if it gets destroyed by an unsuitable situation? Default: true
|
||||||
virtual bool DoesDropOnUnsuitable(void);
|
virtual bool DoesDropOnUnsuitable(void);
|
||||||
|
|
||||||
|
/** Called when one of the neighbors gets set; equivalent to MC block update.
|
||||||
|
By default drops if position no more suitable (CanBeAt(), DoesDropOnUnsuitable(), Drop()),
|
||||||
|
and wakes up all simulators on the block.
|
||||||
|
*/
|
||||||
|
virtual void Check(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
|
||||||
|
|
||||||
/// Get the blockhandler for a specific block id
|
/// Get the blockhandler for a specific block id
|
||||||
static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockType);
|
static cBlockHandler * GetBlockHandler(BLOCKTYPE a_BlockType);
|
||||||
|
@ -480,15 +480,7 @@ void cChunk::CheckBlocks(void)
|
|||||||
Vector3i WorldPos = PositionToWorldPosition( BlockPos );
|
Vector3i WorldPos = PositionToWorldPosition( BlockPos );
|
||||||
|
|
||||||
cBlockHandler * Handler = BlockHandler(GetBlock(index));
|
cBlockHandler * Handler = BlockHandler(GetBlock(index));
|
||||||
if (!Handler->CanBeAt(m_World, WorldPos.x, WorldPos.y, WorldPos.z))
|
Handler->Check(m_World, WorldPos.x, WorldPos.y, WorldPos.z);
|
||||||
{
|
|
||||||
if (Handler->DoesDropOnUnsuitable())
|
|
||||||
{
|
|
||||||
Handler->DropBlock(m_World, WorldPos.x, WorldPos.y, WorldPos.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_World->SetBlock(WorldPos.x, WorldPos.y, WorldPos.z, E_BLOCK_AIR, 0);
|
|
||||||
}
|
|
||||||
} // for itr - ToTickBlocks[]
|
} // for itr - ToTickBlocks[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -918,13 +910,8 @@ void cChunk::SetBlock( int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX, a_RelY, a_RelZ ) );
|
m_ToTickBlocks.push_back(index);
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX + 1, a_RelY, a_RelZ ) );
|
CheckNeighbors(a_RelX, a_RelY, a_RelZ);
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX - 1, a_RelY, a_RelZ ) );
|
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX, a_RelY + 1, a_RelZ ) );
|
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX, a_RelY - 1, a_RelZ ) );
|
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX, a_RelY, a_RelZ + 1 ) );
|
|
||||||
m_ToTickBlocks.push_back( MakeIndex( a_RelX, a_RelY, a_RelZ - 1 ) );
|
|
||||||
|
|
||||||
Vector3i WorldPos = PositionToWorldPosition( a_RelX, a_RelY, a_RelZ );
|
Vector3i WorldPos = PositionToWorldPosition( a_RelX, a_RelY, a_RelZ );
|
||||||
cBlockEntity* BlockEntity = GetBlockEntity( WorldPos );
|
cBlockEntity* BlockEntity = GetBlockEntity( WorldPos );
|
||||||
@ -964,6 +951,75 @@ void cChunk::SetBlock( int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunk::CheckNeighbors(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
|
{
|
||||||
|
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
|
||||||
|
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
|
||||||
|
if (a_RelX < cChunkDef::Width)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX + 1, a_RelY, a_RelZ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ChunkMap->CheckBlock(BlockX + 1, a_RelY, BlockZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_RelX > 0)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back( MakeIndexNoCheck(a_RelX - 1, a_RelY, a_RelZ));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ChunkMap->CheckBlock(BlockX - 1, a_RelY, BlockZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_RelY < cChunkDef::Height - 1)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY + 1, a_RelZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_RelY > 0)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY - 1, a_RelZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_RelZ < cChunkDef::Width - 1)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ChunkMap->CheckBlock(BlockX, a_RelY, BlockZ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_RelZ > 0)
|
||||||
|
{
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ - 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ChunkMap->CheckBlock(BlockX, a_RelY, BlockZ - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunk::CheckBlock(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
|
{
|
||||||
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ToTickBlocks.push_back(MakeIndexNoCheck(a_RelX, a_RelY, a_RelZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta)
|
void cChunk::FastSetBlock( int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta)
|
||||||
{
|
{
|
||||||
ASSERT(!((a_X < 0 || a_X >= Width || a_Y < 0 || a_Y >= Height || a_Z < 0 || a_Z >= Width)));
|
ASSERT(!((a_X < 0 || a_X >= Width || a_Y < 0 || a_Y >= Height || a_Z < 0 || a_Z >= Width)));
|
||||||
|
@ -130,11 +130,15 @@ public:
|
|||||||
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta );
|
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta );
|
||||||
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
|
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
|
||||||
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
|
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }
|
||||||
|
void CheckBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||||
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
|
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta ); // Doesn't force block updates on neighbors, use for simple changes such as grass growing etc.
|
||||||
BLOCKTYPE GetBlock( int a_X, int a_Y, int a_Z );
|
BLOCKTYPE GetBlock( int a_X, int a_Y, int a_Z );
|
||||||
BLOCKTYPE GetBlock( int a_BlockIdx );
|
BLOCKTYPE GetBlock( int a_BlockIdx );
|
||||||
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
void GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta);
|
||||||
|
|
||||||
|
/// Queues all 6 neighbors of the specified block for checking. If outside the chunk, relays the checking to the neighboring chunk
|
||||||
|
void CheckNeighbors(int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
|
||||||
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); }
|
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const {return cChunkDef::GetBiome(m_BiomeMap, a_RelX, a_RelZ); }
|
||||||
|
|
||||||
void CollectPickupsByPlayer(cPlayer * a_Player);
|
void CollectPickupsByPlayer(cPlayer * a_Player);
|
||||||
|
@ -898,18 +898,19 @@ BLOCKTYPE cChunkMap::GetBlockSkyLight(int a_X, int a_Y, int a_Z)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::SetBlockMeta(int a_X, int a_Y, int a_Z, NIBBLETYPE a_BlockMeta)
|
void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_BlockMeta)
|
||||||
{
|
{
|
||||||
int ChunkX, ChunkZ;
|
int ChunkX, ChunkZ;
|
||||||
cChunkDef::AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkZ );
|
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
|
||||||
|
// a_BlockXYZ now contains relative coords!
|
||||||
|
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
cChunkPtr Chunk = GetChunk(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||||
if ((Chunk != NULL) && Chunk->IsValid())
|
if ((Chunk != NULL) && Chunk->IsValid())
|
||||||
{
|
{
|
||||||
Chunk->SetMeta(a_X, a_Y, a_Z, a_BlockMeta);
|
Chunk->SetMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
|
||||||
Chunk->MarkDirty();
|
Chunk->MarkDirty();
|
||||||
Chunk->SendBlockTo( a_X, a_Y, a_Z, NULL );
|
Chunk->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1657,6 +1658,48 @@ void cChunkMap::SaveAllChunks(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cChunkMap::GetNumChunks(void)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
int NumChunks = 0;
|
||||||
|
for (cChunkLayerList::iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||||
|
{
|
||||||
|
NumChunks += (*itr)->GetNumChunksLoaded();
|
||||||
|
}
|
||||||
|
return NumChunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::ChunkValidated(void)
|
||||||
|
{
|
||||||
|
m_evtChunkValid.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::CheckBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
|
{
|
||||||
|
int ChunkX, ChunkZ;
|
||||||
|
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
|
||||||
|
// a_BlockXYZ now contains relative coords!
|
||||||
|
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||||
|
if (Chunk != NULL)
|
||||||
|
{
|
||||||
|
Chunk->CheckBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cChunkMap::cChunkLayer:
|
// cChunkMap::cChunkLayer:
|
||||||
|
|
||||||
@ -1817,30 +1860,6 @@ void cChunkMap::cChunkLayer::UnloadUnusedChunks(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int cChunkMap::GetNumChunks(void)
|
|
||||||
{
|
|
||||||
cCSLock Lock(m_CSLayers);
|
|
||||||
int NumChunks = 0;
|
|
||||||
for (cChunkLayerList::iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
|
||||||
{
|
|
||||||
NumChunks += (*itr)->GetNumChunksLoaded();
|
|
||||||
}
|
|
||||||
return NumChunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::ChunkValidated(void)
|
|
||||||
{
|
|
||||||
m_evtChunkValid.Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cChunkStay:
|
// cChunkStay:
|
||||||
|
|
||||||
|
@ -246,6 +246,9 @@ public:
|
|||||||
|
|
||||||
void ChunkValidated(void); // Called by chunks that have become valid
|
void ChunkValidated(void); // Called by chunks that have become valid
|
||||||
|
|
||||||
|
/// Schedules the specified block for checking (block update)
|
||||||
|
void CheckBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class cChunk; // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
|
friend class cChunk; // The chunks can manipulate neighbors while in their Tick() method, using LockedGetBlock() and LockedSetBlock()
|
||||||
|
@ -39,6 +39,11 @@ void cFloodyFluidSimulator::SimulateBlock(int a_BlockX, int a_BlockY, int a_Bloc
|
|||||||
int y = (a_BlockY > 0) ? 1 : 0; // Relative y-coord of this block in Area
|
int y = (a_BlockY > 0) ? 1 : 0; // Relative y-coord of this block in Area
|
||||||
|
|
||||||
NIBBLETYPE MyMeta = Area.GetRelBlockMeta(1, y, 1);
|
NIBBLETYPE MyMeta = Area.GetRelBlockMeta(1, y, 1);
|
||||||
|
if (!IsAnyFluidBlock(Area.GetRelBlockType(1, y, 1)))
|
||||||
|
{
|
||||||
|
// Can happen - if a block is scheduled for simulating and gets replaced in the meantime.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (MyMeta != 0)
|
if (MyMeta != 0)
|
||||||
{
|
{
|
||||||
@ -121,6 +126,9 @@ bool cFloodyFluidSimulator::CheckTributaries(int a_BlockX, int a_BlockY, int a_B
|
|||||||
|
|
||||||
void cFloodyFluidSimulator::SpreadToNeighbor(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_NewMeta)
|
void cFloodyFluidSimulator::SpreadToNeighbor(int a_BlockX, int a_BlockY, int a_BlockZ, const cBlockArea & a_Area, NIBBLETYPE a_NewMeta)
|
||||||
{
|
{
|
||||||
|
ASSERT(a_NewMeta <= 8); // Invalid meta values
|
||||||
|
ASSERT(a_NewMeta > 0); // Source blocks aren't spread
|
||||||
|
|
||||||
BLOCKTYPE Block = a_Area.GetBlockType(a_BlockX, a_BlockY, a_BlockZ);
|
BLOCKTYPE Block = a_Area.GetBlockType(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
|
||||||
if (IsAnyFluidBlock(Block))
|
if (IsAnyFluidBlock(Block))
|
||||||
@ -149,8 +157,6 @@ void cFloodyFluidSimulator::SpreadToNeighbor(int a_BlockX, int a_BlockY, int a_B
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Spread:
|
// Spread:
|
||||||
LOGD("Fluid: spreading to block {%d, %d, %d}, meta %d", a_BlockX, a_BlockY, a_BlockZ, a_NewMeta);
|
|
||||||
|
|
||||||
m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_FluidBlock, a_NewMeta);
|
m_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_FluidBlock, a_NewMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user