improve rain simulation (#4017)
* Uses vanilla logic to decide which blocks rain falls through. * Rain falls infinitely above the world, and stops at y=0. * Entities will now be extinguished if they are under rain-blocking blocks, and fire will now be extinguished by rain similarly. * Create IsWeatherWetAtXYZ to identify wetness at a particular location. * Use new code for enderman rain detection. * Fixes issue #916 * Disable warnings for global constructors in the fire simulator.
This commit is contained in:
committed by
GitHub
parent
ab5ff6a6f8
commit
6309c6a97f
@@ -25,15 +25,22 @@
|
||||
|
||||
#define MAX_CHANCE_REPLACE_FUEL 100000
|
||||
#define MAX_CHANCE_FLAMMABILITY 100000
|
||||
// The base chance that in a tick, rain will extinguish a fire block.
|
||||
#define CHANCE_BASE_RAIN_EXTINGUISH 0.2
|
||||
// The additional chance, multiplied by the meta of the fire block, that rain
|
||||
// will extinguish a fire block in a tick.
|
||||
#define CHANCE_AGE_M_RAIN_EXTINGUISH 0.03
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const struct
|
||||
{
|
||||
int x, y, z;
|
||||
} gCrossCoords[] =
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||
#endif
|
||||
|
||||
static const Vector3i gCrossCoords[] =
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
@@ -45,10 +52,7 @@ static const struct
|
||||
|
||||
|
||||
|
||||
static const struct
|
||||
{
|
||||
int x, y, z;
|
||||
} gNeighborCoords[] =
|
||||
static const Vector3i gNeighborCoords[] =
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
@@ -58,6 +62,10 @@ static const struct
|
||||
{ 0, 0, -1},
|
||||
} ;
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -97,20 +105,39 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
|
||||
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);
|
||||
|
||||
if (!IsAllowedBlock(BlockType))
|
||||
{
|
||||
// The block is no longer eligible (not a fire block anymore; a player probably placed a block over the fire)
|
||||
FLOG("FS: Removing block {%d, %d, %d}",
|
||||
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
|
||||
AbsPos.x, AbsPos.y, AbsPos.z
|
||||
);
|
||||
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 Raining = std::any_of(std::begin(gCrossCoords), std::end(gCrossCoords),
|
||||
[this, AbsPos](Vector3i 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);
|
||||
itr = Data.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to spread the fire:
|
||||
TrySpreadFire(a_Chunk, itr->x, itr->y, itr->z);
|
||||
TrySpreadFire(a_Chunk, x, y, z);
|
||||
|
||||
itr->Data -= NumMSecs;
|
||||
if (itr->Data >= 0)
|
||||
@@ -120,30 +147,30 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
|
||||
continue;
|
||||
}
|
||||
|
||||
// Burn out the fire one step by increasing the meta:
|
||||
/*
|
||||
FLOG("FS: Fire at {%d, %d, %d} is stepping",
|
||||
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
|
||||
);
|
||||
*/
|
||||
NIBBLETYPE BlockMeta = a_Chunk->GetMeta(x, y, z);
|
||||
// Has the fire burnt out?
|
||||
if (BlockMeta == 0x0f)
|
||||
{
|
||||
// The fire burnt out completely
|
||||
FLOG("FS: Fire at {%d, %d, %d} burnt out, removing the fire block",
|
||||
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width
|
||||
);
|
||||
a_Chunk->SetBlock(itr->x, itr->y, itr->z, E_BLOCK_AIR, 0);
|
||||
RemoveFuelNeighbors(a_Chunk, itr->x, itr->y, itr->z);
|
||||
a_Chunk->SetBlock(x, y, z, E_BLOCK_AIR, 0);
|
||||
RemoveFuelNeighbors(a_Chunk, x, y, z);
|
||||
itr = Data.erase(itr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((itr->y > 0) && (!DoesBurnForever(a_Chunk->GetBlock(itr->x, itr->y - 1, itr->z))))
|
||||
// Burn out the fire one step by increasing the meta:
|
||||
if (!BurnsForever)
|
||||
{
|
||||
a_Chunk->SetMeta(x, y, z, BlockMeta + 1);
|
||||
}
|
||||
itr->Data = GetBurnStepTime(a_Chunk, itr->x, itr->y, itr->z); // TODO: Add some randomness into this
|
||||
|
||||
itr->Data = GetBurnStepTime(a_Chunk, x, y, z); // TODO: Add some randomness into this
|
||||
++itr;
|
||||
} // for itr - Data[]
|
||||
}
|
||||
@@ -283,7 +310,7 @@ int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, in
|
||||
}
|
||||
} // for i - gCrossCoords[]
|
||||
|
||||
if (!IsBlockBelowSolid && (a_RelY >= 0))
|
||||
if (!IsBlockBelowSolid)
|
||||
{
|
||||
// Checked through everything, nothing was flammable
|
||||
// If block below isn't solid, we can't have fire, it would be a non-fueled fire
|
||||
@@ -427,7 +454,3 @@ bool cFireSimulator::CanStartFireInBlock(cChunk * a_NearChunk, int a_RelX, int a
|
||||
} // for i - Coords[]
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user