1
0

Merge pull request #2346 from SamJBarney/TreeGrowthUpdate

Sapling Growth Update
This commit is contained in:
Julian Laubstein 2015-07-14 16:36:53 +02:00
commit e92335b669
4 changed files with 246 additions and 14 deletions

View File

@ -3,6 +3,7 @@
#include "BlockHandler.h"
#include "../World.h"
#include "../FastRandom.h"
@ -34,18 +35,145 @@ 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)
{
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);
}
else
// 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);
}
}
}
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)
{
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;
}
} ;

View File

@ -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;
}

View File

@ -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);

View File

@ -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();