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 "BlockHandler.h"
|
||||||
#include "../World.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
|
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 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;
|
cFastRandom random;
|
||||||
int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
|
// Only grow if we are in the right growth stage and have the right amount of space around them.
|
||||||
a_Chunk.GetWorld()->GrowTree(BlockX, a_RelY, BlockZ);
|
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 "Globals.h"
|
||||||
#include "Trees.h"
|
#include "Trees.h"
|
||||||
#include "../BlockID.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
|
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;
|
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);
|
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 "../ChunkDef.h"
|
||||||
#include "../Noise/Noise.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);
|
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
|
/// 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)
|
/// 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);
|
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)
|
/// 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);
|
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_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_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_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_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());
|
Other.insert(Other.begin(), Logs.begin(), Logs.end());
|
||||||
Logs.clear();
|
Logs.clear();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user