Rewritten SandSimulator to use direct chunk access; and sand falling on torches now creates a pickup.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1240 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
parent
cadf97a70a
commit
6744738a85
@ -5,6 +5,7 @@
|
|||||||
#include "ChunkDef.h"
|
#include "ChunkDef.h"
|
||||||
|
|
||||||
#include "Simulator/FireSimulator.h"
|
#include "Simulator/FireSimulator.h"
|
||||||
|
#include "Simulator/SandSimulator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -271,6 +272,7 @@ public:
|
|||||||
cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; }
|
cFireSimulatorChunkData & GetFireSimulatorData (void) { return m_FireSimulatorData; }
|
||||||
cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; }
|
cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; }
|
||||||
cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; }
|
cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; }
|
||||||
|
cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -319,6 +321,7 @@ private:
|
|||||||
cFireSimulatorChunkData m_FireSimulatorData;
|
cFireSimulatorChunkData m_FireSimulatorData;
|
||||||
cFluidSimulatorData * m_WaterSimulatorData;
|
cFluidSimulatorData * m_WaterSimulatorData;
|
||||||
cFluidSimulatorData * m_LavaSimulatorData;
|
cFluidSimulatorData * m_LavaSimulatorData;
|
||||||
|
cSandSimulatorChunkData m_SandSimulatorData;
|
||||||
|
|
||||||
|
|
||||||
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
|
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
|
||||||
|
@ -50,9 +50,9 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z)
|
|||||||
|
|
||||||
cEntity::~cEntity()
|
cEntity::~cEntity()
|
||||||
{
|
{
|
||||||
LOGD("Deleting entity %d at pos {%.2f, %.2f} ~ [%d, %d]; ptr %p",
|
LOGD("Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p",
|
||||||
m_UniqueID,
|
m_UniqueID,
|
||||||
m_Pos.x, m_Pos.z,
|
m_Pos.x, m_Pos.y, m_Pos.z,
|
||||||
(int)(m_Pos.x / cChunkDef::Width), (int)(m_Pos.z / cChunkDef::Width),
|
(int)(m_Pos.x / cChunkDef::Width), (int)(m_Pos.z / cChunkDef::Width),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
@ -3,15 +3,17 @@
|
|||||||
#include "FallingBlock.h"
|
#include "FallingBlock.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "ClientHandle.h"
|
#include "ClientHandle.h"
|
||||||
|
#include "Simulator/SandSimulator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_BlockType)
|
cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) :
|
||||||
: super(etFallingBlock, a_BlockPosition.x + 0.5f, a_BlockPosition.y + 0.5f, a_BlockPosition.z + 0.5f)
|
super(etFallingBlock, a_BlockPosition.x + 0.5f, a_BlockPosition.y + 0.5f, a_BlockPosition.z + 0.5f),
|
||||||
, m_BlockType(a_BlockType)
|
m_BlockType(a_BlockType),
|
||||||
, m_OriginalPosition(a_BlockPosition)
|
m_BlockMeta(a_BlockMeta),
|
||||||
|
m_OriginalPosition(a_BlockPosition)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +23,7 @@ cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_Block
|
|||||||
|
|
||||||
void cFallingBlock::Initialize(cWorld * a_World)
|
void cFallingBlock::Initialize(cWorld * a_World)
|
||||||
{
|
{
|
||||||
super::Initialize( a_World );
|
super::Initialize(a_World);
|
||||||
a_World->BroadcastSpawn(*this);
|
a_World->BroadcastSpawn(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,13 +46,34 @@ void cFallingBlock::Tick(float a_Dt, MTRand & a_TickRandom)
|
|||||||
m_Speed.y -= MilliDt * 9.8f;
|
m_Speed.y -= MilliDt * 9.8f;
|
||||||
m_Pos.y += m_Speed.y * MilliDt;
|
m_Pos.y += m_Speed.y * MilliDt;
|
||||||
|
|
||||||
// GetWorld()->BroadcastTeleportEntity(*this); // Testing position
|
// GetWorld()->BroadcastTeleportEntity(*this); // Test position
|
||||||
|
|
||||||
Vector3i BlockPos( m_OriginalPosition.x, (int)(m_Pos.y - 0.5), m_OriginalPosition.z);
|
int BlockX = (int)m_OriginalPosition.x;
|
||||||
if (!IsPassable(GetWorld()->GetBlock(BlockPos)))
|
int BlockY = (int)(m_Pos.y - 0.5);
|
||||||
|
int BlockZ = (int)m_OriginalPosition.z;
|
||||||
|
|
||||||
|
if (BlockY < 0)
|
||||||
{
|
{
|
||||||
Destroy();
|
// Fallen out of this world, just continue falling until out of sight, then destroy:
|
||||||
GetWorld()->SetBlock(BlockPos.x, BlockPos.y + 1, BlockPos.z, m_BlockType, 0);
|
if (BlockY < 100)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BlockY < cChunkDef::Height - 1)
|
||||||
|
{
|
||||||
|
BLOCKTYPE BlockBelow = GetWorld()->GetBlock(BlockX, BlockY, BlockZ);
|
||||||
|
if (
|
||||||
|
cSandSimulator::DoesBreakFallingThrough(BlockBelow) || // Fallen onto a block that breaks this into pickups (e. g. half-slab)
|
||||||
|
!cSandSimulator::CanContinueFallThrough(BlockBelow) // Fallen onto a solid block
|
||||||
|
)
|
||||||
|
{
|
||||||
|
cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta);
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,10 @@ class cFallingBlock :
|
|||||||
public:
|
public:
|
||||||
CLASS_PROTODEF(cFallingBlock);
|
CLASS_PROTODEF(cFallingBlock);
|
||||||
|
|
||||||
cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_BlockType);
|
cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
|
|
||||||
BLOCKTYPE GetBlockType(void) const { return m_BlockType; }
|
BLOCKTYPE GetBlockType(void) const { return m_BlockType; }
|
||||||
|
NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; }
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void Initialize(cWorld * a_World) override;
|
virtual void Initialize(cWorld * a_World) override;
|
||||||
@ -33,13 +34,9 @@ public:
|
|||||||
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
virtual void Tick(float a_Dt, MTRand & a_TickRandom) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLOCKTYPE m_BlockType;
|
BLOCKTYPE m_BlockType;
|
||||||
Vector3i m_OriginalPosition;
|
NIBBLETYPE m_BlockMeta;
|
||||||
|
Vector3i m_OriginalPosition;
|
||||||
static bool IsPassable(BLOCKTYPE a_BlockType)
|
|
||||||
{
|
|
||||||
return ((a_BlockType == E_BLOCK_AIR) || IsBlockLiquid(a_BlockType));
|
|
||||||
}
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,60 +12,72 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cSandSimulator::cSandSimulator(cWorld & a_World)
|
cSandSimulator::cSandSimulator(cWorld & a_World, cIniFile & a_IniFile) :
|
||||||
: cSimulator(a_World)
|
cSimulator(a_World),
|
||||||
, m_Blocks(new BlockList)
|
m_TotalBlocks(0)
|
||||||
, m_Buffer(new BlockList)
|
|
||||||
{
|
{
|
||||||
|
m_IsInstantFall = a_IniFile.GetValueSetB("Physics", "SandInstantFall", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cSandSimulator::~cSandSimulator()
|
void cSandSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk)
|
||||||
{
|
{
|
||||||
delete m_Buffer;
|
cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
|
||||||
delete m_Blocks;
|
if (ChunkData.empty())
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSandSimulator::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;
|
return;
|
||||||
BLOCKTYPE BlockID = m_World.GetBlock(Pos.x, Pos.y, Pos.z);
|
}
|
||||||
if(!IsAllowedBlock(BlockID))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BLOCKTYPE BottomBlock = m_World.GetBlock( Pos.x, Pos.y - 1, Pos.z );
|
int BaseX = a_Chunk->GetPosX() * cChunkDef::Width;
|
||||||
|
int BaseZ = a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||||
if( IsPassable(BottomBlock) )
|
for (cSandSimulatorChunkData::const_iterator itr = ChunkData.begin(), end = ChunkData.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
BLOCKTYPE BlockType = a_Chunk->GetBlock(itr->x, itr->y, itr->z);
|
||||||
|
if (!IsAllowedBlock(BlockType) || (itr->y <= 0))
|
||||||
{
|
{
|
||||||
cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockID);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCKTYPE BlockBelow = (itr->y > 0) ? a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z) : E_BLOCK_AIR;
|
||||||
|
if (CanStartFallingThrough(BlockBelow))
|
||||||
|
{
|
||||||
|
if (m_IsInstantFall)
|
||||||
|
{
|
||||||
|
DoInstantFall(a_Chunk, itr->x, itr->y, itr->z);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Vector3i Pos;
|
||||||
|
Pos.x = itr->x + BaseX;
|
||||||
|
Pos.y = itr->y;
|
||||||
|
Pos.z = itr->z + BaseZ;
|
||||||
|
cFallingBlock * FallingBlock = new cFallingBlock(Pos, BlockType, a_Chunk->GetMeta(itr->x, itr->y, itr->z));
|
||||||
FallingBlock->Initialize(&m_World);
|
FallingBlock->Initialize(&m_World);
|
||||||
m_World.SetBlock( Pos.x, Pos.y, Pos.z, E_BLOCK_AIR, 0 );
|
a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_TotalBlocks -= ChunkData.size();
|
||||||
|
ChunkData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cSandSimulator::IsAllowedBlock( BLOCKTYPE a_BlockType )
|
bool cSandSimulator::IsAllowedBlock(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
return a_BlockType == E_BLOCK_SAND
|
switch (a_BlockType)
|
||||||
|| a_BlockType == E_BLOCK_GRAVEL;
|
{
|
||||||
|
case E_BLOCK_SAND:
|
||||||
|
case E_BLOCK_GRAVEL:
|
||||||
|
case E_BLOCK_ANVIL:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,40 +86,169 @@ bool cSandSimulator::IsAllowedBlock( BLOCKTYPE a_BlockType )
|
|||||||
|
|
||||||
void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
|
void cSandSimulator::AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk)
|
||||||
{
|
{
|
||||||
// TODO: Optimize this by passing the block type along
|
if (a_Chunk == NULL)
|
||||||
int RelX = a_BlockX;
|
{
|
||||||
int RelY = a_BlockY;
|
return;
|
||||||
int RelZ = a_BlockZ;
|
}
|
||||||
int ChunkX, ChunkZ;
|
int RelX = a_BlockX - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||||
cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
|
int RelZ = a_BlockZ - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||||
if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, RelY, RelZ)))
|
if (!IsAllowedBlock(a_Chunk->GetBlock(RelX, a_BlockY, RelZ)))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3i Block(a_BlockX, a_BlockY, a_BlockZ);
|
// Check for duplicates:
|
||||||
|
cSandSimulatorChunkData & ChunkData = a_Chunk->GetSandSimulatorData();
|
||||||
//check for duplicates
|
for (cSandSimulatorChunkData::iterator itr = ChunkData.begin(); itr != ChunkData.end(); ++itr)
|
||||||
for (BlockList::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr)
|
|
||||||
{
|
{
|
||||||
Vector3i Pos = *itr;
|
if ((itr->x == RelX) && (itr->y == a_BlockY) && (itr->z == a_BlockZ))
|
||||||
if ((Pos.x == a_BlockX) && (Pos.y == a_BlockY) && (Pos.z == a_BlockZ))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Blocks->push_back(Block);
|
m_TotalBlocks += 1;
|
||||||
|
ChunkData.push_back(cCoordWithInt(RelX, a_BlockY, RelZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cSandSimulator::IsPassable(BLOCKTYPE a_BlockType)
|
bool cSandSimulator::CanStartFallingThrough(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
return (a_BlockType == E_BLOCK_AIR)
|
switch (a_BlockType)
|
||||||
|| IsBlockWater(a_BlockType)
|
{
|
||||||
|| IsBlockLava(a_BlockType)
|
case E_BLOCK_AIR:
|
||||||
|| (a_BlockType == E_BLOCK_FIRE);
|
case E_BLOCK_FIRE:
|
||||||
|
case E_BLOCK_WATER:
|
||||||
|
case E_BLOCK_STATIONARY_WATER:
|
||||||
|
case E_BLOCK_LAVA:
|
||||||
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cSandSimulator::CanContinueFallThrough(BLOCKTYPE a_BlockType)
|
||||||
|
{
|
||||||
|
switch (a_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_AIR:
|
||||||
|
case E_BLOCK_FIRE:
|
||||||
|
case E_BLOCK_WATER:
|
||||||
|
case E_BLOCK_STATIONARY_WATER:
|
||||||
|
case E_BLOCK_LAVA:
|
||||||
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
|
case E_BLOCK_POWERED_RAIL:
|
||||||
|
case E_BLOCK_DETECTOR_RAIL:
|
||||||
|
case E_BLOCK_COBWEB:
|
||||||
|
case E_BLOCK_TALL_GRASS:
|
||||||
|
case E_BLOCK_DEAD_BUSH:
|
||||||
|
case E_BLOCK_YELLOW_FLOWER:
|
||||||
|
case E_BLOCK_RED_ROSE:
|
||||||
|
case E_BLOCK_BROWN_MUSHROOM:
|
||||||
|
case E_BLOCK_RED_MUSHROOM:
|
||||||
|
case E_BLOCK_TORCH:
|
||||||
|
case E_BLOCK_REDSTONE_WIRE:
|
||||||
|
case E_BLOCK_CROPS:
|
||||||
|
case E_BLOCK_PUMPKIN_STEM:
|
||||||
|
case E_BLOCK_MELON_STEM:
|
||||||
|
case E_BLOCK_REDSTONE_TORCH_OFF:
|
||||||
|
case E_BLOCK_REDSTONE_TORCH_ON:
|
||||||
|
case E_BLOCK_STONE_BUTTON:
|
||||||
|
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||||
|
case E_BLOCK_WOODEN_BUTTON:
|
||||||
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
|
case E_BLOCK_REDSTONE_REPEATER_OFF:
|
||||||
|
case E_BLOCK_REDSTONE_REPEATER_ON:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cSandSimulator::IsReplacedOnRematerialization(BLOCKTYPE a_BlockType)
|
||||||
|
{
|
||||||
|
switch (a_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_AIR:
|
||||||
|
case E_BLOCK_FIRE:
|
||||||
|
case E_BLOCK_WATER:
|
||||||
|
case E_BLOCK_STATIONARY_WATER:
|
||||||
|
case E_BLOCK_LAVA:
|
||||||
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
|
case E_BLOCK_TALL_GRASS:
|
||||||
|
case E_BLOCK_DEAD_BUSH:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cSandSimulator::DoesBreakFallingThrough(BLOCKTYPE a_BlockType)
|
||||||
|
{
|
||||||
|
switch (a_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_STONE_SLAB:
|
||||||
|
case E_BLOCK_WOODEN_SLAB:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSandSimulator::FinishFalling(
|
||||||
|
cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
|
||||||
|
BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ASSERT(a_BlockY < cChunkDef::Height);
|
||||||
|
|
||||||
|
BLOCKTYPE CurrentBlockType = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
if ((a_FallingBlockType == E_BLOCK_ANVIL) || IsReplacedOnRematerialization(CurrentBlockType))
|
||||||
|
{
|
||||||
|
// Rematerialize the material here:
|
||||||
|
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FallingBlockType, a_FallingBlockMeta);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a pickup instead:
|
||||||
|
cItems Pickups;
|
||||||
|
Pickups.Add((ENUM_ITEM_ID)a_FallingBlockType, 1, a_FallingBlockMeta);
|
||||||
|
a_World->SpawnItemPickups(Pickups, (double)a_BlockX + 0.5, (double)a_BlockY + 0.5, (double)a_BlockZ + 0.5, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSandSimulator::DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,32 +2,62 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Simulator.h"
|
#include "Simulator.h"
|
||||||
#include "../BlockEntity.h"
|
|
||||||
#include "../Vector3i.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cSandSimulator : public cSimulator
|
/// Despite the class name, this simulator takes care of all blocks that fall when suspended in the air.
|
||||||
|
class cSandSimulator :
|
||||||
|
public cSimulator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cSandSimulator(cWorld & a_World);
|
cSandSimulator(cWorld & a_World, cIniFile & a_IniFile);
|
||||||
~cSandSimulator();
|
|
||||||
|
|
||||||
virtual void Simulate( float a_Dt ) override;
|
// cSimulator overrides:
|
||||||
|
virtual void Simulate(float a_Dt) override {} // Unused in this simulator
|
||||||
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override;
|
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
|
||||||
virtual bool IsPassable( BLOCKTYPE a_BlockType );
|
virtual bool IsAllowedBlock(BLOCKTYPE a_BlockType) override;
|
||||||
|
|
||||||
|
/// Returns true if a falling-able block can start falling through the specified block type
|
||||||
|
static bool CanStartFallingThrough(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
|
/// Returns true if an already-falling block can pass through the specified block type (e. g. torch)
|
||||||
|
static bool CanContinueFallThrough(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
|
/// Returns true if the falling block rematerializing will replace the specified block type (e. g. tall grass)
|
||||||
|
static bool IsReplacedOnRematerialization(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
|
/// Returns true if the specified block breaks falling blocks while they fall through it (e. g. halfslabs)
|
||||||
|
static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType);
|
||||||
|
|
||||||
|
/** Called when a block finishes falling at the specified coords, either by insta-fall,
|
||||||
|
or through cFallingBlock entity.
|
||||||
|
It either rematerializes the block (a_FallingBlockType) at the specified coords, or creates a pickup,
|
||||||
|
based on the block currently present in the world at the dest specified coords
|
||||||
|
*/
|
||||||
|
static void FinishFalling(
|
||||||
|
cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ,
|
||||||
|
BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta
|
||||||
|
);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool m_IsInstantFall; // If set to true, blocks don't fall using cFallingBlock entity, but instantly instead
|
||||||
|
|
||||||
|
int m_TotalBlocks; // Total number of blocks currently in the queue for simulating
|
||||||
|
|
||||||
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
|
||||||
|
|
||||||
typedef std::list <Vector3i> BlockList;
|
/// Performs the instant fall of the block - removes it from top, Finishes it at the bottom
|
||||||
BlockList * m_Blocks;
|
void DoInstantFall(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||||
BlockList * m_Buffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Per-chunk data for the simulator, specified individual chunks to simulate; Data is not used
|
||||||
|
typedef cCoordWithIntList cSandSimulatorChunkData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,10 +250,10 @@ cWorld::cWorld(const AString & a_WorldName) :
|
|||||||
m_BlockTickQueueCopy.reserve(1000);
|
m_BlockTickQueueCopy.reserve(1000);
|
||||||
|
|
||||||
// Simulators:
|
// Simulators:
|
||||||
m_SimulatorManager = new cSimulatorManager(*this);
|
m_SimulatorManager = new cSimulatorManager(*this);
|
||||||
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
|
m_WaterSimulator = InitializeFluidSimulator(IniFile, "Water", E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
|
||||||
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
|
m_LavaSimulator = InitializeFluidSimulator(IniFile, "Lava", E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
|
||||||
m_SandSimulator = new cSandSimulator(*this);
|
m_SandSimulator = new cSandSimulator(*this, IniFile);
|
||||||
m_FireSimulator = new cFireSimulator(*this, IniFile);
|
m_FireSimulator = new cFireSimulator(*this, IniFile);
|
||||||
m_RedstoneSimulator = new cRedstoneSimulator(*this);
|
m_RedstoneSimulator = new cRedstoneSimulator(*this);
|
||||||
|
|
||||||
@ -1166,9 +1166,9 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
|
|||||||
float SpeedY = (float)(a_FlyAwaySpeed * r1.randInt(1000));
|
float SpeedY = (float)(a_FlyAwaySpeed * r1.randInt(1000));
|
||||||
float SpeedZ = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500));
|
float SpeedZ = (float)(a_FlyAwaySpeed * (r1.randInt(1000) - 500));
|
||||||
cPickup * Pickup = new cPickup(
|
cPickup * Pickup = new cPickup(
|
||||||
(int)(a_BlockX * 32) + r1.randInt(16) + r1.randInt(16),
|
(int)(a_BlockX * 32) + (r1.randInt(16) + r1.randInt(16) - 16),
|
||||||
(int)(a_BlockY * 32) + r1.randInt(16) + r1.randInt(16),
|
(int)(a_BlockY * 32) + (r1.randInt(16) + r1.randInt(16) - 16),
|
||||||
(int)(a_BlockZ * 32) + r1.randInt(16) + r1.randInt(16),
|
(int)(a_BlockZ * 32) + (r1.randInt(16) + r1.randInt(16) - 16),
|
||||||
*itr, SpeedX, SpeedY, SpeedZ
|
*itr, SpeedX, SpeedY, SpeedZ
|
||||||
);
|
);
|
||||||
Pickup->Initialize(this);
|
Pickup->Initialize(this);
|
||||||
|
@ -479,7 +479,7 @@ private:
|
|||||||
bool m_IsDeepSnowEnabled;
|
bool m_IsDeepSnowEnabled;
|
||||||
|
|
||||||
// The cRedstone class simulates redstone and needs access to m_RSList
|
// The cRedstone class simulates redstone and needs access to m_RSList
|
||||||
friend class cRedstone;
|
// friend class cRedstone;
|
||||||
std::vector<int> m_RSList;
|
std::vector<int> m_RSList;
|
||||||
|
|
||||||
std::vector<BlockTickQueueItem *> m_BlockTickQueue;
|
std::vector<BlockTickQueueItem *> m_BlockTickQueue;
|
||||||
|
Loading…
Reference in New Issue
Block a user