summaryrefslogtreecommitdiffstats
path: root/src/Blocks
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks')
-rw-r--r--src/Blocks/BlockFarmland.h67
1 files changed, 65 insertions, 2 deletions
diff --git a/src/Blocks/BlockFarmland.h b/src/Blocks/BlockFarmland.h
index 7ed1bb035..61ac872c8 100644
--- a/src/Blocks/BlockFarmland.h
+++ b/src/Blocks/BlockFarmland.h
@@ -10,7 +10,10 @@
#pragma once
#include "BlockHandler.h"
+#include "ChunkInterface.h"
#include "../BlockArea.h"
+#include "../Chunk.h"
+#include "../ClientHandle.h"
@@ -25,6 +28,58 @@ public:
using Super::Super;
+ /** Turns farmland into dirt.
+ Will first check for any colliding entities and teleport them to a higher position.
+ */
+ static void TurnToDirt(cChunk & a_Chunk, Vector3i a_AbsPos)
+ {
+ auto RelPos = cChunkDef::AbsoluteToRelative(a_AbsPos);
+ TurnToDirt(a_Chunk, a_AbsPos, RelPos);
+ }
+
+
+
+
+
+ /** Turns farmland into dirt.
+ Will first check for any colliding entities and teleport them to a higher position.
+ */
+ static void TurnToDirt(cChunk & a_Chunk, Vector3i a_AbsPos, Vector3i a_RelPos)
+ {
+ static const auto FarmlandHeight = cBlockInfo::GetBlockHeight(E_BLOCK_FARMLAND);
+ static const auto FullHeightDelta = 1 - FarmlandHeight;
+
+ a_Chunk.ForEachEntityInBox(
+ cBoundingBox(Vector3d(0.5, FarmlandHeight, 0.5) + a_AbsPos, 0.5, FullHeightDelta),
+ [&](cEntity & Entity)
+ {
+ if (!Entity.IsOnGround())
+ {
+ return false;
+ }
+ Entity.AddPosY(FullHeightDelta);
+
+ // Players need a packet that will update their position
+ if (Entity.IsPlayer())
+ {
+ auto Player = static_cast<cPlayer *>(&Entity);
+ // This works, but it's much worse than Vanilla.
+ // This can be easily improved by implementing relative
+ // "Player Position And Look" packets! See
+ // https://wiki.vg/Protocol#Player_Position_And_Look_.28clientbound.29
+ Player->GetClientHandle()->SendPlayerMoveLook();
+ }
+
+ return false;
+ });
+
+ a_Chunk.SetBlock(a_RelPos, E_BLOCK_DIRT, 0);
+ }
+
+
+
+
+
private:
virtual cItems ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const override
@@ -76,7 +131,8 @@ private:
}
default:
{
- a_Chunk.SetBlock(a_RelPos, E_BLOCK_DIRT, 0);
+ auto AbsPos = a_Chunk.RelativeToAbsolute(a_RelPos);
+ TurnToDirt(a_Chunk, AbsPos, a_RelPos);
break;
}
}
@@ -101,10 +157,17 @@ private:
}
// Check whether we should revert to dirt:
+ // TODO: fix for signs and slabs (possibly more blocks) - they should destroy farmland
auto upperBlock = a_ChunkInterface.GetBlock(a_BlockPos.addedY(1));
if (cBlockInfo::FullyOccupiesVoxel(upperBlock))
{
- a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_DIRT, 0);
+ // Until the fix above is done, this line should also suffice:
+ // a_ChunkInterface.SetBlock(a_BlockPos, E_BLOCK_DIRT, 0);
+ a_ChunkInterface.DoWithChunkAt(a_BlockPos, [&](cChunk & Chunk)
+ {
+ TurnToDirt(Chunk, a_BlockPos);
+ return true;
+ });
}
}