summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Blocks/BlockGrass.h152
-rw-r--r--src/Protocol/Protocol_1_11.cpp2
-rw-r--r--src/Protocol/Protocol_1_8.cpp2
3 files changed, 91 insertions, 65 deletions
diff --git a/src/Blocks/BlockGrass.h b/src/Blocks/BlockGrass.h
index 51a321b35..8792a51f9 100644
--- a/src/Blocks/BlockGrass.h
+++ b/src/Blocks/BlockGrass.h
@@ -52,72 +52,102 @@ public:
a_Chunk.GetWorld()->QueueLightChunk(a_Chunk.GetPosX(), a_Chunk.GetPosZ());
return;
}
- auto AbovePos = a_RelPos.addedY(1);
- if (cChunkDef::IsValidHeight(AbovePos.y))
- {
- // Grass turns back to dirt when the block Above it is not transparent or water.
- // It does not turn to dirt when a snow layer is Above.
- auto Above = a_Chunk.GetBlock(AbovePos);
- if (
- (Above != E_BLOCK_SNOW) &&
- (!cBlockInfo::IsTransparent(Above) || IsBlockWater(Above)))
- {
- a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
- return;
- }
- // Make sure that there is enough light at the source block to spread
- auto light = std::max(a_Chunk.GetBlockLight(AbovePos), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(AbovePos)));
- if (light < 9)
- {
- return;
- }
+ if (!cBlockGrassHandler::TrySurvive(a_Chunk, a_RelPos))
+ {
+ return;
}
// Grass spreads to adjacent dirt blocks:
- auto & rand = GetRandomProvider();
- for (int i = 0; i < 2; i++) // Pick two blocks to grow to
+ for (unsigned i = 0; i < 2; i++) // Pick two blocks to grow to
{
- int OfsX = rand.RandInt(-1, 1);
- int OfsY = rand.RandInt(-3, 1);
- int OfsZ = rand.RandInt(-1, 1);
-
- BLOCKTYPE DestBlock;
- NIBBLETYPE DestMeta;
- auto Pos = a_RelPos + Vector3i(OfsX, OfsY, OfsZ);
- if (!cChunkDef::IsValidHeight(Pos.y))
- {
- // Y Coord out of range
- continue;
- }
- auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(Pos);
- if (Chunk == nullptr)
- {
- // Unloaded chunk
- continue;
- }
- Chunk->GetBlockTypeMeta(Pos, DestBlock, DestMeta);
- if ((DestBlock != E_BLOCK_DIRT) || (DestMeta != E_META_DIRT_NORMAL))
- {
- // Not a regular dirt block
- continue;
- }
- auto AboveDestPos = Pos.addedY(1);
- auto AboveBlockType = Chunk->GetBlock(AboveDestPos);
- auto Light = std::max(Chunk->GetBlockLight(AboveDestPos), Chunk->GetTimeAlteredLight(Chunk->GetSkyLight(AboveDestPos)));
- if ((Light > 4) &&
- cBlockInfo::IsTransparent(AboveBlockType) &&
- (!IsBlockLava(AboveBlockType)) &&
- (!IsBlockWaterOrIce(AboveBlockType))
- )
+ auto & Random = GetRandomProvider();
+ int OfsX = Random.RandInt(-1, 1);
+ int OfsY = Random.RandInt(-3, 1);
+ int OfsZ = Random.RandInt(-1, 1);
+
+ cBlockGrassHandler::TryThrive(a_Chunk, a_RelPos + Vector3i(OfsX, OfsY, OfsZ));
+ } // for i - repeat twice
+ }
+
+
+
+
+
+ /** Check if conditions are favourable to a grass block at the given position.
+ If they are not, the grass dies and is turned to dirt.
+ Returns whether conditions are so good that the grass can try to spread to neighbours. */
+ static bool TrySurvive(cChunk & a_Chunk, const Vector3i a_RelPos)
+ {
+ const auto AbovePos = a_RelPos.addedY(1);
+ if (!cChunkDef::IsValidHeight(AbovePos.y))
+ {
+ return true;
+ }
+
+ // Grass turns back to dirt when the block Above it is not transparent or water.
+ // It does not turn to dirt when a snow layer is Above.
+ const auto Above = a_Chunk.GetBlock(AbovePos);
+ if (
+ (Above != E_BLOCK_SNOW) &&
+ (!cBlockInfo::IsTransparent(Above) || IsBlockWater(Above)))
+ {
+ a_Chunk.FastSetBlock(a_RelPos, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
+ return false;
+ }
+
+ // Make sure that there is enough light at the source block to spread
+ const auto Light = std::max(a_Chunk.GetBlockLight(AbovePos), a_Chunk.GetSkyLightAltered(AbovePos));
+ return (Light >= 9);
+ }
+
+
+
+
+
+ /** Attempt to spread grass to a block at the given position. */
+ static void TryThrive(cChunk & a_Chunk, Vector3i a_RelPos)
+ {
+ if (!cChunkDef::IsValidHeight(a_RelPos.y))
+ {
+ // Y Coord out of range
+ return;
+ }
+
+ auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(a_RelPos);
+ if (Chunk == nullptr)
+ {
+ // Unloaded chunk
+ return;
+ }
+
+ BLOCKTYPE DestBlock;
+ NIBBLETYPE DestMeta;
+ Chunk->GetBlockTypeMeta(a_RelPos, DestBlock, DestMeta);
+
+ if ((DestBlock != E_BLOCK_DIRT) || (DestMeta != E_META_DIRT_NORMAL))
+ {
+ // Not a regular dirt block
+ return;
+ }
+
+ const auto AbovePos = a_RelPos.addedY(1);
+ const auto Above = Chunk->GetBlock(AbovePos);
+ const auto Light = std::max(Chunk->GetBlockLight(AbovePos), Chunk->GetSkyLightAltered(AbovePos));
+
+ if (
+ (Light > 4) &&
+ cBlockInfo::IsTransparent(Above) &&
+ !IsBlockLava(Above) &&
+ !IsBlockWaterOrIce(Above)
+ )
+ {
+ const auto AbsPos = Chunk->RelativeToAbsolute(a_RelPos);
+ if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), AbsPos.x, AbsPos.y, AbsPos.z, ssGrassSpread))
{
- auto AbsPos = Chunk->RelativeToAbsolute(Pos);
- if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), AbsPos.x, AbsPos.y, AbsPos.z, ssGrassSpread))
- {
- Chunk->FastSetBlock(Pos, E_BLOCK_GRASS, 0);
- }
+ Chunk->FastSetBlock(a_RelPos, E_BLOCK_GRASS, 0);
}
- } // for i - repeat twice
+ }
}
@@ -130,7 +160,3 @@ public:
return 1;
}
} ;
-
-
-
-
diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp
index e8381c70b..204371e90 100644
--- a/src/Protocol/Protocol_1_11.cpp
+++ b/src/Protocol/Protocol_1_11.cpp
@@ -394,8 +394,8 @@ void cProtocol_1_11_0::SendSpawnMob(const cMonster & a_Mob)
Pkt.WriteBEDouble(LastSentPos.x);
Pkt.WriteBEDouble(LastSentPos.y);
Pkt.WriteBEDouble(LastSentPos.z);
+ Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used
Pkt.WriteByteAngle(a_Mob.GetPitch());
- Pkt.WriteByteAngle(a_Mob.GetHeadYaw());
Pkt.WriteByteAngle(a_Mob.GetYaw());
Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedX() * 400));
Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedY() * 400));
diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp
index a9fa8f23a..b5d78e457 100644
--- a/src/Protocol/Protocol_1_8.cpp
+++ b/src/Protocol/Protocol_1_8.cpp
@@ -1409,8 +1409,8 @@ void cProtocol_1_8_0::SendSpawnMob(const cMonster & a_Mob)
Pkt.WriteFPInt(LastSentPos.x);
Pkt.WriteFPInt(LastSentPos.y);
Pkt.WriteFPInt(LastSentPos.z);
+ Pkt.WriteByteAngle(a_Mob.GetHeadYaw()); // Doesn't seem to be used
Pkt.WriteByteAngle(a_Mob.GetPitch());
- Pkt.WriteByteAngle(a_Mob.GetHeadYaw());
Pkt.WriteByteAngle(a_Mob.GetYaw());
Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedX() * 400));
Pkt.WriteBEInt16(static_cast<Int16>(a_Mob.GetSpeedY() * 400));