From 4f554e91abd861323aaf9f46d75ff0350a519cef Mon Sep 17 00:00:00 2001 From: DarkoGNU <42816979+DarkoGNU@users.noreply.github.com> Date: Thu, 21 Apr 2022 20:56:21 +0200 Subject: Implement farmland trampling (#5401) * Add DarkoGNU to CONTRIBUTORS * HandleFarmlandTrampling function & its docs * Fix decimal separators (, -> .) * Fix style. Adjust thresholds. Make function non-virtual * Adjust thresholds again. Prepare for fixing #5402 * Trying to fix falling through farmlands * Another style fix * Add FarmlandTramplingEnabled to world.ini * Docs for IsFarmlandTramplingEnabled * Style * Farmland trampling - handling the random chance * Trampling kinda works, very buggy * Trying to fix clang-tidy * Fix trampling * Trying to fix the 'undocumented API symbol' * Implement bearbin's suggestions * Calculate volume properly * Don't use std::pow for squaring * Improved comments * Really, should comments' style be checked? --- src/Blocks/BlockFarmland.h | 67 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) (limited to 'src/Blocks/BlockFarmland.h') 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(&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; + }); } } -- cgit v1.2.3