1
0

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:
Alexander Harkness 2017-12-26 21:25:57 +00:00 committed by GitHub
parent ab5ff6a6f8
commit 6309c6a97f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 180 additions and 113 deletions

View File

@ -238,7 +238,7 @@ return
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns whether the specified block type will be destroyed after a single hit.", Notes = "Returns true if the specified block type will be destroyed after a single hit.",
}, },
IsPistonBreakable = IsPistonBreakable =
{ {
@ -256,7 +256,43 @@ return
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns whether a piston can break the specified block type.", Notes = "Returns true if a piston can break the specified block type.",
},
IsRainBlocker =
{
IsStatic = true,
Params =
{
{
Name = "BlockType",
Type = "number",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "Returns true if the specified block type blocks rain from passing through.",
},
IsSkylightDispersant =
{
IsStatic = true,
Params =
{
{
Name = "BlockType",
Type = "number",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "Returns true if skylight is impeded by passage through a block of the specified type.",
}, },
IsSnowable = IsSnowable =
{ {
@ -294,24 +330,6 @@ return
}, },
Notes = "Returns whether the specified block type is solid.", Notes = "Returns whether the specified block type is solid.",
}, },
IsSkylightDispersant =
{
IsStatic = true,
Params =
{
{
Name = "BlockType",
Type = "number",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "Returns true if skylight is impeded by passage through a block of the specified type.",
},
IsTransparent = IsTransparent =
{ {
IsStatic = true, IsStatic = true,

View File

@ -2237,7 +2237,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the current world is raining (no thunderstorm).", Notes = "Returns true if the current weather is rainy.",
}, },
IsWeatherRainAt = IsWeatherRainAt =
{ {
@ -2258,7 +2258,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the specified location is raining (takes biomes into account - it never rains in a desert).", Notes = "Returns true if it is rainy at the specified location. This takes into account biomes.",
}, },
IsWeatherStorm = IsWeatherStorm =
{ {
@ -2268,7 +2268,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the current world is stormy.", Notes = "Returns true if the current weather is stormy.",
}, },
IsWeatherStormAt = IsWeatherStormAt =
{ {
@ -2289,7 +2289,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the specified location is stormy (takes biomes into account - no storm in a desert).", Notes = "Returns true if it is stormy at the specified location. This takes into account biomes.",
}, },
IsWeatherSunny = IsWeatherSunny =
{ {
@ -2320,7 +2320,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the current weather is sunny at the specified location (takes into account biomes).", Notes = "Returns true if it is sunny at the specified location. This takes into account biomes.",
}, },
IsWeatherWet = IsWeatherWet =
{ {
@ -2330,7 +2330,7 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the current world has any precipitation (rain or storm).", Notes = "Returns true if the world currently has any precipitation - rain, storm or snow.",
}, },
IsWeatherWetAt = IsWeatherWetAt =
{ {
@ -2351,7 +2351,24 @@ function OnAllChunksAvailable()</pre> All return values from the callbacks are i
Type = "boolean", Type = "boolean",
}, },
}, },
Notes = "Returns true if the specified location has any precipitation (rain or storm) (takes biomes into account, deserts are never wet).", Notes = "Returns true if it is raining or storming at the specified location. This takes into account biomes.",
},
IsWeatherWetAtXYZ =
{
Params =
{
{
Name = "Pos",
Type = "Vector3i",
},
},
Returns =
{
{
Type = "boolean",
},
},
Notes = "Returns true if the specified location has wet weather (rain or storm), using the same logic as IsWeatherWetAt, except that any rain-blocking blocks above the specified position will block the precipitation and this function will return false.",
}, },
PrepareChunk = PrepareChunk =
{ {
@ -3637,4 +3654,3 @@ World:ForEachEntity(
}, },
}, },
} }

View File

@ -464,6 +464,16 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
Info[E_BLOCK_YELLOW_SHULKER_BOX ].m_PistonBreakable = true; Info[E_BLOCK_YELLOW_SHULKER_BOX ].m_PistonBreakable = true;
/* Blocks that block rain or snow's passage:
* All solid blocks are also rain blockers, and they are set automatically
* at the end of this function.
*/
Info[E_BLOCK_SIGN_POST ].m_IsRainBlocker = true;
Info[E_BLOCK_WALLSIGN ].m_IsRainBlocker = true;
Info[E_BLOCK_WALL_BANNER ].m_IsRainBlocker = true;
Info[E_BLOCK_STANDING_BANNER ].m_IsRainBlocker = true;
// Blocks that can be snowed over: // Blocks that can be snowed over:
Info[E_BLOCK_BEDROCK ].m_IsSnowable = true; Info[E_BLOCK_BEDROCK ].m_IsSnowable = true;
Info[E_BLOCK_BLOCK_OF_COAL ].m_IsSnowable = true; Info[E_BLOCK_BLOCK_OF_COAL ].m_IsSnowable = true;
@ -554,8 +564,8 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
Info[E_BLOCK_BIG_FLOWER ].m_IsSolid = false; Info[E_BLOCK_BIG_FLOWER ].m_IsSolid = false;
Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSolid = false; Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSolid = false;
Info[E_BLOCK_CARROTS ].m_IsSolid = false; Info[E_BLOCK_CARROTS ].m_IsSolid = false;
Info[E_BLOCK_CHORUS_PLANT ].m_IsSolid = false;
Info[E_BLOCK_CHORUS_FLOWER ].m_IsSolid = false; Info[E_BLOCK_CHORUS_FLOWER ].m_IsSolid = false;
Info[E_BLOCK_CHORUS_PLANT ].m_IsSolid = false;
Info[E_BLOCK_COBWEB ].m_IsSolid = false; Info[E_BLOCK_COBWEB ].m_IsSolid = false;
Info[E_BLOCK_CROPS ].m_IsSolid = false; Info[E_BLOCK_CROPS ].m_IsSolid = false;
Info[E_BLOCK_DANDELION ].m_IsSolid = false; Info[E_BLOCK_DANDELION ].m_IsSolid = false;
@ -575,17 +585,17 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
Info[E_BLOCK_POTATOES ].m_IsSolid = false; Info[E_BLOCK_POTATOES ].m_IsSolid = false;
Info[E_BLOCK_POWERED_RAIL ].m_IsSolid = false; Info[E_BLOCK_POWERED_RAIL ].m_IsSolid = false;
Info[E_BLOCK_RAIL ].m_IsSolid = false; Info[E_BLOCK_RAIL ].m_IsSolid = false;
Info[E_BLOCK_RED_MUSHROOM ].m_IsSolid = false;
Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_IsSolid = false; Info[E_BLOCK_REDSTONE_TORCH_OFF ].m_IsSolid = false;
Info[E_BLOCK_REDSTONE_TORCH_ON ].m_IsSolid = false; Info[E_BLOCK_REDSTONE_TORCH_ON ].m_IsSolid = false;
Info[E_BLOCK_REDSTONE_WIRE ].m_IsSolid = false; Info[E_BLOCK_REDSTONE_WIRE ].m_IsSolid = false;
Info[E_BLOCK_RED_MUSHROOM ].m_IsSolid = false;
Info[E_BLOCK_REEDS ].m_IsSolid = false; Info[E_BLOCK_REEDS ].m_IsSolid = false;
Info[E_BLOCK_SAPLING ].m_IsSolid = false; Info[E_BLOCK_SAPLING ].m_IsSolid = false;
Info[E_BLOCK_SIGN_POST ].m_IsSolid = false; Info[E_BLOCK_SIGN_POST ].m_IsSolid = false;
Info[E_BLOCK_SNOW ].m_IsSolid = false; Info[E_BLOCK_SNOW ].m_IsSolid = false;
Info[E_BLOCK_STANDING_BANNER ].m_IsSolid = false;
Info[E_BLOCK_STATIONARY_LAVA ].m_IsSolid = false; Info[E_BLOCK_STATIONARY_LAVA ].m_IsSolid = false;
Info[E_BLOCK_STATIONARY_WATER ].m_IsSolid = false; Info[E_BLOCK_STATIONARY_WATER ].m_IsSolid = false;
Info[E_BLOCK_STANDING_BANNER ].m_IsSolid = false;
Info[E_BLOCK_STONE_BUTTON ].m_IsSolid = false; Info[E_BLOCK_STONE_BUTTON ].m_IsSolid = false;
Info[E_BLOCK_STONE_PRESSURE_PLATE ].m_IsSolid = false; Info[E_BLOCK_STONE_PRESSURE_PLATE ].m_IsSolid = false;
Info[E_BLOCK_TALL_GRASS ].m_IsSolid = false; Info[E_BLOCK_TALL_GRASS ].m_IsSolid = false;
@ -974,8 +984,9 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
Info[E_BLOCK_RED_SHULKER_BOX ].m_Hardness = 0.2f; Info[E_BLOCK_RED_SHULKER_BOX ].m_Hardness = 0.2f;
Info[E_BLOCK_BLACK_SHULKER_BOX ].m_Hardness = 0.2f; Info[E_BLOCK_BLACK_SHULKER_BOX ].m_Hardness = 0.2f;
Info[E_BLOCK_STRUCTURE_BLOCK ].m_Hardness = -1.0f; Info[E_BLOCK_STRUCTURE_BLOCK ].m_Hardness = -1.0f;
for (size_t i = 0; i < Info.size(); ++i)
{
Info[i].m_IsRainBlocker |= Info[i].m_IsSolid;
}
} }

View File

@ -37,7 +37,10 @@ public:
/** Can a piston break this block? */ /** Can a piston break this block? */
bool m_PistonBreakable; bool m_PistonBreakable;
/** Does a block disperse sky light? (only relevant for transparent blocks) */ /** Does this block block the passage of rain? */
bool m_IsRainBlocker;
/** Does this block disperse sky light? (only relevant for transparent blocks) */
bool m_IsSkylightDispersant; bool m_IsSkylightDispersant;
/** Can this block hold snow atop? */ /** Can this block hold snow atop? */
@ -79,6 +82,7 @@ public:
inline static bool IsTransparent (BLOCKTYPE a_Type) { return Get(a_Type).m_Transparent; } inline static bool IsTransparent (BLOCKTYPE a_Type) { return Get(a_Type).m_Transparent; }
inline static bool IsOneHitDig (BLOCKTYPE a_Type) { return Get(a_Type).m_OneHitDig; } inline static bool IsOneHitDig (BLOCKTYPE a_Type) { return Get(a_Type).m_OneHitDig; }
inline static bool IsPistonBreakable (BLOCKTYPE a_Type) { return Get(a_Type).m_PistonBreakable; } inline static bool IsPistonBreakable (BLOCKTYPE a_Type) { return Get(a_Type).m_PistonBreakable; }
inline static bool IsRainBlocker (BLOCKTYPE a_Type) { return Get(a_Type).m_IsRainBlocker; }
inline static bool IsSkylightDispersant (BLOCKTYPE a_Type) inline static bool IsSkylightDispersant (BLOCKTYPE a_Type)
{ {
return ((Get(a_Type).m_IsSkylightDispersant) || (Get(a_Type).m_SpreadLightFalloff > 1)); return ((Get(a_Type).m_IsSkylightDispersant) || (Get(a_Type).m_SpreadLightFalloff > 1));
@ -102,6 +106,7 @@ public:
, m_Transparent(false) , m_Transparent(false)
, m_OneHitDig(false) , m_OneHitDig(false)
, m_PistonBreakable(false) , m_PistonBreakable(false)
, m_IsRainBlocker(false)
, m_IsSkylightDispersant(false) , m_IsSkylightDispersant(false)
, m_IsSnowable(false) , m_IsSnowable(false)
, m_IsSolid(true) , m_IsSolid(true)
@ -149,7 +154,3 @@ inline cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
{ {
return cBlockInfo::Get(a_BlockType).m_Handler.get(); return cBlockInfo::Get(a_BlockType).m_Handler.get();
} }

View File

@ -65,7 +65,7 @@ public:
virtual void SetTimeOfDay(int a_TimeOfDay) = 0; virtual void SetTimeOfDay(int a_TimeOfDay) = 0;
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */ /** Returns true if it is raining or storming at the specified location. This takes into account biomes. */
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0; virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
/** Returns or sets the minumim or maximum netherportal width */ /** Returns or sets the minumim or maximum netherportal width */

View File

@ -1172,12 +1172,9 @@ void cEntity::TickBurning(cChunk & a_Chunk)
} }
// Fire is extinguished by rain // Fire is extinguished by rain
if (GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT)) if (GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()))
{ {
if (POSY_TOINT > m_World->GetHeight(POSX_TOINT, POSZ_TOINT)) m_TicksLeftBurning = 0;
{
m_TicksLeftBurning = 0;
}
} }
// Do the burning damage: // Do the burning damage:

View File

@ -194,37 +194,13 @@ void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
} }
// Take damage when touching water, drowning damage seems to be most appropriate // Take damage when touching water, drowning damage seems to be most appropriate
if (CheckRain() || IsSwimming()) if (
cChunkDef::IsValidHeight(POSY_TOINT) &&
(GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()) || IsSwimming())
)
{ {
EventLosePlayer(); EventLosePlayer();
TakeDamage(dtDrowning, nullptr, 1, 0); TakeDamage(dtDrowning, nullptr, 1, 0);
// TODO teleport to a safe location // TODO teleport to a safe location
} }
} }
bool cEnderman::CheckRain(void)
{
if (!GetWorld()->IsWeatherRain())
{
return false;
}
Vector3d coords = GetPosition();
for (int Y = static_cast<int>(coords.y); Y < cChunkDef::Height; ++Y)
{
BLOCKTYPE Block = m_World->GetBlock(static_cast<int>(coords.x), Y, static_cast<int>(coords.z));
if (Block != E_BLOCK_AIR)
{
return false;
}
}
return true;
}

View File

@ -29,8 +29,6 @@ public:
/** Returns if the current sky light level is sufficient for the enderman to become aggravated */ /** Returns if the current sky light level is sufficient for the enderman to become aggravated */
bool CheckLight(void); bool CheckLight(void);
/** Returns if the enderman gets hit by the rain */
bool CheckRain(void);
private: private:
@ -39,7 +37,3 @@ private:
NIBBLETYPE CarriedMeta; NIBBLETYPE CarriedMeta;
} ; } ;

View File

@ -29,7 +29,6 @@ SET (HDRS
VaporizeFluidSimulator.h VaporizeFluidSimulator.h
) )
if(NOT MSVC) if(NOT MSVC)
add_library(Simulator ${SRCS} ${HDRS}) add_library(Simulator ${SRCS} ${HDRS})
endif() endif()

View File

@ -25,15 +25,22 @@
#define MAX_CHANCE_REPLACE_FUEL 100000 #define MAX_CHANCE_REPLACE_FUEL 100000
#define MAX_CHANCE_FLAMMABILITY 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 #ifdef __clang__
{ #pragma clang diagnostic push
int x, y, z; #pragma clang diagnostic ignored "-Wglobal-constructors"
} gCrossCoords[] = #endif
static const Vector3i gCrossCoords[] =
{ {
{ 1, 0, 0}, { 1, 0, 0},
{-1, 0, 0}, {-1, 0, 0},
@ -45,10 +52,7 @@ static const struct
static const struct static const Vector3i gNeighborCoords[] =
{
int x, y, z;
} gNeighborCoords[] =
{ {
{ 1, 0, 0}, { 1, 0, 0},
{-1, 0, 0}, {-1, 0, 0},
@ -58,6 +62,10 @@ static const struct
{ 0, 0, -1}, { 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 x = itr->x;
int y = itr->y; int y = itr->y;
int z = itr->z; 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); BLOCKTYPE BlockType = a_Chunk->GetBlock(x, y, z);
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) // 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}", 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); itr = Data.erase(itr);
continue; 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: // Try to spread the fire:
TrySpreadFire(a_Chunk, itr->x, itr->y, itr->z); TrySpreadFire(a_Chunk, x, y, z);
itr->Data -= NumMSecs; itr->Data -= NumMSecs;
if (itr->Data >= 0) if (itr->Data >= 0)
@ -120,30 +147,30 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
continue; continue;
} }
// Burn out the fire one step by increasing the meta:
/* /*
FLOG("FS: Fire at {%d, %d, %d} is stepping", FLOG("FS: Fire at {%d, %d, %d} is stepping",
itr->x + a_ChunkX * cChunkDef::Width, itr->y, itr->z + a_ChunkZ * cChunkDef::Width 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) if (BlockMeta == 0x0f)
{ {
// The fire burnt out completely
FLOG("FS: Fire at {%d, %d, %d} burnt out, removing the fire block", 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 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); a_Chunk->SetBlock(x, y, z, E_BLOCK_AIR, 0);
RemoveFuelNeighbors(a_Chunk, itr->x, itr->y, itr->z); RemoveFuelNeighbors(a_Chunk, x, y, z);
itr = Data.erase(itr); itr = Data.erase(itr);
continue; 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); 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; ++itr;
} // for itr - Data[] } // for itr - Data[]
} }
@ -283,7 +310,7 @@ int cFireSimulator::GetBurnStepTime(cChunk * a_Chunk, int a_RelX, int a_RelY, in
} }
} // for i - gCrossCoords[] } // for i - gCrossCoords[]
if (!IsBlockBelowSolid && (a_RelY >= 0)) if (!IsBlockBelowSolid)
{ {
// Checked through everything, nothing was flammable // Checked through everything, nothing was flammable
// If block below isn't solid, we can't have fire, it would be a non-fueled fire // 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[] } // for i - Coords[]
return false; return false;
} }

View File

@ -542,6 +542,34 @@ void cWorld::ChangeWeather(void)
bool cWorld::IsWeatherWetAtXYZ(Vector3i a_Pos)
{
if ((a_Pos.y < 0) || !IsWeatherWetAt(a_Pos.x, a_Pos.z))
{
return false;
}
if (a_Pos.y >= cChunkDef::Height)
{
return true;
}
for (int y = GetHeight(a_Pos.x, a_Pos.z); y >= a_Pos.y; y--)
{
auto BlockType = GetBlock({a_Pos.x, y, a_Pos.z});
if (cBlockInfo::IsRainBlocker(BlockType))
{
return false;
}
}
return true;
}
void cWorld::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ) void cWorld::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
return m_ChunkMap->SetNextBlockTick(a_BlockX, a_BlockY, a_BlockZ); return m_ChunkMap->SetNextBlockTick(a_BlockX, a_BlockY, a_BlockZ);

View File

@ -766,7 +766,7 @@ public:
/** Returns the current weather. Instead of comparing values directly to the weather constants, use IsWeatherXXX() functions, if possible */ /** Returns the current weather. Instead of comparing values directly to the weather constants, use IsWeatherXXX() functions, if possible */
eWeather GetWeather(void) const { return m_Weather; } eWeather GetWeather(void) const { return m_Weather; }
/** Returns true if the current weather is sun */ /** Returns true if the current weather is sunny. */
bool IsWeatherSunny(void) const { return (m_Weather == wSunny); } bool IsWeatherSunny(void) const { return (m_Weather == wSunny); }
/** Returns true if it is sunny at the specified location. This takes into account biomes. */ /** Returns true if it is sunny at the specified location. This takes into account biomes. */
@ -775,7 +775,7 @@ public:
return (IsWeatherSunny() || IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); return (IsWeatherSunny() || IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
} }
/** Returns true if the current weather is rain */ /** Returns true if the current weather is rainy. */
bool IsWeatherRain(void) const { return (m_Weather == wRain); } bool IsWeatherRain(void) const { return (m_Weather == wRain); }
/** Returns true if it is raining at the specified location. This takes into account biomes. */ /** Returns true if it is raining at the specified location. This takes into account biomes. */
@ -784,7 +784,7 @@ public:
return (IsWeatherRain() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); return (IsWeatherRain() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
} }
/** Returns true if the current weather is stormy */ /** Returns true if the current weather is stormy. */
bool IsWeatherStorm(void) const { return (m_Weather == wStorm); } bool IsWeatherStorm(void) const { return (m_Weather == wStorm); }
/** Returns true if the weather is stormy at the specified location. This takes into account biomes. */ /** Returns true if the weather is stormy at the specified location. This takes into account biomes. */
@ -793,15 +793,23 @@ public:
return (IsWeatherStorm() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); return (IsWeatherStorm() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
} }
/** Returns true if the current weather has any precipitation - rain, storm or snow */ /** Returns true if the world currently has any precipitation - rain, storm or snow. */
bool IsWeatherWet(void) const { return !IsWeatherSunny(); } bool IsWeatherWet(void) const { return !IsWeatherSunny(); }
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */ /** Returns true if it is raining or storming at the specified location.
This takes into account biomes. */
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override
{ {
return (IsWeatherWet() && !IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ))); auto Biome = GetBiomeAt(a_BlockX, a_BlockZ);
return (IsWeatherWet() && !IsBiomeNoDownfall(Biome) && !IsBiomeCold(Biome));
} }
/** Returns true if the specified location has wet weather (rain or storm),
using the same logic as IsWeatherWetAt, except that any rain-blocking blocks
above the specified position will block the precipitation and this function
will return false. */
virtual bool IsWeatherWetAtXYZ(Vector3i a_Pos);
/** Returns the seed of the world. */ /** Returns the seed of the world. */
int GetSeed(void) { return m_Generator.GetSeed(); } int GetSeed(void) { return m_Generator.GetSeed(); }
@ -1129,7 +1137,3 @@ private:
void SetChunkData(cSetChunkData & a_SetChunkData); void SetChunkData(cSetChunkData & a_SetChunkData);
}; // tolua_export }; // tolua_export