Makes tall grass and large flowers bonemealable
Adds the bonemeal particle effect to some more places
This commit is contained in:
parent
706257f8fb
commit
f1192c6860
@ -1105,6 +1105,37 @@ int cChunk::GrowCactus(int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunk::GrowTallGrass(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
|
{
|
||||||
|
if (a_RelY > (cChunkDef::Height - 2))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BLOCKTYPE BlockType;
|
||||||
|
NIBBLETYPE BlockMeta;
|
||||||
|
if (!UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (BlockType != E_BLOCK_TALL_GRASS)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
NIBBLETYPE LargeFlowerMeta;
|
||||||
|
switch (BlockMeta)
|
||||||
|
{
|
||||||
|
case E_META_TALL_GRASS_GRASS: LargeFlowerMeta = E_META_BIG_FLOWER_DOUBLE_TALL_GRASS; break;
|
||||||
|
case E_META_TALL_GRASS_FERN: LargeFlowerMeta = E_META_BIG_FLOWER_LARGE_FERN; break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return UnboundedRelFastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_BIG_FLOWER, LargeFlowerMeta) &&
|
||||||
|
UnboundedRelFastSetBlock(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_BIG_FLOWER, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunk::UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
|
bool cChunk::UnboundedRelGetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta) const
|
||||||
{
|
{
|
||||||
if (!cChunkDef::IsValidHeight(a_RelY))
|
if (!cChunkDef::IsValidHeight(a_RelY))
|
||||||
|
@ -586,6 +586,9 @@ private:
|
|||||||
/** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking); returns the amount of blocks the cactus grew inside this call */
|
/** Grows cactus by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking); returns the amount of blocks the cactus grew inside this call */
|
||||||
int GrowCactus (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
|
int GrowCactus (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks);
|
||||||
|
|
||||||
|
/** Grows a tall grass present at the block specified to a two tall grass; returns true if the grass grew */
|
||||||
|
bool GrowTallGrass (int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
|
||||||
/** Grows a melon or a pumpkin next to the block specified (assumed to be the stem); returns true if the pumpkin or melon sucessfully grew */
|
/** Grows a melon or a pumpkin next to the block specified (assumed to be the stem); returns true if the pumpkin or melon sucessfully grew */
|
||||||
bool GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
|
bool GrowMelonPumpkin(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, MTRand & a_Random);
|
||||||
|
|
||||||
|
@ -2651,6 +2651,24 @@ int cChunkMap::GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkMap::GrowTallGrass(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
|
{
|
||||||
|
int ChunkX, ChunkZ;
|
||||||
|
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
|
||||||
|
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoLoad(ChunkX, ChunkZ);
|
||||||
|
if (Chunk != nullptr)
|
||||||
|
{
|
||||||
|
return Chunk->GrowTallGrass(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
|
void cChunkMap::SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
int ChunkX, ChunkZ;
|
int ChunkX, ChunkZ;
|
||||||
|
@ -369,6 +369,9 @@ public:
|
|||||||
/** Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config; returns the amount of blocks the cactus grew inside this call */
|
/** Grows a cactus present at the block specified by the amount of blocks specified, up to the max height specified in the config; returns the amount of blocks the cactus grew inside this call */
|
||||||
int GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
|
int GrowCactus(int a_BlockX, int a_BlockY, int a_BlockZ, int a_NumBlocksToGrow);
|
||||||
|
|
||||||
|
/** Grows a tall grass present at the block specified to a two tall grass; returns true if the grass grew */
|
||||||
|
bool GrowTallGrass(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
|
||||||
/** Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call */
|
/** Sets the blockticking to start at the specified block. Only one blocktick per chunk may be set, second call overwrites the first call */
|
||||||
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ);
|
void SetNextBlockTick(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
|
||||||
|
@ -187,6 +187,8 @@ cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AStrin
|
|||||||
m_IsPumpkinBonemealable(true),
|
m_IsPumpkinBonemealable(true),
|
||||||
m_IsSaplingBonemealable(true),
|
m_IsSaplingBonemealable(true),
|
||||||
m_IsSugarcaneBonemealable(false),
|
m_IsSugarcaneBonemealable(false),
|
||||||
|
m_IsBigFlowerBonemealable(true),
|
||||||
|
m_IsTallGrassBonemealable(true),
|
||||||
m_bCommandBlocksEnabled(true),
|
m_bCommandBlocksEnabled(true),
|
||||||
m_bUseChatPrefixes(false),
|
m_bUseChatPrefixes(false),
|
||||||
m_TNTShrapnelLevel(slNone),
|
m_TNTShrapnelLevel(slNone),
|
||||||
@ -471,6 +473,8 @@ void cWorld::Start(void)
|
|||||||
m_IsPumpkinBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinBonemealable", false);
|
m_IsPumpkinBonemealable = IniFile.GetValueSetB("Plants", "IsPumpkinBonemealable", false);
|
||||||
m_IsSaplingBonemealable = IniFile.GetValueSetB("Plants", "IsSaplingBonemealable", true);
|
m_IsSaplingBonemealable = IniFile.GetValueSetB("Plants", "IsSaplingBonemealable", true);
|
||||||
m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false);
|
m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false);
|
||||||
|
m_IsBigFlowerBonemealable = IniFile.GetValueSetB("Plants", "IsBigFlowerBonemealable", true);
|
||||||
|
m_IsTallGrassBonemealable = IniFile.GetValueSetB("Plants", "IsTallGrassBonemealable", true);
|
||||||
m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true);
|
m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true);
|
||||||
m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
|
m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
|
||||||
int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", static_cast<int>(slAll));
|
int TNTShrapnelLevel = IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", static_cast<int>(slAll));
|
||||||
@ -1778,8 +1782,6 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
|
BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
|
||||||
}
|
}
|
||||||
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
||||||
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1787,8 +1789,13 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType);
|
if (!GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_POTATOES:
|
case E_BLOCK_POTATOES:
|
||||||
@ -1830,8 +1837,6 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
|
BlockMeta = std::min(BlockMeta, static_cast<NIBBLETYPE>(7));
|
||||||
}
|
}
|
||||||
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
||||||
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1839,8 +1844,13 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType);
|
if (!GrowMelonPumpkin(a_BlockX, a_BlockY, a_BlockZ, BlockType))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_SAPLING:
|
case E_BLOCK_SAPLING:
|
||||||
@ -1865,15 +1875,13 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
}
|
}
|
||||||
|
|
||||||
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, static_cast<NIBBLETYPE>(GrowState << 3 | TypeMeta));
|
FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, static_cast<NIBBLETYPE>(GrowState << 3 | TypeMeta));
|
||||||
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
|
||||||
}
|
}
|
||||||
else if (random.NextInt(99) < 45)
|
else if (random.NextInt(99) < 45)
|
||||||
{
|
{
|
||||||
|
|
||||||
GrowTreeFromSapling(a_BlockX, a_BlockY, a_BlockZ, BlockMeta);
|
GrowTreeFromSapling(a_BlockX, a_BlockY, a_BlockZ, BlockMeta);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_GRASS:
|
case E_BLOCK_GRASS:
|
||||||
@ -1923,7 +1931,12 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_ChunkMap->GrowSugarcane(a_BlockX, a_BlockY, a_BlockZ, 1) != 0;
|
if (m_ChunkMap->GrowSugarcane(a_BlockX, a_BlockY, a_BlockZ, 1) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case E_BLOCK_CACTUS:
|
case E_BLOCK_CACTUS:
|
||||||
@ -1932,8 +1945,58 @@ bool cWorld::GrowRipePlant(int a_BlockX, int a_BlockY, int a_BlockZ, bool a_IsBy
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_ChunkMap->GrowCactus(a_BlockX, a_BlockY, a_BlockZ, 1) != 0;
|
if (m_ChunkMap->GrowCactus(a_BlockX, a_BlockY, a_BlockZ, 1) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case E_BLOCK_TALL_GRASS:
|
||||||
|
{
|
||||||
|
if (a_IsByBonemeal && !m_IsTallGrassBonemealable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_ChunkMap->GrowTallGrass(a_BlockX, a_BlockY, a_BlockZ))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case E_BLOCK_BIG_FLOWER:
|
||||||
|
{
|
||||||
|
if (a_IsByBonemeal && !m_IsBigFlowerBonemealable)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (BlockMeta & 8) // the upper flower block does not save the type of the flower
|
||||||
|
{
|
||||||
|
GetBlockTypeMeta(a_BlockX, a_BlockY - 1, a_BlockZ, BlockType, BlockMeta);
|
||||||
|
if (BlockType != E_BLOCK_BIG_FLOWER)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(BlockMeta == E_META_BIG_FLOWER_DOUBLE_TALL_GRASS) ||
|
||||||
|
(BlockMeta == E_META_BIG_FLOWER_LARGE_FERN)
|
||||||
|
) // tall grass and fern do not work
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn flower item
|
||||||
|
BroadcastSoundParticleEffect(EffectID::PARTICLE_HAPPY_VILLAGER, a_BlockX, a_BlockY, a_BlockZ, 0);
|
||||||
|
cItems FlowerItem;
|
||||||
|
FlowerItem.Add(E_BLOCK_BIG_FLOWER, 1, BlockMeta);
|
||||||
|
SpawnItemPickups(FlowerItem, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // switch (BlockType)
|
} // switch (BlockType)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -937,6 +937,8 @@ private:
|
|||||||
bool m_IsPumpkinBonemealable;
|
bool m_IsPumpkinBonemealable;
|
||||||
bool m_IsSaplingBonemealable;
|
bool m_IsSaplingBonemealable;
|
||||||
bool m_IsSugarcaneBonemealable;
|
bool m_IsSugarcaneBonemealable;
|
||||||
|
bool m_IsBigFlowerBonemealable;
|
||||||
|
bool m_IsTallGrassBonemealable;
|
||||||
|
|
||||||
/** Whether command blocks are enabled or not */
|
/** Whether command blocks are enabled or not */
|
||||||
bool m_bCommandBlocksEnabled;
|
bool m_bCommandBlocksEnabled;
|
||||||
|
Loading…
Reference in New Issue
Block a user