Sapling Growth Update
* Growth has been slowed down * Saplings do not grow if they do not have enough space to grow * Saplings do not grow unless the light level is 9 or above * Dark Oak doesn't grow unless it is in a 2x2 Jungle Trees now will grow into a large tree when 2x2 saplings are used.
This commit is contained in:
parent
f6f27a139e
commit
d017fe5e39
@ -3,6 +3,7 @@
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../World.h"
|
||||
#include "../FastRandom.h"
|
||||
|
||||
|
||||
|
||||
@ -34,17 +35,144 @@ public:
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
|
||||
NIBBLETYPE Light = std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY, a_RelZ)));
|
||||
|
||||
if ((Meta & 0x08) != 0)
|
||||
// Only grow if we have the right amount of light
|
||||
if (Light > 8)
|
||||
{
|
||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ);
|
||||
cFastRandom random;
|
||||
// Only grow if we are in the right growth stage and have the right amount of space around them.
|
||||
if (((Meta & 0x08) != 0) && (random.NextInt(99) < 45) && CanGrowAt(a_Chunk, a_RelX, a_RelY, a_RelZ, Meta))
|
||||
{
|
||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ);
|
||||
}
|
||||
// Only move to the next growth stage if we haven't gone there yet
|
||||
else if (((Meta & 0x08) == 0) && (random.NextInt(99) < 45))
|
||||
{
|
||||
a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
bool CanGrowAt(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
a_Meta = a_Meta & 0x07;
|
||||
int CheckHeight = 0;
|
||||
bool LargeTree = false;
|
||||
|
||||
// Get the height to check against
|
||||
switch (a_Meta)
|
||||
{
|
||||
a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
|
||||
case E_META_SAPLING_APPLE:
|
||||
{
|
||||
CheckHeight = 5;
|
||||
break;
|
||||
}
|
||||
case E_META_SAPLING_CONIFER:
|
||||
{
|
||||
CheckHeight = 7;
|
||||
if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
|
||||
{
|
||||
CheckHeight = 16;
|
||||
LargeTree = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case E_META_SAPLING_BIRCH:
|
||||
{
|
||||
CheckHeight = 6;
|
||||
break;
|
||||
}
|
||||
case E_META_SAPLING_JUNGLE:
|
||||
{
|
||||
CheckHeight = 7;
|
||||
if (IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
|
||||
{
|
||||
CheckHeight = 13;
|
||||
LargeTree = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Dark Oaks only grow in a 2x2 area
|
||||
case E_META_SAPLING_DARK_OAK:
|
||||
{
|
||||
if (!IsLargeTree(a_Chunk, a_RelX, a_RelY, a_RelZ, a_Meta))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CheckHeight = 7;
|
||||
LargeTree = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We should always get a valid CheckHeight
|
||||
ASSERT(CheckHeight != 0);
|
||||
|
||||
// Don't grow a tree if we don't have enough space left above it in the chunk
|
||||
if ((a_RelY + CheckHeight) > cChunkDef::Height)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool CanGrow = true;
|
||||
|
||||
// Validate the neighbor blocks. They cannot be solid.
|
||||
BLOCKTYPE check = E_BLOCK_AIR;
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX - 1, a_RelY, a_RelZ, check);
|
||||
CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY, a_RelZ, check);
|
||||
CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ - 1, check);
|
||||
CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ + 1, check);
|
||||
CanGrow = CanGrow && cBlockInfo::IsTransparent(check);
|
||||
|
||||
|
||||
|
||||
while (CheckHeight && CanGrow)
|
||||
{
|
||||
check = a_Chunk.GetBlock(a_RelX, a_RelY + CheckHeight, a_RelZ);
|
||||
CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
|
||||
|
||||
// We have to check above the neighboring saplings as well
|
||||
if (LargeTree)
|
||||
{
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ, check);
|
||||
CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY + CheckHeight, a_RelZ + 1, check);
|
||||
CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
|
||||
|
||||
a_Chunk.UnboundedRelGetBlockType(a_RelX + 1, a_RelY + CheckHeight, a_RelZ + 1, check);
|
||||
CanGrow = CanGrow && ((check == E_BLOCK_AIR) || (check == E_BLOCK_LEAVES));
|
||||
}
|
||||
|
||||
--CheckHeight;
|
||||
}
|
||||
|
||||
return CanGrow;
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsLargeTree(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
|
||||
{
|
||||
BLOCKTYPE type;
|
||||
NIBBLETYPE meta;
|
||||
bool LargeTree = true;
|
||||
a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ, type, meta);
|
||||
LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
|
||||
a_Chunk.UnboundedRelGetBlock(a_RelX + 1, a_RelY, a_RelZ + 1, type, meta);
|
||||
LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
|
||||
a_Chunk.UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ + 1, type, meta);
|
||||
LargeTree = LargeTree && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
|
||||
return LargeTree;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Globals.h"
|
||||
#include "Trees.h"
|
||||
#include "../BlockID.h"
|
||||
#include "../World.h"
|
||||
|
||||
|
||||
|
||||
@ -200,7 +201,8 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
|
||||
}
|
||||
else
|
||||
{
|
||||
GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
|
||||
bool IsLarge = a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) < 0x60000000;
|
||||
GetJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks, IsLarge);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -920,9 +922,9 @@ void GetAppleBushImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
|
||||
|
||||
|
||||
|
||||
void GetJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
|
||||
void GetJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large)
|
||||
{
|
||||
if (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY + 32 * a_Seq, a_BlockZ) < 0x60000000)
|
||||
if (!a_Large)
|
||||
{
|
||||
GetSmallJungleTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
|
||||
}
|
||||
@ -1041,3 +1043,89 @@ void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
|
||||
|
||||
|
||||
|
||||
bool GetLargeTreeAdjustment(cWorld & a_World, int & a_X, int & a_Y, int & a_Z, NIBBLETYPE a_Meta)
|
||||
{
|
||||
bool IsLarge = true;
|
||||
a_Meta = a_Meta & 0x07;
|
||||
|
||||
// Check to see if we are the northwest corner
|
||||
for (int x = 0; x < 2; ++x)
|
||||
{
|
||||
for (int z = 0; z < 2; ++z)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLarge)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IsLarge = true;
|
||||
// Check to see if we are the southwest corner
|
||||
for (int x = 0; x < 2; ++x)
|
||||
{
|
||||
for (int z = 0; z > -2; --z)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLarge)
|
||||
{
|
||||
--a_Z;
|
||||
return true;
|
||||
}
|
||||
|
||||
IsLarge = true;
|
||||
// Check to see if we are the southeast corner
|
||||
for (int x = 0; x > -2; --x)
|
||||
{
|
||||
for (int z = 0; z > -2; --z)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLarge)
|
||||
{
|
||||
--a_Z;
|
||||
--a_X;
|
||||
return true;
|
||||
}
|
||||
|
||||
IsLarge = true;
|
||||
// Check to see if we are the northeast corner
|
||||
for (int x = 0; x > -2; --x)
|
||||
{
|
||||
for (int z = 0; z < 2; ++z)
|
||||
{
|
||||
NIBBLETYPE meta;
|
||||
BLOCKTYPE type;
|
||||
a_World.GetBlockTypeMeta(a_X + x, a_Y, a_Z + z, type, meta);
|
||||
IsLarge = IsLarge && (type == E_BLOCK_SAPLING) && ((a_Meta & meta) == a_Meta);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsLarge)
|
||||
{
|
||||
--a_X;
|
||||
}
|
||||
|
||||
return IsLarge;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -20,6 +20,8 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is
|
||||
#include "../ChunkDef.h"
|
||||
#include "../Noise/Noise.h"
|
||||
|
||||
class cWorld;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -96,7 +98,7 @@ void GetSwampTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
|
||||
void GetAppleBushImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
|
||||
|
||||
/// Generates an image of a random jungle tree
|
||||
void GetJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
|
||||
void GetJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks, bool a_Large);
|
||||
|
||||
/// Generates an image of a large jungle tree (2x2 trunk)
|
||||
void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
|
||||
@ -104,7 +106,7 @@ void GetLargeJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise &
|
||||
/// Generates an image of a small jungle tree (1x1 trunk)
|
||||
void GetSmallJungleTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks);
|
||||
|
||||
|
||||
bool GetLargeTreeAdjustment(cWorld & a_World, int & a_X, int & a_Y, int & a_Z, NIBBLETYPE a_Meta);
|
||||
|
||||
|
||||
|
||||
|
@ -1393,9 +1393,23 @@ void cWorld::GrowTreeFromSapling(int a_X, int a_Y, int a_Z, NIBBLETYPE a_Sapling
|
||||
case E_META_SAPLING_APPLE: GetAppleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_BIRCH: GetBirchTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_CONIFER: GetConiferTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_JUNGLE: GetJungleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_ACACIA: GetAcaciaTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_DARK_OAK: GetDarkoakTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other); break;
|
||||
case E_META_SAPLING_JUNGLE:
|
||||
{
|
||||
bool IsLarge = GetLargeTreeAdjustment(*this, a_X, a_Y, a_Z, a_SaplingMeta);
|
||||
GetJungleTreeImage (a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other, IsLarge);
|
||||
break;
|
||||
}
|
||||
case E_META_SAPLING_DARK_OAK:
|
||||
{
|
||||
if (!GetLargeTreeAdjustment(*this, a_X, a_Y, a_Z, a_SaplingMeta))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetDarkoakTreeImage(a_X, a_Y, a_Z, Noise, WorldAge, Logs, Other);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Other.insert(Other.begin(), Logs.begin(), Logs.end());
|
||||
Logs.clear();
|
||||
|
Loading…
Reference in New Issue
Block a user