summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockAnvil.h8
-rw-r--r--src/Blocks/BlockBed.h7
-rw-r--r--src/Blocks/BlockButton.h34
-rw-r--r--src/Blocks/BlockCocoaPod.h8
-rw-r--r--src/Blocks/BlockComparator.h79
-rw-r--r--src/Blocks/BlockDirt.h41
-rw-r--r--src/Blocks/BlockDoor.cpp20
-rw-r--r--src/Blocks/BlockDoor.h12
-rw-r--r--src/Blocks/BlockFarmland.h13
-rw-r--r--src/Blocks/BlockFire.h19
-rw-r--r--src/Blocks/BlockFluid.h6
-rw-r--r--src/Blocks/BlockHandler.cpp40
-rw-r--r--src/Blocks/BlockHandler.h23
-rw-r--r--src/Blocks/BlockHopper.h2
-rw-r--r--src/Blocks/BlockLadder.h11
-rw-r--r--src/Blocks/BlockLeaves.h36
-rw-r--r--src/Blocks/BlockLever.h18
-rw-r--r--src/Blocks/BlockPiston.cpp6
-rw-r--r--src/Blocks/BlockQuartz.h7
-rw-r--r--src/Blocks/BlockRail.h43
-rw-r--r--src/Blocks/BlockSapling.h142
-rw-r--r--src/Blocks/BlockSideways.h6
-rw-r--r--src/Blocks/BlockSlab.h10
-rw-r--r--src/Blocks/BlockStairs.h6
-rw-r--r--src/Blocks/BlockTorch.h23
-rw-r--r--src/Blocks/BlockTrapdoor.h11
-rw-r--r--src/Blocks/BlockTripwireHook.h16
-rw-r--r--src/Blocks/BlockVine.h2
-rw-r--r--src/Blocks/BlockWallSign.h12
-rw-r--r--src/Blocks/CMakeLists.txt5
-rw-r--r--src/Blocks/WorldInterface.h12
31 files changed, 521 insertions, 157 deletions
diff --git a/src/Blocks/BlockAnvil.h b/src/Blocks/BlockAnvil.h
index abfa0f782..154394550 100644
--- a/src/Blocks/BlockAnvil.h
+++ b/src/Blocks/BlockAnvil.h
@@ -46,10 +46,10 @@ public:
switch (Direction)
{
- case 0: a_BlockMeta = 0x2 | Meta << 2; break;
- case 1: a_BlockMeta = 0x3 | Meta << 2; break;
- case 2: a_BlockMeta = 0x0 | Meta << 2; break;
- case 3: a_BlockMeta = 0x1 | Meta << 2; break;
+ case 0: a_BlockMeta = static_cast<NIBBLETYPE>(0x2 | Meta << 2); break;
+ case 1: a_BlockMeta = static_cast<NIBBLETYPE>(0x3 | Meta << 2); break;
+ case 2: a_BlockMeta = static_cast<NIBBLETYPE>(0x0 | Meta << 2); break;
+ case 3: a_BlockMeta = static_cast<NIBBLETYPE>(0x1 | Meta << 2); break;
default:
{
return false;
diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h
index 46f361686..905c0ea76 100644
--- a/src/Blocks/BlockBed.h
+++ b/src/Blocks/BlockBed.h
@@ -36,11 +36,6 @@ public:
a_Pickups.push_back(cItem(E_ITEM_BED, 1, 0));
}
- virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
- {
- return true;
- }
-
// Bed specific helper functions
static NIBBLETYPE RotationToMetaData(double a_Rotation)
@@ -53,7 +48,7 @@ public:
a_Rotation = (a_Rotation / 360) * 4;
- return ((char)a_Rotation + 2) % 4;
+ return (static_cast<NIBBLETYPE>(a_Rotation + 2)) % 4;
}
static Vector3i MetaDataToDirection(NIBBLETYPE a_MetaData)
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index d24c7d952..3558729bb 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -19,15 +19,35 @@ public:
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{
+ NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+
+ double x(a_BlockX);
+ double y(a_BlockY);
+ double z(a_BlockZ);
+
+ // If button is already on do nothing
+ if (Meta & 0x08)
+ {
+ return;
+ }
+
// Set p the ON bit to on
- NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
+ Meta |= 0x08;
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
- a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
+ a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", x, y, z, 0.5f, 0.6f);
// Queue a button reset (unpress)
- a_ChunkInterface.QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30, m_BlockType, a_WorldInterface);
+ int delay = (m_BlockType == E_BLOCK_STONE_BUTTON) ? 20 : 30;
+
+ a_ChunkInterface.QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x07), delay, m_BlockType, a_WorldInterface);
+
+ a_Player->GetWorld()->ScheduleTask(delay, [x, y, z](cWorld & a_World)
+ {
+ a_World.BroadcastSoundEffect("random.click", x, y, z, 0.5f, 0.5f);
+ });
+
}
@@ -67,14 +87,19 @@ public:
case BLOCK_FACE_XM: return 0x2;
case BLOCK_FACE_XP: return 0x1;
case BLOCK_FACE_YM: return 0x0;
- default:
+ case BLOCK_FACE_NONE:
{
ASSERT(!"Unhandled block face!");
return 0x0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x7)
@@ -93,6 +118,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockCocoaPod.h b/src/Blocks/BlockCocoaPod.h
index 1b659d48f..4d16d2552 100644
--- a/src/Blocks/BlockCocoaPod.h
+++ b/src/Blocks/BlockCocoaPod.h
@@ -81,12 +81,18 @@ public:
case BLOCK_FACE_XM: return 3;
case BLOCK_FACE_XP: return 1;
case BLOCK_FACE_ZP: return 2;
- default:
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
{
ASSERT(!"Unknown face");
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockComparator.h b/src/Blocks/BlockComparator.h
index ed73a162e..3babeddad 100644
--- a/src/Blocks/BlockComparator.h
+++ b/src/Blocks/BlockComparator.h
@@ -64,6 +64,85 @@ public:
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetYaw());
return true;
}
+
+
+ inline static Vector3i GetSideCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, bool a_bInverse)
+ {
+ if (!a_bInverse)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockX++; break;
+ case 0x1: a_BlockZ--; break;
+ case 0x2: a_BlockX--; break;
+ case 0x3: a_BlockZ++; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockX--; break;
+ case 0x1: a_BlockZ++; break;
+ case 0x2: a_BlockX++; break;
+ case 0x3: a_BlockZ--; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+
+ inline static Vector3i GetRearCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockZ++; break;
+ case 0x1: a_BlockX--; break;
+ case 0x2: a_BlockZ--; break;
+ case 0x3: a_BlockX++; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
+
+
+ inline static Vector3i GetFrontCoordinate(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta)
+ {
+ switch (a_Meta)
+ {
+ case 0x0: a_BlockZ--; break;
+ case 0x1: a_BlockX++; break;
+ case 0x2: a_BlockZ++; break;
+ case 0x3: a_BlockX--; break;
+ default:
+ {
+ LOGWARNING("%s: Unknown metadata: %d", __FUNCTION__, a_Meta);
+ ASSERT(!"Unknown metadata while determining orientation of comparator!");
+ break;
+ }
+ }
+
+ return Vector3i(a_BlockX, a_BlockY, a_BlockZ);
+ }
} ;
diff --git a/src/Blocks/BlockDirt.h b/src/Blocks/BlockDirt.h
index 32512a2ef..3d671d218 100644
--- a/src/Blocks/BlockDirt.h
+++ b/src/Blocks/BlockDirt.h
@@ -3,6 +3,7 @@
#include "BlockHandler.h"
#include "../FastRandom.h"
+#include "../BlockInfo.h"
#include "Root.h"
#include "Bindings/PluginManager.h"
@@ -39,19 +40,6 @@ public:
{
return;
}
-
- // Grass becomes dirt if there is something on top of it:
- if (a_RelY < cChunkDef::Height - 1)
- {
- BLOCKTYPE Above;
- NIBBLETYPE AboveMeta;
- a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY + 1, a_RelZ, Above, AboveMeta);
- if (!cBlockInfo::GetHandler(Above)->CanDirtGrowGrass(AboveMeta))
- {
- a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
- return;
- }
- }
// Make sure that there is enough light at the source block to spread
if (!a_Chunk.GetWorld()->IsChunkLighted(a_Chunk.GetPosX(), a_Chunk.GetPosZ()))
@@ -59,10 +47,24 @@ public:
a_Chunk.GetWorld()->QueueLightChunk(a_Chunk.GetPosX(), a_Chunk.GetPosZ());
return;
}
- else if ((a_RelY < cChunkDef::Height - 1) && std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY + 1, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY + 1, a_RelZ))) < 9)
+ else if ((a_RelY < cChunkDef::Height - 1))
{
+ BLOCKTYPE above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
+
+ // Grass turns back to dirt when the block above is not transparent
+ if (!cBlockInfo::IsTransparent(above))
+ {
+ a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
+ return;
+ }
+
+ NIBBLETYPE light = std::max(a_Chunk.GetBlockLight(a_RelX, a_RelY + 1, a_RelZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(a_RelX, a_RelY + 1, a_RelZ)));
// Source block is not bright enough to spread
- return;
+ if (light < 9)
+ {
+ return;
+ }
+
}
// Grass spreads to adjacent dirt blocks:
@@ -95,11 +97,10 @@ public:
// Not a regular dirt block
continue;
}
-
- BLOCKTYPE AboveDest;
- NIBBLETYPE AboveMeta;
- Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
- if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
+ BLOCKTYPE above = a_Chunk.GetBlock(BlockX, BlockY + 1, BlockZ);
+ NIBBLETYPE light = std::max(a_Chunk.GetBlockLight(BlockX, BlockY + 1, BlockZ), a_Chunk.GetTimeAlteredLight(a_Chunk.GetSkyLight(BlockX, BlockY + 1, BlockZ)));
+ // Grass does not spread to blocks with a light level less than 5
+ if ((light > 4) && cBlockInfo::IsTransparent(above))
{
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread(*Chunk->GetWorld(), Chunk->GetPosX() * cChunkDef::Width + BlockX, BlockY, Chunk->GetPosZ() * cChunkDef::Width + BlockZ, ssGrassSpread))
{
diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp
index d13c8d657..a4e375cf0 100644
--- a/src/Blocks/BlockDoor.cpp
+++ b/src/Blocks/BlockDoor.cpp
@@ -50,10 +50,24 @@ void cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterfac
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
- if (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_WOODEN_DOOR)
+ switch (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))
{
- ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
- a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
+ default:
+ {
+ ASSERT(!"Unhandled door block type");
+ }
+ case E_BLOCK_ACACIA_DOOR:
+ case E_BLOCK_BIRCH_DOOR:
+ case E_BLOCK_DARK_OAK_DOOR:
+ case E_BLOCK_JUNGLE_DOOR:
+ case E_BLOCK_SPRUCE_DOOR:
+ case E_BLOCK_IRON_DOOR:
+ case E_BLOCK_WOODEN_DOOR:
+ {
+ ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
+ a_Player->GetWorld()->BroadcastSoundParticleEffect(1003, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle());
+ break;
+ }
}
}
diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h
index 445383e7c..79ed4f723 100644
--- a/src/Blocks/BlockDoor.h
+++ b/src/Blocks/BlockDoor.h
@@ -55,6 +55,10 @@ public:
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
+ if ((a_BlockMeta & 0x08) != 0) // is top part of door
+ {
+ return;
+ }
switch (m_BlockType)
{
case E_BLOCK_WOODEN_DOOR:
@@ -242,13 +246,13 @@ public:
if ((Meta & 0x08) != 0)
{
// The coords are pointing at the top part of the door
- if (a_BlockX > 0)
+ if (a_BlockY > 0)
{
NIBBLETYPE DownMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY - 1, a_BlockZ);
- return (NIBBLETYPE) ((DownMeta & 0x07) | 0x08 | (Meta << 4));
+ return static_cast<NIBBLETYPE>((DownMeta & 0x07) | 0x08 | (Meta << 4));
}
// This is the top part of the door at the bottommost layer of the world, there's no bottom:
- return (NIBBLETYPE) (0x08 | (Meta << 4));
+ return static_cast<NIBBLETYPE>(0x08 | (Meta << 4));
}
else
{
@@ -256,7 +260,7 @@ public:
if (a_BlockY < cChunkDef::Height - 1)
{
NIBBLETYPE UpMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ);
- return (NIBBLETYPE) (Meta | (UpMeta << 4));
+ return static_cast<NIBBLETYPE>(Meta | (UpMeta << 4));
}
// This is the bottom part of the door at the topmost layer of the world, there's no top:
return Meta;
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index 23a7392da..8d43632ff 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -65,13 +65,22 @@ public:
}
}
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
+
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override
{
+ // Don't care about any neighbor but the one above us (fix recursion loop in #2213):
+ if (a_WhichNeighbor != BLOCK_FACE_YP)
+ {
+ return;
+ }
+
+ // Don't care about anything if we're at the top of the world:
if (a_BlockY >= cChunkDef::Height)
{
return;
}
+ // Check whether we should revert to dirt:
BLOCKTYPE UpperBlock = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ);
if (cBlockInfo::FullyOccupiesVoxel(UpperBlock))
{
@@ -79,11 +88,13 @@ public:
}
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
a_Pickups.Add(E_BLOCK_DIRT, 1, 0); // Reset meta
}
+
bool IsWaterInNear(cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
{
if (a_Chunk.GetWorld()->IsWeatherWetAt(a_RelX, a_RelZ))
diff --git a/src/Blocks/BlockFire.h b/src/Blocks/BlockFire.h
index 2038df94b..3f75455da 100644
--- a/src/Blocks/BlockFire.h
+++ b/src/Blocks/BlockFire.h
@@ -121,6 +121,20 @@ public:
}
}
+ int PortalHeight = MaxY - Y - 1;
+ int PortalWidth = XZP - XZM + 1;
+ if ((PortalHeight < a_WorldInterface.GetMinNetherPortalHeight()) || (PortalHeight > a_WorldInterface.GetMaxNetherPortalHeight()))
+ {
+ // The portal isn't high enough, or is too high
+ return;
+ }
+
+ if ((PortalWidth < a_WorldInterface.GetMinNetherPortalWidth()) || (PortalWidth > a_WorldInterface.GetMaxNetherPortalWidth()))
+ {
+ // The portal isn't wide enough, or is too wide
+ return;
+ }
+
for (int Height = Y + 1; Height <= MaxY - 1; Height++) // Loop through boundary to set portal blocks
{
for (int Width = XZM; Width <= XZP; Width++)
@@ -217,6 +231,11 @@ public:
return (FoundFrameZP && FoundFrameZM);
}
+
+ virtual bool DoesIgnoreBuildCollision(cPlayer * a_Player, NIBBLETYPE a_Meta) override
+ {
+ return true;
+ }
};
diff --git a/src/Blocks/BlockFluid.h b/src/Blocks/BlockFluid.h
index 2823baedc..58b3ce042 100644
--- a/src/Blocks/BlockFluid.h
+++ b/src/Blocks/BlockFluid.h
@@ -49,12 +49,6 @@ public:
}
super::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk);
}
-
-
- virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
- {
- return false;
- }
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 452cc94a5..412fc3aeb 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -389,12 +389,12 @@ void cBlockHandler::OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWor
void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
// Notify the neighbors
- NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1);
+ NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ, BLOCK_FACE_XP);
+ NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ, BLOCK_FACE_XM);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_YP);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_YM);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1, BLOCK_FACE_ZP);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1, BLOCK_FACE_ZM);
}
@@ -404,29 +404,30 @@ void cBlockHandler::OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface
void cBlockHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Notify the neighbors
- NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1);
- NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1);
+ NeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY, a_BlockZ, BLOCK_FACE_XP);
+ NeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY, a_BlockZ, BLOCK_FACE_XM);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_YP);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_YM);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ - 1, BLOCK_FACE_ZP);
+ NeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ + 1, BLOCK_FACE_ZM);
}
-void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
+void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_NeighborX, int a_NeighborY, int a_NeighborZ, eBlockFace a_WhichNeighbor)
{
- if ((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height))
+ if ((a_NeighborY >= 0) && (a_NeighborY < cChunkDef::Height))
{
- cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ))->OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
+ cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_NeighborX, a_NeighborY, a_NeighborZ))->OnNeighborChanged(a_ChunkInterface, a_NeighborX, a_NeighborY, a_NeighborZ, a_WhichNeighbor);
}
}
+
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.
@@ -512,15 +513,6 @@ bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, in
-bool cBlockHandler::CanDirtGrowGrass(NIBBLETYPE a_Meta)
-{
- return ((cBlockInfo::IsTransparent(m_BlockType)) || (cBlockInfo::IsOneHitDig(m_BlockType)));
-}
-
-
-
-
-
bool cBlockHandler::IsUseable()
{
return false;
diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h
index 4dec0dc95..1b357c3f1 100644
--- a/src/Blocks/BlockHandler.h
+++ b/src/Blocks/BlockHandler.h
@@ -56,13 +56,19 @@ public:
/// Called before a block gets destroyed / replaced with air
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ);
- /// Called when a direct neighbor of this block has been changed (The position is the own position, not the neighbor position)
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) {}
-
- /// Notifies all neighbors of the given block about a change
- static void NeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ);
-
- /// Called while the player diggs the block.
+ /** Called when a direct neighbor of this block has been changed (The position is the block's own position, not the changing neighbor's position)
+ a_WhichNeighbor indicates which neighbor has changed. For example, BLOCK_FACE_YP meant the neighbor above has changed.
+ BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) {}
+
+ /** Notifies the specified neighbor that the current block has changed.
+ a_NeighborXYZ coords are the coords of the neighbor
+ a_WhichNeighbor specifies which neighbor (relative to a_NeighborXYZ) has changed.
+ For example BLOCK_FACE_YP means that the block at {a_NeighborX, a_NeighborY + 1, a_NeighborZ} has changed.
+ BLOCK_FACE_NONE means that it is a neighbor not directly adjacent (diagonal, etc.) */
+ static void NeighborChanged(cChunkInterface & a_ChunkInterface, int a_NeighborX, int a_NeighborY, int a_NeighborZ, eBlockFace a_WhichNeighbor);
+
+ /** Called when the player starts digging the block. */
virtual void OnDigging(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {}
/// Called if the user right clicks the block and the block is useable
@@ -83,9 +89,6 @@ 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);
-
- /** Can the dirt under this block grow to grass? */
- virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta);
/** Checks if the block can be placed at this point.
Default: CanBeAt(...)
diff --git a/src/Blocks/BlockHopper.h b/src/Blocks/BlockHopper.h
index 4a5d32dd5..06e2b0e9f 100644
--- a/src/Blocks/BlockHopper.h
+++ b/src/Blocks/BlockHopper.h
@@ -35,7 +35,7 @@ public:
case BLOCK_FACE_NORTH: a_BlockMeta = E_META_HOPPER_FACING_ZP; break;
case BLOCK_FACE_SOUTH: a_BlockMeta = E_META_HOPPER_FACING_ZM; break;
case BLOCK_FACE_WEST: a_BlockMeta = E_META_HOPPER_FACING_XP; break;
- default: a_BlockMeta = E_META_HOPPER_UNATTACHED; break;
+ case BLOCK_FACE_NONE: a_BlockMeta = E_META_HOPPER_UNATTACHED; break;
}
return true;
}
diff --git a/src/Blocks/BlockLadder.h b/src/Blocks/BlockLadder.h
index ab3f55439..d727f8f8e 100644
--- a/src/Blocks/BlockLadder.h
+++ b/src/Blocks/BlockLadder.h
@@ -57,8 +57,17 @@ public:
case BLOCK_FACE_ZP: return 0x3;
case BLOCK_FACE_XM: return 0x4;
case BLOCK_FACE_XP: return 0x5;
- default: return 0x2;
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
+ {
+ return 0x2;
+ }
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockLeaves.h b/src/Blocks/BlockLeaves.h
index bd9a7414e..2368eab7b 100644
--- a/src/Blocks/BlockLeaves.h
+++ b/src/Blocks/BlockLeaves.h
@@ -40,33 +40,49 @@ public:
{
cFastRandom rand;
- // Old leaves - 3 bits contain display; new leaves - 1st bit, shifted left two for saplings to understand
- if (rand.NextInt(6) == 0)
+ // There is a chance to drop a sapling that varies depending on the type of leaf broken.
+ // TODO: Take into account fortune for sapling drops.
+ int chance;
+ if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_JUNGLE))
+ {
+ // Jungle leaves have a 2.5% chance of dropping a sapling.
+ chance = rand.NextInt(40);
+ }
+ else
+ {
+ // Other leaves have a 5% chance of dropping a sapling.
+ chance = rand.NextInt(20);
+ }
+ if (chance == 0)
{
a_Pickups.push_back(
cItem(
E_BLOCK_SAPLING,
1,
- (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : (2 << (a_BlockMeta & 0x01))
+ (m_BlockType == E_BLOCK_LEAVES) ? (a_BlockMeta & 0x03) : static_cast<short>(4 + (a_BlockMeta & 0x01))
)
);
}
-
- // 1 % chance of dropping an apple, if the leaves' type is Apple Leaves
+
+ // 0.5 % chance of dropping an apple, if the leaves' type is Apple Leaves
if ((m_BlockType == E_BLOCK_LEAVES) && ((a_BlockMeta & 0x03) == E_META_LEAVES_APPLE))
{
- if (rand.NextInt(101) == 0)
+ if (rand.NextInt(200) == 0)
{
a_Pickups.push_back(cItem(E_ITEM_RED_APPLE, 1, 0));
}
}
}
-
-
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
+
+
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override
{
+ // Unset 0x8 bit so this block gets checked for decay:
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
- a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7); // Unset 0x8 bit so it gets checked for decay
+ if ((Meta & 0x08) != 0)
+ {
+ a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x7);
+ }
}
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index 2da138e5f..8d676b56f 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -59,14 +59,18 @@ public:
// Determine lever direction:
switch (a_Dir)
{
- case BLOCK_FACE_YP: return 0x6;
- case BLOCK_FACE_XP: return 0x1;
- case BLOCK_FACE_XM: return 0x2;
- case BLOCK_FACE_ZP: return 0x3;
- case BLOCK_FACE_ZM: return 0x4;
- case BLOCK_FACE_YM: return 0x0;
- default: return 0x6;
+ case BLOCK_FACE_YP: return 0x6;
+ case BLOCK_FACE_XP: return 0x1;
+ case BLOCK_FACE_XM: return 0x2;
+ case BLOCK_FACE_ZP: return 0x3;
+ case BLOCK_FACE_ZM: return 0x4;
+ case BLOCK_FACE_YM: return 0x0;
+ case BLOCK_FACE_NONE: return 0x6;
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp
index d9f4913d8..75f8621a7 100644
--- a/src/Blocks/BlockPiston.cpp
+++ b/src/Blocks/BlockPiston.cpp
@@ -179,7 +179,7 @@ void cBlockPistonHandler::ExtendPiston(int a_BlockX, int a_BlockY, int a_BlockZ,
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, pistonBlock, pistonMeta | 0x8);
a_World->SetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), false);
- a_World->ScheduleTask(PISTON_TICK_DELAY, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
}
@@ -229,7 +229,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
std::vector<Vector3i> ScheduledBlocks;
ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
ScheduledBlocks.push_back(Vector3i(tempx, tempy, tempz));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
return;
}
}
@@ -239,7 +239,7 @@ void cBlockPistonHandler::RetractPiston(int a_BlockX, int a_BlockY, int a_BlockZ
std::vector<Vector3i> ScheduledBlocks;
ScheduledBlocks.push_back(Vector3i(a_BlockX, a_BlockY, a_BlockZ));
- a_World->ScheduleTask(PISTON_TICK_DELAY + 1, std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks));
+ a_World->ScheduleTask(PISTON_TICK_DELAY + 1, static_cast<cWorld::cTaskPtr>(std::make_shared<cWorld::cTaskSendBlockToAllPlayers>(ScheduledBlocks)));
}
diff --git a/src/Blocks/BlockQuartz.h b/src/Blocks/BlockQuartz.h
index edc4fb9c5..b936a7e4a 100644
--- a/src/Blocks/BlockQuartz.h
+++ b/src/Blocks/BlockQuartz.h
@@ -36,6 +36,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace, NIBBLETYPE a_QuartzMeta)
{
switch (a_BlockFace)
@@ -58,11 +59,15 @@ public:
return 0x3; // East or west
}
- default:
+ case BLOCK_FACE_NONE:
{
ASSERT(!"Unhandled block face!");
return a_QuartzMeta; // No idea, give a special meta (all sides the same)
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h
index a2e27a351..7fb910e8c 100644
--- a/src/Blocks/BlockRail.h
+++ b/src/Blocks/BlockRail.h
@@ -47,15 +47,14 @@ public:
super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
// Alert diagonal rails
- OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
-
- OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1, BLOCK_FACE_NONE);
}
@@ -64,19 +63,18 @@ public:
super::OnDestroyed(a_ChunkInterface, a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ);
// Alert diagonal rails
- OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
-
- OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
- OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ + 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY + 1, a_BlockZ - 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX + 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX - 1, a_BlockY - 1, a_BlockZ, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ + 1, BLOCK_FACE_NONE);
+ OnNeighborChanged(a_ChunkInterface, a_BlockX, a_BlockY - 1, a_BlockZ - 1, BLOCK_FACE_NONE);
}
- virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_WhichNeighbor) override
{
NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (IsUnstable(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ) && (Meta != FindMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ)))
@@ -487,7 +485,12 @@ public:
}
break;
}
- default: break;
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
+ {
+ break;
+ }
}
return true;
}
diff --git a/src/Blocks/BlockSapling.h b/src/Blocks/BlockSapling.h
index bec79c6f3..c15e0a195 100644
--- a/src/Blocks/BlockSapling.h
+++ b/src/Blocks/BlockSapling.h
@@ -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);
-
- if ((Meta & 0x08) != 0)
+ 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)));
+
+ // 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);
+ }
+ // 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)
{
- 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);
+ 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;
+ }
}
- else
+ // 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)
{
- a_Chunk.SetMeta(a_RelX, a_RelY, a_RelZ, Meta | 0x08);
+ 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;
}
} ;
diff --git a/src/Blocks/BlockSideways.h b/src/Blocks/BlockSideways.h
index 4b1e38d6d..e52fbaa2f 100644
--- a/src/Blocks/BlockSideways.h
+++ b/src/Blocks/BlockSideways.h
@@ -58,12 +58,16 @@ public:
return a_Meta | 0x4; // East or west
}
- default:
+ case BLOCK_FACE_NONE:
{
ASSERT(!"Unhandled block face!");
return a_Meta | 0xC; // No idea, give a special meta
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
} ;
diff --git a/src/Blocks/BlockSlab.h b/src/Blocks/BlockSlab.h
index d762154df..58e85013e 100644
--- a/src/Blocks/BlockSlab.h
+++ b/src/Blocks/BlockSlab.h
@@ -41,7 +41,7 @@ public:
) override
{
a_BlockType = m_BlockType;
- NIBBLETYPE Meta = (NIBBLETYPE) a_Player->GetEquippedItem().m_ItemDamage;
+ NIBBLETYPE Meta = static_cast<NIBBLETYPE>(a_Player->GetEquippedItem().m_ItemDamage);
// Set the correct metadata based on player equipped item (i.e. a_BlockMeta not initialised yet)
switch (a_BlockFace)
@@ -88,12 +88,6 @@ public:
return true;
}
-
- virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
- {
- return ((a_Meta & 0x8) != 0);
- }
-
/// Returns true if the specified blocktype is one of the slabs handled by this handler
static bool IsAnySlabType(BLOCKTYPE a_BlockType)
@@ -104,7 +98,7 @@ public:
virtual void OnCancelRightClick(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace) override
{
- if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player->GetEquippedItem().m_ItemType != (short)m_BlockType))
+ if ((a_BlockFace == BLOCK_FACE_NONE) || (a_Player->GetEquippedItem().m_ItemType != static_cast<short>(m_BlockType)))
{
return;
}
diff --git a/src/Blocks/BlockStairs.h b/src/Blocks/BlockStairs.h
index d396204e0..7ef69d2ec 100644
--- a/src/Blocks/BlockStairs.h
+++ b/src/Blocks/BlockStairs.h
@@ -62,12 +62,6 @@ public:
}
- virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
- {
- return true;
- }
-
-
static NIBBLETYPE RotationToMetaData(double a_Rotation)
{
a_Rotation += 90 + 45; // So its not aligned with axis
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index d63df94cf..0a834d13d 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -59,7 +59,7 @@ public:
case BLOCK_FACE_WEST: return E_META_TORCH_WEST;
case BLOCK_FACE_NORTH: return E_META_TORCH_NORTH;
case BLOCK_FACE_SOUTH: return E_META_TORCH_SOUTH;
- default:
+ case BLOCK_FACE_NONE:
{
ASSERT(!"Unhandled torch direction!");
break;
@@ -103,6 +103,11 @@ public:
case E_BLOCK_STAINED_GLASS:
case E_BLOCK_FENCE:
case E_BLOCK_NETHER_BRICK_FENCE:
+ case E_BLOCK_SPRUCE_FENCE:
+ case E_BLOCK_BIRCH_FENCE:
+ case E_BLOCK_JUNGLE_FENCE:
+ case E_BLOCK_DARK_OAK_FENCE:
+ case E_BLOCK_ACACIA_FENCE:
case E_BLOCK_COBBLESTONE_WALL:
{
// Torches can only be placed on top of these blocks
@@ -114,6 +119,22 @@ public:
// Toches can be placed on the top of these slabs only if the occupy the top half of the voxel
return ((a_BlockFace == BLOCK_FACE_YP) && ((a_BlockMeta & 0x08) == 0x08));
}
+ case E_BLOCK_WOODEN_STAIRS:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_BRICK_STAIRS:
+ case E_BLOCK_STONE_BRICK_STAIRS:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_SPRUCE_WOOD_STAIRS:
+ case E_BLOCK_BIRCH_WOOD_STAIRS:
+ case E_BLOCK_JUNGLE_WOOD_STAIRS:
+ case E_BLOCK_QUARTZ_STAIRS:
+ case E_BLOCK_ACACIA_WOOD_STAIRS:
+ case E_BLOCK_DARK_OAK_WOOD_STAIRS:
+ case E_BLOCK_RED_SANDSTONE_STAIRS:
+ {
+ return (a_BlockFace == BLOCK_FACE_TOP) && (a_BlockMeta & E_BLOCK_STAIRS_UPSIDE_DOWN);
+ }
default:
{
if (cBlockInfo::FullyOccupiesVoxel(a_BlockType))
diff --git a/src/Blocks/BlockTrapdoor.h b/src/Blocks/BlockTrapdoor.h
index dbb0b5a5b..a1d2dff6f 100644
--- a/src/Blocks/BlockTrapdoor.h
+++ b/src/Blocks/BlockTrapdoor.h
@@ -66,6 +66,7 @@ public:
return true;
}
+
inline static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_BlockFace)
{
switch (a_BlockFace)
@@ -74,14 +75,21 @@ public:
case BLOCK_FACE_ZM: return 0x0;
case BLOCK_FACE_XP: return 0x3;
case BLOCK_FACE_XM: return 0x2;
- default:
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
{
ASSERT(!"Unhandled block face!");
return 0;
}
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x3)
@@ -98,6 +106,7 @@ public:
}
}
+
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta;
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
index 88d389711..39892af5a 100644
--- a/src/Blocks/BlockTripwireHook.h
+++ b/src/Blocks/BlockTripwireHook.h
@@ -16,6 +16,7 @@ public:
{
}
+
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
@@ -29,6 +30,7 @@ public:
return true;
}
+
inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction)
{
switch (a_Direction)
@@ -37,10 +39,21 @@ public:
case BLOCK_FACE_XP: return 0x3;
case BLOCK_FACE_ZM: return 0x2;
case BLOCK_FACE_ZP: return 0x0;
- default: ASSERT(!"Unhandled tripwire hook direction!"); return 0x0;
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YM:
+ case BLOCK_FACE_YP:
+ {
+ ASSERT(!"Unhandled tripwire hook direction!");
+ return 0x0;
+ }
}
+ #if !defined(__clang__)
+ ASSERT(!"Unknown BLOCK_FACE");
+ return 0;
+ #endif
}
+
inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x03)
@@ -53,6 +66,7 @@ public:
}
}
+
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to zero
diff --git a/src/Blocks/BlockVine.h b/src/Blocks/BlockVine.h
index 00d7a69b8..3d06a8223 100644
--- a/src/Blocks/BlockVine.h
+++ b/src/Blocks/BlockVine.h
@@ -177,7 +177,7 @@ public:
}
- virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ)
+ virtual void OnUpdate(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
{
UNUSED(a_ChunkInterface);
UNUSED(a_WorldInterface);
diff --git a/src/Blocks/BlockWallSign.h b/src/Blocks/BlockWallSign.h
index b6599d033..9b90b78bf 100644
--- a/src/Blocks/BlockWallSign.h
+++ b/src/Blocks/BlockWallSign.h
@@ -55,11 +55,13 @@ public:
{
switch (a_Direction)
{
- case 0x2: return 0x2;
- case 0x3: return 0x3;
- case 0x4: return 0x4;
- case 0x5: return 0x5;
- default:
+ case BLOCK_FACE_ZM: return 0x2;
+ case BLOCK_FACE_ZP: return 0x3;
+ case BLOCK_FACE_XM: return 0x4;
+ case BLOCK_FACE_XP: return 0x5;
+ case BLOCK_FACE_NONE:
+ case BLOCK_FACE_YP:
+ case BLOCK_FACE_YM:
{
break;
}
diff --git a/src/Blocks/CMakeLists.txt b/src/Blocks/CMakeLists.txt
index ed3e321d4..d8affd9cf 100644
--- a/src/Blocks/CMakeLists.txt
+++ b/src/Blocks/CMakeLists.txt
@@ -95,6 +95,11 @@ SET (HDRS
MetaRotator.h
WorldInterface.h)
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set_source_files_properties(BlockHandler.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
+ set_source_files_properties(BlockPiston.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=old-style-cast")
+endif()
+
if(NOT MSVC)
add_library(Blocks ${SRCS} ${HDRS})
endif()
diff --git a/src/Blocks/WorldInterface.h b/src/Blocks/WorldInterface.h
index 44c118195..826df7034 100644
--- a/src/Blocks/WorldInterface.h
+++ b/src/Blocks/WorldInterface.h
@@ -55,6 +55,18 @@ public:
/** Returns true if it is raining, stormy or snowing at the specified location. This takes into account biomes. */
virtual bool IsWeatherWetAt(int a_BlockX, int a_BlockZ) = 0;
+ /** Returns or sets the minumim or maximum netherportal width */
+ virtual int GetMinNetherPortalWidth(void) const = 0;
+ virtual int GetMaxNetherPortalWidth(void) const = 0;
+ virtual void SetMinNetherPortalWidth(int a_NewMinWidth) = 0;
+ virtual void SetMaxNetherPortalWidth(int a_NewMaxWidth) = 0;
+
+ /** Returns or sets the minumim or maximum netherportal height */
+ virtual int GetMinNetherPortalHeight(void) const = 0;
+ virtual int GetMaxNetherPortalHeight(void) const = 0;
+ virtual void SetMinNetherPortalHeight(int a_NewMinHeight) = 0;
+ virtual void SetMaxNetherPortalHeight(int a_NewMaxHeight) = 0;
+
/** Returns the world height at the specified coords; waits for the chunk to get loaded / generated */
virtual int GetHeight(int a_BlockX, int a_BlockZ) = 0;