summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexander Harkness <me@bearbin.net>2017-12-26 22:25:57 +0100
committerGitHub <noreply@github.com>2017-12-26 22:25:57 +0100
commit6309c6a97fdbabfde978358f5f9a0f61ab74f91f (patch)
tree18b76401b21bb16425d6a630e109d737afea6bb7 /src
parent.editorconfig fixes (#4113) (diff)
downloadcuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar.gz
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar.bz2
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar.lz
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar.xz
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.tar.zst
cuberite-6309c6a97fdbabfde978358f5f9a0f61ab74f91f.zip
Diffstat (limited to 'src')
-rw-r--r--src/BlockInfo.cpp25
-rw-r--r--src/BlockInfo.h11
-rw-r--r--src/Blocks/WorldInterface.h2
-rw-r--r--src/Entities/Entity.cpp7
-rw-r--r--src/Mobs/Enderman.cpp32
-rw-r--r--src/Mobs/Enderman.h6
-rw-r--r--src/Simulator/CMakeLists.txt1
-rw-r--r--src/Simulator/FireSimulator.cpp67
-rw-r--r--src/World.cpp28
-rw-r--r--src/World.h24
10 files changed, 118 insertions, 85 deletions
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index 3021c5efe..c2f248a26 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -464,6 +464,16 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
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:
Info[E_BLOCK_BEDROCK ].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_BROWN_MUSHROOM ].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_PLANT ].m_IsSolid = false;
Info[E_BLOCK_COBWEB ].m_IsSolid = false;
Info[E_BLOCK_CROPS ].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_POWERED_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_ON ].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_SAPLING ].m_IsSolid = false;
Info[E_BLOCK_SIGN_POST ].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_WATER ].m_IsSolid = false;
- Info[E_BLOCK_STANDING_BANNER ].m_IsSolid = false;
Info[E_BLOCK_STONE_BUTTON ].m_IsSolid = false;
Info[E_BLOCK_STONE_PRESSURE_PLATE ].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_BLACK_SHULKER_BOX ].m_Hardness = 0.2f;
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;
+ }
+}
diff --git a/src/BlockInfo.h b/src/BlockInfo.h
index fd8408638..e7544bf2d 100644
--- a/src/BlockInfo.h
+++ b/src/BlockInfo.h
@@ -37,7 +37,10 @@ public:
/** Can a piston break this block? */
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;
/** 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 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 IsRainBlocker (BLOCKTYPE a_Type) { return Get(a_Type).m_IsRainBlocker; }
inline static bool IsSkylightDispersant (BLOCKTYPE a_Type)
{
return ((Get(a_Type).m_IsSkylightDispersant) || (Get(a_Type).m_SpreadLightFalloff > 1));
@@ -102,6 +106,7 @@ public:
, m_Transparent(false)
, m_OneHitDig(false)
, m_PistonBreakable(false)
+ , m_IsRainBlocker(false)
, m_IsSkylightDispersant(false)
, m_IsSnowable(false)
, m_IsSolid(true)
@@ -149,7 +154,3 @@ inline cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
{
return cBlockInfo::Get(a_BlockType).m_Handler.get();
}
-
-
-
-
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index 19c520ece..344eb9ca3 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -65,7 +65,7 @@ public:
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;
/** Returns or sets the minumim or maximum netherportal width */
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 4245f607d..646566ae6 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1172,12 +1172,9 @@ void cEntity::TickBurning(cChunk & a_Chunk)
}
// 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:
diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp
index 000496df0..b7013affd 100644
--- a/src/Mobs/Enderman.cpp
+++ b/src/Mobs/Enderman.cpp
@@ -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
- if (CheckRain() || IsSwimming())
+ if (
+ cChunkDef::IsValidHeight(POSY_TOINT) &&
+ (GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()) || IsSwimming())
+ )
{
EventLosePlayer();
TakeDamage(dtDrowning, nullptr, 1, 0);
// 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;
-}
-
-
-
-
diff --git a/src/Mobs/Enderman.h b/src/Mobs/Enderman.h
index c9ffbeaba..d8731b709 100644
--- a/src/Mobs/Enderman.h
+++ b/src/Mobs/Enderman.h
@@ -29,8 +29,6 @@ public:
/** Returns if the current sky light level is sufficient for the enderman to become aggravated */
bool CheckLight(void);
- /** Returns if the enderman gets hit by the rain */
- bool CheckRain(void);
private:
@@ -39,7 +37,3 @@ private:
NIBBLETYPE CarriedMeta;
} ;
-
-
-
-
diff --git a/src/Simulator/CMakeLists.txt b/src/Simulator/CMakeLists.txt
index 45972a6ef..5a67dd026 100644
--- a/src/Simulator/CMakeLists.txt
+++ b/src/Simulator/CMakeLists.txt
@@ -29,7 +29,6 @@ SET (HDRS
VaporizeFluidSimulator.h
)
-
if(NOT MSVC)
add_library(Simulator ${SRCS} ${HDRS})
endif()
diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp
index d5671c5c2..ac7456b0a 100644
--- a/src/Simulator/FireSimulator.cpp
+++ b/src/Simulator/FireSimulator.cpp
@@ -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;
}
-
-
-
-
diff --git a/src/World.cpp b/src/World.cpp
index 4dd9cbc86..4cf25aee3 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -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)
{
return m_ChunkMap->SetNextBlockTick(a_BlockX, a_BlockY, a_BlockZ);
diff --git a/src/World.h b/src/World.h
index d76f4c258..bce9212af 100644
--- a/src/World.h
+++ b/src/World.h
@@ -766,7 +766,7 @@ public:
/** 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; }
- /** Returns true if the current weather is sun */
+ /** Returns true if the current weather is sunny. */
bool IsWeatherSunny(void) const { return (m_Weather == wSunny); }
/** 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)));
}
- /** Returns true if the current weather is rain */
+ /** Returns true if the current weather is rainy. */
bool IsWeatherRain(void) const { return (m_Weather == wRain); }
/** 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)));
}
- /** Returns true if the current weather is stormy */
+ /** Returns true if the current weather is stormy. */
bool IsWeatherStorm(void) const { return (m_Weather == wStorm); }
/** 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)));
}
- /** 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(); }
- /** 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
{
- 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. */
int GetSeed(void) { return m_Generator.GetSeed(); }
@@ -1129,7 +1137,3 @@ private:
void SetChunkData(cSetChunkData & a_SetChunkData);
}; // tolua_export
-
-
-
-