summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
authorSamuel Barney <samjbarney@gmail.com>2015-08-19 19:05:30 +0200
committerSamuel Barney <samjbarney@gmail.com>2015-08-19 19:05:30 +0200
commitb5ed23d2a6696586b70b11a1bed51f4565079e5d (patch)
treed4c4ebe5a88eaeba8ce9d53122c9eb92e297870c /src/Blocks
parentMerge pull request #2439 from cuberite/AppveyorYml (diff)
parent* Logic for handling plant growth has been centralized into cBlockPlant, and all growable plants now inherit from it. (diff)
downloadcuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar.gz
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar.bz2
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar.lz
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar.xz
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.tar.zst
cuberite-b5ed23d2a6696586b70b11a1bed51f4565079e5d.zip
Diffstat (limited to '')
-rw-r--r--src/Blocks/BlockCactus.h25
-rw-r--r--src/Blocks/BlockCrops.h18
-rw-r--r--src/Blocks/BlockFarmland.h11
-rw-r--r--src/Blocks/BlockFluid.h16
-rw-r--r--src/Blocks/BlockHandler.cpp2
-rw-r--r--src/Blocks/BlockHandler.h3
-rw-r--r--src/Blocks/BlockNetherWart.h9
-rw-r--r--src/Blocks/BlockNetherrack.h12
-rw-r--r--src/Blocks/BlockPlant.h132
-rw-r--r--src/Blocks/BlockStems.h33
-rw-r--r--src/Blocks/BlockSugarcane.h25
11 files changed, 256 insertions, 30 deletions
diff --git a/src/Blocks/BlockCactus.h b/src/Blocks/BlockCactus.h
index cb6cecc7b..29e86d085 100644
--- a/src/Blocks/BlockCactus.h
+++ b/src/Blocks/BlockCactus.h
@@ -1,18 +1,19 @@
#pragma once
-#include "BlockHandler.h"
+#include "BlockPlant.h"
class cBlockCactusHandler :
- public cBlockHandler
+ public cBlockPlant
{
+ typedef cBlockPlant Super;
public:
cBlockCactusHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : Super(a_BlockType, false)
{
}
@@ -64,7 +65,10 @@ 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
{
- a_Chunk.GetWorld()->GrowCactus(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
+ if (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth)
+ {
+ a_Chunk.GetWorld()->GrowCactus(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
+ }
}
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
@@ -72,6 +76,19 @@ public:
UNUSED(a_Meta);
return 7;
}
+
+protected:
+
+ virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
+ {
+ auto Action = paStay;
+ if (((a_RelY + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_AIR))
+ {
+ Action = Super::CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
+ }
+
+ return Action;
+ }
} ;
diff --git a/src/Blocks/BlockCrops.h b/src/Blocks/BlockCrops.h
index c54625561..9014f7046 100644
--- a/src/Blocks/BlockCrops.h
+++ b/src/Blocks/BlockCrops.h
@@ -1,7 +1,7 @@
#pragma once
-#include "BlockHandler.h"
+#include "BlockPlant.h"
#include "../FastRandom.h"
@@ -10,11 +10,12 @@
/** Common class that takes care of carrots, potatoes and wheat */
class cBlockCropsHandler :
- public cBlockHandler
+ public cBlockPlant
{
+ typedef cBlockPlant Super;
public:
cBlockCropsHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : Super(a_BlockType, true)
{
}
@@ -82,12 +83,17 @@ public:
{
Light = SkyLight;
}
-
- if ((Meta < 7) && (Light > 8))
+
+ // Check to see if the plant can grow
+ auto Action = CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
+
+ // If there is still room to grow and the plant can grow, then grow.
+ // Otherwise if the plant needs to die, then dig it up
+ if ((Meta < 7) && (Action == paGrowth))
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, ++Meta);
}
- else if (Light < 9)
+ else if (Action == paDeath)
{
a_Chunk.GetWorld()->DigBlock(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width);
}
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index 886823ed6..e6c7f16f6 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -127,6 +127,17 @@ public:
return false;
}
+
+ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override
+ {
+ return (
+ (a_Plant == E_BLOCK_CROPS) ||
+ (a_Plant == E_BLOCK_CARROTS) ||
+ (a_Plant == E_BLOCK_POTATOES) ||
+ (a_Plant == E_BLOCK_MELON_STEM) ||
+ (a_Plant == E_BLOCK_PUMPKIN_STEM)
+ );
+ }
} ;
diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h
index 56a2ad3c2..2d9adbab5 100644
--- a/src/Blocks/BlockFluid.h
+++ b/src/Blocks/BlockFluid.h
@@ -57,6 +57,17 @@ public:
ASSERT(!"Unhandled blocktype in fluid/water handler!");
return 0;
}
+
+ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override
+ {
+ return (
+ (a_Plant == E_BLOCK_CROPS) ||
+ (a_Plant == E_BLOCK_CARROTS) ||
+ (a_Plant == E_BLOCK_POTATOES) ||
+ (a_Plant == E_BLOCK_MELON_STEM) ||
+ (a_Plant == E_BLOCK_PUMPKIN_STEM)
+ );
+ }
} ;
@@ -144,6 +155,11 @@ public:
UNUSED(a_Meta);
return 4;
}
+
+ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override
+ {
+ return false;
+ }
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index ae5274d02..dab99e53d 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -49,6 +49,7 @@
#include "BlockMobSpawner.h"
#include "BlockMushroom.h"
#include "BlockMycelium.h"
+#include "BlockNetherrack.h"
#include "BlockNetherWart.h"
#include "BlockOre.h"
#include "BlockPiston.h"
@@ -263,6 +264,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
+ case E_BLOCK_NETHERRACK: return new cBlockNetherrack (a_BlockType);
case E_BLOCK_NETHER_QUARTZ_ORE: return new cBlockOreHandler (a_BlockType);
case E_BLOCK_NEW_LEAVES: return new cBlockLeavesHandler (a_BlockType);
case E_BLOCK_NEW_LOG: return new cBlockSidewaysHandler (a_BlockType);
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index c2a9e1769..0159230a2 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -88,6 +88,9 @@ public:
/** Checks if the block can stay at the specified relative coords in the chunk */
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
+
+ /** Checks whether the block has an effect on growing the plant */
+ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) { return false; }
/** Checks if the block can be placed at this point.
Default: CanBeAt(...)
diff --git a/src/Blocks/BlockNetherWart.h b/src/Blocks/BlockNetherWart.h
index 6a76e0828..b10150a92 100644
--- a/src/Blocks/BlockNetherWart.h
+++ b/src/Blocks/BlockNetherWart.h
@@ -1,7 +1,7 @@
#pragma once
-#include "BlockHandler.h"
+#include "BlockPlant.h"
#include "../FastRandom.h"
#include "../World.h"
@@ -10,11 +10,12 @@
class cBlockNetherWartHandler :
- public cBlockHandler
+ public cBlockPlant
{
+ typedef cBlockPlant Super;
public:
cBlockNetherWartHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : Super(a_BlockType, false)
{
}
@@ -36,7 +37,7 @@ 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);
- if (Meta < 7)
+ if ((Meta < 7) && (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth))
{
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_NETHER_WART, ++Meta);
}
diff --git a/src/Blocks/BlockNetherrack.h b/src/Blocks/BlockNetherrack.h
new file mode 100644
index 000000000..3ccd811f3
--- /dev/null
+++ b/src/Blocks/BlockNetherrack.h
@@ -0,0 +1,12 @@
+#pragma once
+
+
+#include "BlockHandler.h"
+
+class cBlockNetherrack : public cBlockHandler
+{
+public:
+ cBlockNetherrack(BLOCKTYPE a_Type) : cBlockHandler(a_Type){}
+
+ virtual bool CanSustainPlant(BLOCKTYPE a_Plant) override { return (a_Plant == E_BLOCK_NETHER_WART); }
+};
diff --git a/src/Blocks/BlockPlant.h b/src/Blocks/BlockPlant.h
new file mode 100644
index 000000000..0e6aca7eb
--- /dev/null
+++ b/src/Blocks/BlockPlant.h
@@ -0,0 +1,132 @@
+
+// BlockPlant.h
+
+// Base class for any growing block
+
+
+
+
+
+#pragma once
+
+#include "BlockHandler.h"
+
+class cBlockPlant : public cBlockHandler
+{
+ typedef cBlockHandler Super;
+ bool m_NeedLightToGrow;
+public:
+ cBlockPlant(BLOCKTYPE a_BlockType, bool a_LightToGrow)
+ : Super(a_BlockType), m_NeedLightToGrow(a_LightToGrow){}
+
+protected:
+ enum PlantAction
+ {
+ paDeath,
+ paGrowth,
+ paStay
+ };
+
+ /** Checks whether there is enough light for the plant to grow.
+ If the plant doesn't require light to grow, then it returns paGrowth.
+ If the plant requires light to grow and there is enough light, it returns paGrowth.
+ If the plant requires light to grow and there isn't enough light, it returns paStay.
+ If the plant requires light to grow and there is too little light, it returns paDeath.
+ */
+ PlantAction HasEnoughLight(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ {
+ // If the plant requires light to grow, check to see if there is enough light
+ // Otherwise, return true
+ if (m_NeedLightToGrow)
+ {
+ NIBBLETYPE Blocklight = a_Chunk.GetBlockLight(a_RelX, a_RelY, a_RelZ);
+ NIBBLETYPE SkyLight = a_Chunk.GetSkyLight (a_RelX, a_RelY, a_RelZ);
+ NIBBLETYPE Light = a_Chunk.GetTimeAlteredLight(SkyLight);
+
+ // If the amount of light provided by blocks is greater than the sky light, use it instead
+ if (Blocklight > Light)
+ {
+ Light = Blocklight;
+ }
+
+ // Return true if there is enough light
+ // Set m_ShouldDie if the base light amounts are not enough to sustain a plant
+ if (Light > 8)
+ {
+ return paGrowth;
+ }
+ else if (Blocklight < 9 && SkyLight < 9)
+ {
+ return paDeath;
+ }
+
+ return paStay;
+ }
+
+ return paGrowth;
+ }
+
+ /** Checks whether a plant can grow grow, based on what is returned from cBlockPlant::HasEnoughLight
+ and a random check based on what is returned from cBlockPlant::GetGrowthChance.
+ Can return three values.
+ paGrowth when the conditions are right for the plant to grow.
+ paStay when the conditions are not quite right.
+ paDeath is returned when there isn't enough light for the plant to survive.
+ Plants that don't require light will never have a paDeath returned
+ */
+ virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ {
+ cFastRandom rand;
+ // Plant can grow if it has the required amount of light, and it passes a random chance based on surrounding blocks
+ PlantAction Action = HasEnoughLight(a_Chunk, a_RelX, a_RelY, a_RelZ);
+ if ((Action == paGrowth) && (rand.NextInt(GetGrowthChance(a_Chunk, a_RelX, a_RelY, a_RelZ)) != 0))
+ {
+ Action = paStay;
+ }
+ return Action;
+ }
+
+ /** Generates a int value between 4 and 25 based on surrounding blocks that affect how quickly the plant grows.
+ The higher the value, the less likely the plant is to grow */
+ virtual int GetGrowthChance(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ {
+ float Chance = 1.0f;
+ a_RelY -= 1;
+ for (int x = -1; x < 2; ++x)
+ {
+ for (int z = -1; z < 2; ++z)
+ {
+ float Adjustment = 0.0f;
+ BLOCKTYPE Block;
+ NIBBLETYPE Meta;
+
+ // If the chunk we are trying to get the block information from is loaded
+ if (a_Chunk.UnboundedRelGetBlock(a_RelX + x, a_RelY, a_RelZ + z, Block, Meta))
+ {
+ cBlockHandler * Handler = cBlockInfo::Get(Block).m_Handler;
+
+ // If the block affects growth, add to the adjustment
+ if (Handler->CanSustainPlant(m_BlockType))
+ {
+ Adjustment = 1.0f;
+
+ // Farmland alters the chance further if it is watered
+ if ((Block == E_BLOCK_FARMLAND) && (Meta != 0))
+ {
+ Adjustment = 3.0f;
+ }
+ }
+ }
+
+ // If this is not the block right underneath the plant, it has little effect on the growth
+ if ((x != 0) || (z != 0))
+ {
+ Adjustment /= 4.0f;
+ }
+
+ Chance += Adjustment;
+ }
+ }
+ return FloorC(24.0f / Chance) + 1;
+ }
+};
diff --git a/src/Blocks/BlockStems.h b/src/Blocks/BlockStems.h
index 13b7a599f..df832c55a 100644
--- a/src/Blocks/BlockStems.h
+++ b/src/Blocks/BlockStems.h
@@ -1,7 +1,7 @@
#pragma once
-#include "BlockHandler.h"
+#include "BlockPlant.h"
#include "../World.h"
@@ -9,11 +9,12 @@
class cBlockStemsHandler :
- public cBlockHandler
+ public cBlockPlant
{
+ typedef cBlockPlant Super;
public:
cBlockStemsHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : Super(a_BlockType, true)
{
}
@@ -25,18 +26,26 @@ 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);
- if (Meta >= 7)
+ auto Action = CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
+ if (Action == paGrowth)
{
- // Grow the produce:
- int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
- int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
- a_Chunk.GetWorld()->GrowMelonPumpkin(BlockX, a_RelY, BlockZ, m_BlockType);
+ NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
+ if (Meta >= 7)
+ {
+ // Grow the produce:
+ int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
+ int BlockZ = a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width;
+ a_Chunk.GetWorld()->GrowMelonPumpkin(BlockX, a_RelY, BlockZ, m_BlockType);
+ }
+ else
+ {
+ // Grow the stem:
+ a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, Meta + 1);
+ }
}
- else
+ else if (Action == paDeath)
{
- // Grow the stem:
- a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, m_BlockType, Meta + 1);
+ a_Chunk.GetWorld()->DigBlock(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width);
}
}
diff --git a/src/Blocks/BlockSugarcane.h b/src/Blocks/BlockSugarcane.h
index 632dc8baa..2b4c9e583 100644
--- a/src/Blocks/BlockSugarcane.h
+++ b/src/Blocks/BlockSugarcane.h
@@ -1,18 +1,19 @@
#pragma once
-#include "BlockHandler.h"
+#include "BlockPlant.h"
class cBlockSugarcaneHandler :
- public cBlockHandler
+ public cBlockPlant
{
+ typedef cBlockPlant Super;
public:
cBlockSugarcaneHandler(BLOCKTYPE a_BlockType)
- : cBlockHandler(a_BlockType)
+ : Super(a_BlockType, false)
{
}
@@ -73,7 +74,10 @@ 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
{
- a_Chunk.GetWorld()->GrowSugarcane(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
+ if (CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ) == paGrowth)
+ {
+ a_Chunk.GetWorld()->GrowSugarcane(a_RelX + a_Chunk.GetPosX() * cChunkDef::Width, a_RelY, a_RelZ + a_Chunk.GetPosZ() * cChunkDef::Width, 1);
+ }
}
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
@@ -81,6 +85,19 @@ public:
UNUSED(a_Meta);
return 7;
}
+
+protected:
+
+ virtual PlantAction CanGrow(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
+ {
+ auto Action = paStay;
+ if (((a_RelY + 1) < cChunkDef::Height) && (a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ) == E_BLOCK_AIR))
+ {
+ Action = Super::CanGrow(a_Chunk, a_RelX, a_RelY, a_RelZ);
+ }
+
+ return Action;
+ }
} ;