summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2021-01-05 03:13:02 +0100
committerTiger Wang <ziwei.tiger@outlook.com>2021-01-11 17:39:56 +0100
commit9328afe65c72b29f5cedbf1897ea8559f6b2c42f (patch)
tree92d9490d062009278ed8d78f8981014e88ba8f05
parentzlib -> libdeflate (#5085) (diff)
downloadcuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar.gz
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar.bz2
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar.lz
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar.xz
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.tar.zst
cuberite-9328afe65c72b29f5cedbf1897ea8559f6b2c42f.zip
-rw-r--r--src/Blocks/BlockFarmland.h5
-rw-r--r--src/Chunk.cpp58
-rw-r--r--src/Chunk.h12
-rw-r--r--src/ChunkMap.cpp62
-rw-r--r--src/ChunkMap.h19
-rw-r--r--src/Entities/Entity.cpp4
-rw-r--r--src/Entities/Floater.cpp24
-rw-r--r--src/MobSpawner.cpp7
-rw-r--r--src/Mobs/Enderman.cpp14
-rw-r--r--src/Mobs/Monster.cpp8
-rw-r--r--src/Mobs/SnowGolem.cpp18
-rw-r--r--src/Simulator/FireSimulator.cpp13
-rw-r--r--src/World.cpp35
-rw-r--r--src/World.h13
14 files changed, 204 insertions, 88 deletions
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index f7003a650..2622ac98c 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -115,13 +115,14 @@ private:
/** Returns true if there's either a water source block close enough to hydrate the specified position, or it's raining there. */
static bool IsWaterInNear(const cChunk & a_Chunk, const Vector3i a_RelPos)
{
- const auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos);
- if (a_Chunk.GetWorld()->IsWeatherWetAtXYZ(WorldPos))
+ if (a_Chunk.IsWeatherWetAt(a_RelPos.addedY(1)))
{
// Rain hydrates farmland, too
return true;
}
+ const auto WorldPos = a_Chunk.RelativeToAbsolute(a_RelPos);
+
// Search for water in a close proximity:
// Ref.: https://minecraft.gamepedia.com/Farmland#Hydration
// TODO: Rewrite this to use the chunk and its neighbors directly
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 5a6cca3eb..4140d4f85 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -626,7 +626,6 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
int WorldX, WorldY, WorldZ;
PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
- EMCSBiome Biome = m_ChunkMap->GetBiomeAt(WorldX, WorldZ);
// MG TODO :
// Moon cycle (for slime)
// check player and playerspawn presence < 24 blocks
@@ -641,12 +640,16 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
*/
NumberOfTries++;
- if (!IsLightValid())
+
+ Vector3i Try(TryX, TryY, TryZ);
+ const auto Chunk = GetRelNeighborChunkAdjustCoords(Try);
+
+ if ((Chunk == nullptr) || !Chunk->IsValid() || !Chunk->IsLightValid())
{
continue;
}
- auto newMob = a_MobSpawner.TryToSpawnHere(this, {TryX, TryY, TryZ}, Biome, MaxNbOfSuccess);
+ auto newMob = a_MobSpawner.TryToSpawnHere(this, Try, GetBiomeAt(Try.x, Try.z), MaxNbOfSuccess);
if (newMob == nullptr)
{
continue;
@@ -1190,15 +1193,56 @@ bool cChunk::UnboundedRelFastSetBlock(Vector3i a_RelPos, BLOCKTYPE a_BlockType,
-int cChunk::GetHeight(int a_X, int a_Z)
+int cChunk::GetHeight(int a_X, int a_Z) const
{
ASSERT((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width));
+ return m_HeightMap[a_X + a_Z * Width];
+}
+
+
+
+
+
+bool cChunk::IsWeatherSunnyAt(int a_RelX, int a_RelZ) const
+{
+ return m_World->IsWeatherSunny() || IsBiomeNoDownfall(GetBiomeAt(a_RelX, a_RelZ));
+}
+
+
+
+
+
+bool cChunk::IsWeatherWetAt(const int a_RelX, const int a_RelZ) const
+{
+ const auto Biome = GetBiomeAt(a_RelX, a_RelZ);
+ return m_World->IsWeatherWet() && !IsBiomeNoDownfall(Biome) && !IsBiomeCold(Biome);
+}
- if ((a_X >= 0) && (a_X < Width) && (a_Z >= 0) && (a_Z < Width))
+
+
+
+
+bool cChunk::IsWeatherWetAt(const Vector3i a_Position) const
+{
+ if ((a_Position.y < 0) || !IsWeatherWetAt(a_Position.x, a_Position.z))
+ {
+ return false;
+ }
+
+ if (a_Position.y >= cChunkDef::Height)
{
- return m_HeightMap[a_X + a_Z * Width];
+ return true;
}
- return 0;
+
+ for (int y = GetHeight(a_Position.x, a_Position.z); y >= a_Position.y; y--)
+ {
+ if (cBlockInfo::IsRainBlocker(GetBlock({ a_Position.x, y, a_Position.z })))
+ {
+ return false;
+ }
+ }
+
+ return true;
}
diff --git a/src/Chunk.h b/src/Chunk.h
index 28f7b0bec..d0283f3e4 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -221,7 +221,17 @@ public:
/** Sets the sign text. Returns true if successful. Also sends update packets to all clients in the chunk */
bool SetSignLines(int a_RelX, int a_RelY, int a_RelZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4);
- int GetHeight( int a_X, int a_Z);
+ int GetHeight( int a_X, int a_Z) const;
+
+ /** Returns true if it is sunny at the specified location. This takes into account biomes. */
+ bool IsWeatherSunnyAt(int a_RelX, int a_RelZ) const;
+
+ /** Returns true if it is raining or storming at the specified location, taking into account biomes. */
+ bool IsWeatherWetAt(int a_RelX, int a_RelZ) const;
+
+ /** Returns true if it is raining or storming at the specified location,
+ and the rain reaches (the bottom of) the specified block position. */
+ bool IsWeatherWetAt(Vector3i a_Position) const;
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index f06dd057f..c5798260b 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -337,6 +337,63 @@ bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
+bool cChunkMap::IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const
+{
+ int ChunkX, ChunkZ, BlockY = 0;
+ cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
+
+ cCSLock Lock(m_CSChunks);
+ const auto Chunk = FindChunk(ChunkX, ChunkZ);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ return m_World->IsWeatherSunny();
+ }
+
+ return Chunk->IsWeatherSunnyAt(a_BlockX, a_BlockZ);
+}
+
+
+
+
+
+bool cChunkMap::IsWeatherWetAt(int a_BlockX, int a_BlockZ) const
+{
+ int ChunkX, ChunkZ, BlockY = 0;
+ cChunkDef::AbsoluteToRelative(a_BlockX, BlockY, a_BlockZ, ChunkX, ChunkZ);
+
+ cCSLock Lock(m_CSChunks);
+ const auto Chunk = FindChunk(ChunkX, ChunkZ);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ return m_World->IsWeatherWet();
+ }
+
+ return Chunk->IsWeatherWetAt(a_BlockX, a_BlockZ);
+}
+
+
+
+
+
+bool cChunkMap::IsWeatherWetAt(const Vector3i a_Position) const
+{
+ const auto ChunkPosition = cChunkDef::BlockToChunk(a_Position);
+ const auto Position = cChunkDef::AbsoluteToRelative(a_Position, ChunkPosition);
+
+ cCSLock Lock(m_CSChunks);
+ const auto Chunk = FindChunk(ChunkPosition.m_ChunkX, ChunkPosition.m_ChunkZ);
+ if ((Chunk == nullptr) || !Chunk->IsValid())
+ {
+ return m_World->IsWeatherWet();
+ }
+
+ return Chunk->IsWeatherWetAt(Position);
+}
+
+
+
+
+
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
{
cCSLock Lock(m_CSChunks);
@@ -647,10 +704,7 @@ EMCSBiome cChunkMap::GetBiomeAt(int a_BlockX, int a_BlockZ) const
{
return Chunk->GetBiomeAt(X, Z);
}
- else
- {
- return m_World->GetGenerator().GetBiomeAt(a_BlockX, a_BlockZ);
- }
+ return EMCSBiome::biInvalidBiome;
}
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index e40a5d59d..de1f29754 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -5,9 +5,6 @@
#pragma once
-
-#include <functional>
-
#include "ChunkDataCallback.h"
#include "EffectID.h"
#include "FunctionRef.h"
@@ -120,6 +117,10 @@ public:
/** Returns true iff the chunk is in the loader / generator queue. */
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const;
+ bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const;
+ bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) const;
+ bool IsWeatherWetAt(Vector3i a_Position) const;
+
bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const;
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ) const;
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
@@ -143,15 +144,15 @@ public:
Ignored if the chunk is invalid. */
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_BlockMeta);
- void SetBlock (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
- bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
- bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const;
+ void SetBlock (Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+ bool GetBlockTypeMeta (Vector3i a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const;
+ bool GetBlockInfo (Vector3i, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_Meta, NIBBLETYPE & a_SkyLight, NIBBLETYPE & a_BlockLight) const;
/** Special function used for growing trees, replaces only blocks that tree may overwrite */
- void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
+ void ReplaceTreeBlocks(const sSetBlockVector & a_Blocks);
- /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, otherwise uses the world generator to provide the biome value */
- EMCSBiome GetBiomeAt (int a_BlockX, int a_BlockZ) const;
+ /** Returns the biome at the specified coords. Reads the biome from the chunk, if loaded, invalid otherwise. */
+ EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ) const;
/** Sets the biome at the specified coords. Returns true if successful, false if not (chunk not loaded).
Doesn't resend the chunk to clients. */
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index 438117650..f07eab415 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1198,8 +1198,8 @@ void cEntity::TickBurning(cChunk & a_Chunk)
m_TicksLeftBurning = 0;
}
- // Fire is extinguished by rain
- if (GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()))
+ // Fire is extinguished by rain:
+ if (a_Chunk.IsWeatherWetAt(cChunkDef::AbsoluteToRelative(GetPosition().Floor(), a_Chunk.GetPos())))
{
m_TicksLeftBurning = 0;
}
diff --git a/src/Entities/Floater.cpp b/src/Entities/Floater.cpp
index bb326f70b..2738c12d3 100644
--- a/src/Entities/Floater.cpp
+++ b/src/Entities/Floater.cpp
@@ -101,11 +101,16 @@ void cFloater::SpawnOn(cClientHandle & a_Client)
void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
- auto & Random = GetRandomProvider();
-
HandlePhysics(a_Dt, a_Chunk);
- if (IsBlockWater(m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT))
- && (m_World->GetBlockMeta(POSX_TOINT, POSY_TOINT, POSZ_TOINT) == 0))
+
+ PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
+ if (!RelSuccess)
+ {
+ return;
+ }
+
+ auto & Random = GetRandomProvider();
+ if (IsBlockWater(Chunk->GetBlock(Rel)) && (Chunk->GetMeta(Rel) == 0))
{
if (!m_CanPickupItem && (m_AttachedMobID == cEntity::INVALID_ID)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob.
{
@@ -113,7 +118,7 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
m_BitePos = GetPosition();
m_World->BroadcastSoundEffect("entity.bobber.splash", GetPosition(), 1, 1);
- SetPosY(GetPosY() - 1);
+ AddSpeedY(-10);
m_CanPickupItem = true;
m_PickupCountDown = 20;
m_CountDownTime = Random.RandInt(100, 900);
@@ -132,9 +137,9 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
m_CountDownTime--;
- if (m_World->GetHeight(POSX_TOINT, POSZ_TOINT) == POSY_TOINT)
+ if (Chunk->IsWeatherWetAt(Rel))
{
- if (m_World->IsWeatherWet() && Random.RandBool(0.25)) // 25% chance of an extra countdown when being rained on.
+ if (Random.RandBool(0.25)) // 25% chance of an extra countdown when being rained on.
{
m_CountDownTime--;
}
@@ -150,7 +155,10 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
}
// Check water at the top of floater otherwise it floats into the air above the water
- if (IsBlockWater(m_World->GetBlock(POSX_TOINT, FloorC(GetPosY() + GetHeight()), POSZ_TOINT)))
+ if (
+ const auto Above = Rel.addedY(FloorC(GetPosY() + GetHeight()));
+ (Above.y < cChunkDef::Height) && IsBlockWater(m_World->GetBlock(Above))
+ )
{
SetSpeedY(0.7);
}
diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp
index b83cd247d..c04467fd3 100644
--- a/src/MobSpawner.cpp
+++ b/src/MobSpawner.cpp
@@ -74,10 +74,6 @@ eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome)
bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck)
{
- if (a_Chunk == nullptr)
- {
- return false;
- }
if ((a_RelPos.y >= cChunkDef::Height - 1) || (a_RelPos.y <= 0))
{
return false;
@@ -502,9 +498,6 @@ cMonster * cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, EMCS
m_NewPack = false;
}
- // Make sure we are looking at the right chunk to spawn in
- a_Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(a_RelPos);
-
if ((m_AllowedTypes.find(m_MobType) != m_AllowedTypes.end()) && CanSpawnHere(a_Chunk, a_RelPos, m_MobType, a_Biome))
{
auto NewMob = cMonster::NewMonsterFromType(m_MobType);
diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp
index 02450487b..a107762c6 100644
--- a/src/Mobs/Enderman.cpp
+++ b/src/Mobs/Enderman.cpp
@@ -1,6 +1,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+#include "Chunk.h"
#include "Enderman.h"
#include "../Entities/Player.h"
#include "../LineBlockTracer.h"
@@ -148,11 +149,14 @@ void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
return;
}
- // Take damage when wet
- if (
- cChunkDef::IsValidHeight(POSY_TOINT) &&
- (GetWorld()->IsWeatherWetAtXYZ(GetPosition().Floor()) || IsInWater())
- )
+ PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
+ if (!RelSuccess)
+ {
+ return;
+ }
+
+ // Take damage when wet:
+ if (IsInWater() || Chunk->IsWeatherWetAt(Rel))
{
EventLosePlayer();
TakeDamage(dtEnvironment, nullptr, 1, 0);
diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp
index 7e8e7eba3..52b3f8454 100644
--- a/src/Mobs/Monster.cpp
+++ b/src/Mobs/Monster.cpp
@@ -1667,10 +1667,10 @@ bool cMonster::WouldBurnAt(Vector3d a_Location, cChunk & a_Chunk)
}
if (
- (Chunk->GetBlock(Rel.x, Rel.y, Rel.z) != E_BLOCK_SOULSAND) && // Not on soulsand
- (GetWorld()->GetTimeOfDay() < 12000 + 1000) && // Daytime
- GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) && // Not raining
- !IsInWater() // Isn't swimming
+ (Chunk->GetBlock(Rel) != E_BLOCK_SOULSAND) && // Not on soulsand
+ (GetWorld()->GetTimeOfDay() < 12000 + 1000) && // Daytime
+ Chunk->IsWeatherSunnyAt(Rel.x, Rel.z) && // Not raining
+ !IsInWater() // Isn't swimming
)
{
int MobHeight = CeilC(a_Location.y + GetHeight()) - 1; // The block Y coord of the mob's head
diff --git a/src/Mobs/SnowGolem.cpp b/src/Mobs/SnowGolem.cpp
index 93c29cafb..c6db0cbd1 100644
--- a/src/Mobs/SnowGolem.cpp
+++ b/src/Mobs/SnowGolem.cpp
@@ -1,6 +1,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+#include "Chunk.h"
#include "SnowGolem.h"
#include "../BlockInfo.h"
#include "../World.h"
@@ -36,17 +37,22 @@ void cSnowGolem::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
// The base class tick destroyed us
return;
}
- if (IsBiomeNoDownfall(m_World->GetBiomeAt(POSX_TOINT, POSZ_TOINT)))
+
+ PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
+ if (!RelSuccess)
+ {
+ return;
+ }
+
+ if (IsBiomeNoDownfall(Chunk->GetBiomeAt(Rel.x, Rel.z)))
{
TakeDamage(dtEnvironment, nullptr, GetRawDamageAgainst(*this), GetKnockbackAmountAgainst(*this));
}
- else
+ else if (const auto Below = Rel.addedY(-1); Below.y >= 0)
{
- BLOCKTYPE BlockBelow = m_World->GetBlock(POSX_TOINT, POSY_TOINT - 1, POSZ_TOINT);
- BLOCKTYPE Block = m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT);
- if ((Block == E_BLOCK_AIR) && cBlockInfo::IsSolid(BlockBelow))
+ if ((Chunk->GetBlock(Rel) == E_BLOCK_AIR) && cBlockInfo::IsSolid(Chunk->GetBlock(Below)))
{
- m_World->SetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT, E_BLOCK_SNOW, 0);
+ Chunk->SetBlock(Rel, E_BLOCK_SNOW, 0);
}
}
}
diff --git a/src/Simulator/FireSimulator.cpp b/src/Simulator/FireSimulator.cpp
index 30fe88acd..67a00f241 100644
--- a/src/Simulator/FireSimulator.cpp
+++ b/src/Simulator/FireSimulator.cpp
@@ -87,7 +87,6 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
for (cCoordWithIntList::iterator itr = Data.begin(); itr != Data.end();)
{
Vector3i relPos(itr->x, itr->y, itr->z);
- auto absPos = a_Chunk->RelativeToAbsolute(relPos);
auto blockType = a_Chunk->GetBlock(relPos);
if (!IsAllowedBlock(blockType))
@@ -101,12 +100,16 @@ void cFireSimulator::SimulateChunk(std::chrono::milliseconds a_Dt, int a_ChunkX,
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)
+ auto Raining = std::any_of(std::begin(gCrossCoords), std::end(gCrossCoords), [a_Chunk, relPos](Vector3i cc)
+ {
+ auto Adjusted = relPos + cc;
+ const auto Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(Adjusted);
+ if ((Chunk != nullptr) && Chunk->IsValid())
{
- return (m_World.IsWeatherWetAtXYZ(absPos + cc));
+ return Chunk->IsWeatherWetAt(Adjusted);
}
- );
+ return false;
+ });
// Randomly burn out the fire if it is raining:
if (!BurnsForever && Raining && GetRandomProvider().RandBool(CHANCE_BASE_RAIN_EXTINGUISH + (BlockMeta * CHANCE_AGE_M_RAIN_EXTINGUISH)))
diff --git a/src/World.cpp b/src/World.cpp
index 46d08ab44..6b224b634 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -548,28 +548,27 @@ void cWorld::ChangeWeather(void)
-bool cWorld::IsWeatherWetAtXYZ(Vector3i a_Pos)
+bool cWorld::IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const
{
- if ((a_Pos.y < 0) || !IsWeatherWetAt(a_Pos.x, a_Pos.z))
- {
- return false;
- }
+ return m_ChunkMap.IsWeatherSunnyAt(a_BlockX, a_BlockZ);
+}
- 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;
+
+
+bool cWorld::IsWeatherWetAt(int a_BlockX, int a_BlockZ)
+{
+ return m_ChunkMap.IsWeatherWetAt(a_BlockX, a_BlockZ);
+}
+
+
+
+
+
+bool cWorld::IsWeatherWetAtXYZ(const Vector3i a_Position)
+{
+ return m_ChunkMap.IsWeatherWetAt(a_Position);
}
diff --git a/src/World.h b/src/World.h
index b0ffc2b07..ba4e5ee58 100644
--- a/src/World.h
+++ b/src/World.h
@@ -999,10 +999,7 @@ public:
bool IsWeatherSunny(void) const { return (m_Weather == wSunny); }
/** Returns true if it is sunny at the specified location. This takes into account biomes. */
- bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ)
- {
- return (IsWeatherSunny() || IsBiomeNoDownfall(GetBiomeAt(a_BlockX, a_BlockZ)));
- }
+ bool IsWeatherSunnyAt(int a_BlockX, int a_BlockZ) const;
/** Returns true if the current weather is rainy. */
bool IsWeatherRain(void) const { return (m_Weather == wRain); }
@@ -1027,15 +1024,11 @@ public:
/** 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
- {
- auto Biome = GetBiomeAt(a_BlockX, a_BlockZ);
- return (IsWeatherWet() && !IsBiomeNoDownfall(Biome) && !IsBiomeCold(Biome));
- }
+ virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) override;
/** Returns true if it is raining or storming at the specified location,
and the rain reaches (the bottom of) the specified block position. */
- virtual bool IsWeatherWetAtXYZ(Vector3i a_Pos) override;
+ virtual bool IsWeatherWetAtXYZ(Vector3i a_Position) override;
/** Returns the seed of the world. */
int GetSeed(void) { return m_Generator.GetSeed(); }