summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
authorTiger Wang <ziwei.tiger@outlook.com>2020-04-22 00:12:55 +0200
committerTiger Wang <ziwei.tiger@outlook.com>2020-07-06 21:56:05 +0200
commite205d4109beb413b5db932e6035280789b653721 (patch)
tree844aadb47e76cfbc410e2577cd2c8d940bec33f9 /src/Blocks
parentUpdate mbedtls to 2.23.0 (diff)
downloadcuberite-e205d4109beb413b5db932e6035280789b653721.tar
cuberite-e205d4109beb413b5db932e6035280789b653721.tar.gz
cuberite-e205d4109beb413b5db932e6035280789b653721.tar.bz2
cuberite-e205d4109beb413b5db932e6035280789b653721.tar.lz
cuberite-e205d4109beb413b5db932e6035280789b653721.tar.xz
cuberite-e205d4109beb413b5db932e6035280789b653721.tar.zst
cuberite-e205d4109beb413b5db932e6035280789b653721.zip
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockGrass.h152
1 files changed, 89 insertions, 63 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;
}
} ;
-
-
-
-