Moved growing from cWorld / cChunk to cBlockHandler descendants.
This commit is contained in:
@@ -102,40 +102,38 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
|
||||
int NumMSecs = static_cast<int>(a_Dt.count());
|
||||
for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
|
||||
{
|
||||
int x = itr->x;
|
||||
int y = itr->y;
|
||||
int z = itr->z;
|
||||
auto AbsPos = cChunkDef::RelativeToAbsolute({x, y, z}, a_Chunk->GetPosX(), a_Chunk->GetPosZ());
|
||||
BLOCKTYPE BlockType = a_Chunk->GetBlock(x, y, z);
|
||||
Vector3i relPos(itr->x, itr->y, itr->z);
|
||||
auto absPos = a_Chunk->RelativeToAbsolute(relPos);
|
||||
auto blockType = a_Chunk->GetBlock(relPos);
|
||||
|
||||
if (!IsAllowedBlock(BlockType))
|
||||
if (!IsAllowedBlock(blockType))
|
||||
{
|
||||
// The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire)
|
||||
FIRE_FLOG("FS: Removing block {0}", AbsPos);
|
||||
FIRE_FLOG("FS: Removing block {0}", absPos);
|
||||
itr = Data.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto BurnsForever = ((y > 0) && DoesBurnForever(a_Chunk->GetBlock(x, (y - 1), z)));
|
||||
auto BlockMeta = a_Chunk->GetMeta(x, y, z);
|
||||
auto BurnsForever = ((relPos.y > 0) && DoesBurnForever(a_Chunk->GetBlock(relPos.addedY(-1))));
|
||||
auto BlockMeta = a_Chunk->GetMeta(relPos);
|
||||
|
||||
auto Raining = std::any_of(std::begin(gCrossCoords), std::end(gCrossCoords),
|
||||
[this, AbsPos](Vector3i cc)
|
||||
[this, absPos](Vector3i cc)
|
||||
{
|
||||
return (m_World.IsWeatherWetAtXYZ(AbsPos + cc));
|
||||
return (m_World.IsWeatherWetAtXYZ(absPos + cc));
|
||||
}
|
||||
);
|
||||
|
||||
// Randomly burn out the fire if it is raining:
|
||||
if (!BurnsForever && Raining && GetRandomProvider().RandBool(CHANCE_BASE_RAIN_EXTINGUISH + (BlockMeta * CHANCE_AGE_M_RAIN_EXTINGUISH)))
|
||||
{
|
||||
a_Chunk->SetBlock({x, y, z}, E_BLOCK_AIR, 0);
|
||||
a_Chunk->SetBlock(relPos, E_BLOCK_AIR, 0);
|
||||
itr = Data.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to spread the fire:
|
||||
TrySpreadFire(a_Chunk, x, y, z);
|
||||
TrySpreadFire(a_Chunk, relPos);
|
||||
|
||||
itr->Data -= NumMSecs;
|
||||
if (itr->Data >= 0)
|
||||
@@ -145,20 +143,15 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
FIRE_FLOG("FS: Fire at {0} is stepping",
|
||||
a_Chunk->PositionToWorldPosition(itr->x, itr->y, itr->z)
|
||||
);
|
||||
*/
|
||||
// FIRE_FLOG("FS: Fire at {0} is stepping", absPos);
|
||||
|
||||
// Has the fire burnt out?
|
||||
if (BlockMeta == 0x0f)
|
||||
{
|
||||
// The fire burnt out completely
|
||||
FIRE_FLOG("FS: Fire at {0} burnt out, removing the fire block",
|
||||
a_Chunk->PositionToWorldPosition({itr->x, itr->y, itr->z})
|
||||
);
|
||||
a_Chunk->SetBlock({x, y, z}, E_BLOCK_AIR, 0);
|
||||
RemoveFuelNeighbors(a_Chunk, x, y, z);
|
||||
FIRE_FLOG("FS: Fire at {0} burnt out, removing the fire block", absPos);
|
||||
a_Chunk->SetBlock(relPos, E_BLOCK_AIR, 0);
|
||||
RemoveFuelNeighbors(a_Chunk, relPos);
|
||||
itr = Data.erase(itr);
|
||||
continue;
|
||||
}
|
||||
@@ -166,10 +159,10 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
|
||||
// Burn out the fire one step by increasing the meta:
|
||||
if (!BurnsForever)
|
||||
{
|
||||
a_Chunk->SetMeta(x, y, z, BlockMeta + 1);
|
||||
a_Chunk->SetMeta(relPos, BlockMeta + 1);
|
||||
}
|
||||
|
||||
itr->Data = GetBurnStepTime(a_Chunk, x, y, z); // TODO: Add some randomness into this
|
||||
itr->Data = GetBurnStepTime(a_Chunk, relPos); // TODO: Add some randomness into this
|
||||
++itr;
|
||||
} // for itr - Data[]
|
||||
}
|
||||
@@ -278,12 +271,12 @@ void cFireSimulator::AddBlock(Vector3i a_Block, cChunk * a_Chunk)
|
||||
|
||||
|
||||
|
||||
int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
bool IsBlockBelowSolid = false;
|
||||
if (a_RelY > 0)
|
||||
if (a_RelPos.y > 0)
|
||||
{
|
||||
BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelX, a_RelY - 1, a_RelZ);
|
||||
BLOCKTYPE BlockBelow = a_Chunk->GetBlock(a_RelPos.addedY(-1));
|
||||
if (DoesBurnForever(BlockBelow))
|
||||
{
|
||||
// Is burning atop of netherrack, burn forever (re-check in 10 sec)
|
||||
@@ -296,11 +289,11 @@ int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, in
|
||||
IsBlockBelowSolid = cBlockInfo::IsSolid(BlockBelow);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
|
||||
for (const auto & cross: gCrossCoords)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
if (a_Chunk->UnboundedRelGetBlock(a_RelX + gCrossCoords[i].x, a_RelY, a_RelZ + gCrossCoords[i].z, BlockType, BlockMeta))
|
||||
if (a_Chunk->UnboundedRelGetBlock(a_RelPos + cross, BlockType, BlockMeta))
|
||||
{
|
||||
if (IsFuel(BlockType))
|
||||
{
|
||||
@@ -314,7 +307,7 @@ int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, in
|
||||
// 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);
|
||||
a_Chunk->SetBlock(a_RelPos, E_BLOCK_AIR, 0);
|
||||
return 0;
|
||||
}
|
||||
return static_cast<int>(m_BurnStepTimeNonfuel);
|
||||
@@ -324,7 +317,7 @@ int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, in
|
||||
|
||||
|
||||
|
||||
void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
/*
|
||||
if (GetRandomProvider().RandBool(0.99))
|
||||
@@ -334,11 +327,11 @@ void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int
|
||||
}
|
||||
*/
|
||||
|
||||
for (int x = a_RelX - 1; x <= a_RelX + 1; x++)
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int z = a_RelZ - 1; z <= a_RelZ + 1; z++)
|
||||
for (int z = -1; z <= 1; z++)
|
||||
{
|
||||
for (int y = a_RelY - 1; y <= a_RelY + 2; y++) // flames spread up one more block than around
|
||||
for (int y = 1; y <= 2; y++) // flames spread up one more block than around
|
||||
{
|
||||
// No need to check the coords for equality with the parent block,
|
||||
// it cannot catch fire anyway (because it's not an air block)
|
||||
@@ -348,24 +341,18 @@ void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start the fire in the neighbor {x, y, z}
|
||||
/*
|
||||
FIRE_LOG("FS: Trying to start fire at {0}.",
|
||||
a_Chunk->PositionToWorldPosition(x, y, z)
|
||||
);
|
||||
*/
|
||||
if (CanStartFireInBlock(a_Chunk, x, y, z))
|
||||
// Start the fire in the neighbor a_RelPos + {x, y, z}
|
||||
auto dstRelPos = a_RelPos + Vector3i{x, y, z};
|
||||
if (CanStartFireInBlock(a_Chunk, dstRelPos))
|
||||
{
|
||||
int a_PosX = x + a_Chunk->GetPosX() * cChunkDef::Width;
|
||||
int a_PosZ = z + a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||
|
||||
if (cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, a_PosX, y, a_PosZ, ssFireSpread))
|
||||
auto dstAbsPos = a_Chunk->RelativeToAbsolute(dstRelPos);
|
||||
if (cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, dstAbsPos.x, dstAbsPos.y, dstAbsPos.z, ssFireSpread))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FIRE_FLOG("FS: Starting new fire at {0}.", Vector3i{a_PosX, y, a_PosZ});
|
||||
a_Chunk->UnboundedRelSetBlock(x, y, z, E_BLOCK_FIRE, 0);
|
||||
FIRE_FLOG("FS: Starting new fire at {0}.", dstAbsPos);
|
||||
a_Chunk->UnboundedRelSetBlock(dstRelPos, E_BLOCK_FIRE, 0);
|
||||
}
|
||||
} // for y
|
||||
} // for z
|
||||
@@ -376,45 +363,40 @@ void cFireSimulator::TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int
|
||||
|
||||
|
||||
|
||||
void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, Vector3i a_RelPos)
|
||||
{
|
||||
for (auto & Coord : gNeighborCoords)
|
||||
for (auto & coord : gNeighborCoords)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
int X = a_RelX + Coord.x;
|
||||
int Z = a_RelZ + Coord.z;
|
||||
|
||||
cChunkPtr Neighbour = a_Chunk->GetRelNeighborChunkAdjustCoords(X, Z);
|
||||
if (Neighbour == nullptr)
|
||||
auto relPos = a_RelPos + coord;
|
||||
auto neighbor = a_Chunk->GetRelNeighborChunkAdjustCoords(relPos);
|
||||
if (neighbor == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
BlockType = Neighbour->GetBlock(X, a_RelY + Coord.y, Z);
|
||||
BlockType = neighbor->GetBlock(relPos);
|
||||
|
||||
if (!IsFuel(BlockType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int AbsX = (Neighbour->GetPosX() * cChunkDef::Width) + X;
|
||||
int Y = a_RelY + Coord.y;
|
||||
int AbsZ = (Neighbour->GetPosZ() * cChunkDef::Width) + Z;
|
||||
|
||||
auto absPos = neighbor->RelativeToAbsolute(relPos);
|
||||
if (BlockType == E_BLOCK_TNT)
|
||||
{
|
||||
m_World.SpawnPrimedTNT({static_cast<double>(AbsX), static_cast<double>(Y), static_cast<double>(AbsZ)}, 0);
|
||||
Neighbour->SetBlock({X, Y, Z}, E_BLOCK_AIR, 0);
|
||||
neighbor->SetBlock(relPos, E_BLOCK_AIR, 0);
|
||||
m_World.SpawnPrimedTNT(absPos, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
bool ShouldReplaceFuel = (GetRandomProvider().RandBool(m_ReplaceFuelChance * (1.0 / MAX_CHANCE_REPLACE_FUEL)));
|
||||
if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, AbsX, Y, AbsZ, ssFireSpread))
|
||||
if (ShouldReplaceFuel && !cRoot::Get()->GetPluginManager()->CallHookBlockSpread(m_World, absPos.x, absPos.y, absPos.z, ssFireSpread))
|
||||
{
|
||||
Neighbour->SetBlock({X, Y, Z}, E_BLOCK_FIRE, 0);
|
||||
neighbor->SetBlock(relPos, E_BLOCK_FIRE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Neighbour->SetBlock({X, Y, Z}, E_BLOCK_AIR, 0);
|
||||
neighbor->SetBlock(relPos, E_BLOCK_AIR, 0);
|
||||
}
|
||||
} // for i - Coords[]
|
||||
}
|
||||
@@ -423,11 +405,11 @@ void cFireSimulator::RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_Rel
|
||||
|
||||
|
||||
|
||||
bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ)
|
||||
bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, Vector3i a_RelPos)
|
||||
{
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
|
||||
if (!a_NearChunk->UnboundedRelGetBlock(a_RelPos, BlockType, BlockMeta))
|
||||
{
|
||||
// The chunk is not accessible
|
||||
return false;
|
||||
@@ -439,9 +421,9 @@ bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAYCOUNT(gNeighborCoords); i++)
|
||||
for (const auto & neighbor: gNeighborCoords)
|
||||
{
|
||||
if (!a_NearChunk->UnboundedRelGetBlock(a_RelX + gNeighborCoords[i].x, a_RelY + gNeighborCoords[i].y, a_RelZ + gNeighborCoords[i].z, BlockType, BlockMeta))
|
||||
if (!a_NearChunk->UnboundedRelGetBlock(a_RelPos + neighbor, BlockType, BlockMeta))
|
||||
{
|
||||
// Neighbor inaccessible, skip it while evaluating
|
||||
continue;
|
||||
|
||||
@@ -46,19 +46,19 @@ protected:
|
||||
virtual void AddBlock(Vector3i a_Block, cChunk * a_Chunk) override;
|
||||
|
||||
/** Returns the time [msec] after which the specified fire block is stepped again; based on surrounding fuels */
|
||||
int GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||
int GetBurnStepTime(cChunk * a_Chunk, Vector3i a_RelPos);
|
||||
|
||||
/** Tries to spread fire to a neighborhood of the specified block */
|
||||
void TrySpreadFire(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||
void TrySpreadFire(cChunk * a_Chunk, Vector3i a_RelPos);
|
||||
|
||||
/** Removes all burnable blocks neighboring the specified block */
|
||||
void RemoveFuelNeighbors(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||
void RemoveFuelNeighbors(cChunk * a_Chunk, Vector3i a_RelPos);
|
||||
|
||||
/** Returns true if a fire can be started in the specified block,
|
||||
that is, it is an air block and has fuel next to it.
|
||||
Note that a_NearChunk may be a chunk neighbor to the block specified!
|
||||
The coords are relative to a_NearChunk but not necessarily in it. */
|
||||
bool CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||
bool CanStartFireInBlock(cChunk * a_NearChunk, Vector3i a_RelPos);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ void cFloodyFluidSimulator::SimulateBlock(cChunk * a_Chunk, int a_RelX, int a_Re
|
||||
}
|
||||
|
||||
// When in contact with water, lava should harden
|
||||
if (HardenBlock(a_Chunk, a_RelX, a_RelY, a_RelZ, MyBlock, MyMeta))
|
||||
if (HardenBlock(a_Chunk, {a_RelX, a_RelY, a_RelZ}, MyBlock, MyMeta))
|
||||
{
|
||||
// Block was changed, bail out
|
||||
return;
|
||||
@@ -221,19 +221,18 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
|
||||
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);
|
||||
Vector3i relPos(a_RelX, a_RelY, a_RelZ);
|
||||
a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(relPos);
|
||||
if ((a_NearChunk == nullptr) || (!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;
|
||||
|
||||
const auto absPos = a_NearChunk->RelativeToAbsolute(relPos);
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
a_NearChunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta);
|
||||
a_NearChunk->GetBlockTypeMeta(relPos, BlockType, BlockMeta);
|
||||
|
||||
if (IsAllowedBlock(BlockType))
|
||||
{
|
||||
@@ -252,13 +251,13 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
|
||||
// Lava flowing into water, change to stone / cobblestone based on direction:
|
||||
BLOCKTYPE NewBlock = (a_NewMeta == 8) ? E_BLOCK_STONE : E_BLOCK_COBBLESTONE;
|
||||
FLUID_FLOG(" Lava flowing into water, turning water at rel {0} into {1}",
|
||||
Vector3i{a_RelX, a_RelY, a_RelZ}, ItemTypeToString(NewBlock)
|
||||
relPos, ItemTypeToString(NewBlock)
|
||||
);
|
||||
a_NearChunk->SetBlock({a_RelX, a_RelY, a_RelZ}, NewBlock, 0);
|
||||
a_NearChunk->SetBlock(relPos, NewBlock, 0);
|
||||
|
||||
m_World.BroadcastSoundEffect(
|
||||
"block.lava.extinguish",
|
||||
Vector3d(BlockX, a_RelY, BlockZ),
|
||||
absPos,
|
||||
0.5f,
|
||||
1.5f
|
||||
);
|
||||
@@ -272,13 +271,13 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
|
||||
// Water flowing into lava, change to cobblestone / obsidian based on dest block:
|
||||
BLOCKTYPE NewBlock = (BlockMeta == 0) ? E_BLOCK_OBSIDIAN : E_BLOCK_COBBLESTONE;
|
||||
FLUID_FLOG(" Water flowing into lava, turning lava at rel {0} into {1}",
|
||||
Vector3i{a_RelX, a_RelY, a_RelZ}, ItemTypeToString(NewBlock)
|
||||
relPos, ItemTypeToString(NewBlock)
|
||||
);
|
||||
a_NearChunk->SetBlock({a_RelX, a_RelY, a_RelZ}, NewBlock, 0);
|
||||
a_NearChunk->SetBlock(relPos, NewBlock, 0);
|
||||
|
||||
m_World.BroadcastSoundEffect(
|
||||
"block.lava.extinguish",
|
||||
Vector3d(BlockX, a_RelY, BlockZ),
|
||||
absPos,
|
||||
0.5f,
|
||||
1.5f
|
||||
);
|
||||
@@ -302,16 +301,16 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
|
||||
cBlockHandler * Handler = BlockHandler(BlockType);
|
||||
if (Handler->DoesDropOnUnsuitable())
|
||||
{
|
||||
m_World.DropBlockAsPickups({BlockX, a_RelY, BlockZ}, nullptr, nullptr);
|
||||
m_World.DropBlockAsPickups(absPos, nullptr, nullptr);
|
||||
}
|
||||
} // if (CanWashAway)
|
||||
|
||||
// Spread:
|
||||
FLUID_FLOG(" Spreading to {0} with meta {1}", Vector3i{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);
|
||||
FLUID_FLOG(" Spreading to {0} with meta {1}", absPos, a_NewMeta);
|
||||
a_NearChunk->SetBlock(relPos, m_FluidBlock, a_NewMeta);
|
||||
m_World.GetSimulatorManager()->WakeUp(absPos, a_NearChunk);
|
||||
|
||||
HardenBlock(a_NearChunk, a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
|
||||
HardenBlock(a_NearChunk, relPos, m_FluidBlock, a_NewMeta);
|
||||
}
|
||||
|
||||
|
||||
@@ -365,8 +364,10 @@ bool cFloodyFluidSimulator::CheckNeighborsForSource(cChunk * a_Chunk, int a_RelX
|
||||
|
||||
|
||||
|
||||
bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta)
|
||||
{
|
||||
ASSERT(cChunkDef::IsValidRelPos(a_RelPos));
|
||||
|
||||
// Only lava blocks can harden
|
||||
if (!IsBlockLava(a_BlockType))
|
||||
{
|
||||
@@ -377,16 +378,16 @@ bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY
|
||||
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
static const Vector3i Coords[] =
|
||||
static const Vector3i neighborOffsets[] =
|
||||
{
|
||||
Vector3i( 1, 0, 0),
|
||||
Vector3i(-1, 0, 0),
|
||||
Vector3i( 0, 0, 1),
|
||||
Vector3i( 0, 0, -1),
|
||||
};
|
||||
for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
|
||||
for (const auto & ofs: neighborOffsets)
|
||||
{
|
||||
if (!a_Chunk->UnboundedRelGetBlock(a_RelX + Coords[i].x, a_RelY, a_RelZ + Coords[i].z, BlockType, BlockMeta))
|
||||
if (!a_Chunk->UnboundedRelGetBlock(a_RelPos + ofs, BlockType, BlockMeta))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -401,13 +402,13 @@ bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY
|
||||
if (a_Meta == 0)
|
||||
{
|
||||
// Source lava block
|
||||
a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, E_BLOCK_OBSIDIAN, 0);
|
||||
a_Chunk->SetBlock(a_RelPos, E_BLOCK_OBSIDIAN, 0);
|
||||
return true;
|
||||
}
|
||||
// Ignore last lava level
|
||||
else if (a_Meta <= 4)
|
||||
{
|
||||
a_Chunk->SetBlock({a_RelX, a_RelY, a_RelZ}, E_BLOCK_COBBLESTONE, 0);
|
||||
a_Chunk->SetBlock(a_RelPos, E_BLOCK_COBBLESTONE, 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ protected:
|
||||
|
||||
/** Checks if the specified block should harden (Water / Lava interaction) and if so, converts it to a suitable block.
|
||||
Returns whether the block was changed or not. */
|
||||
bool HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta);
|
||||
bool HardenBlock(cChunk * a_Chunk, Vector3i a_RelPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta);
|
||||
|
||||
/** Spread fluid to XZ neighbors.
|
||||
The coords are of the block currently being processed; a_NewMeta is the new meta for the new fluid block.
|
||||
|
||||
Reference in New Issue
Block a user