From a62b2b1be2103d7de2fd66c7304b7473e369be3c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 5 May 2021 14:25:10 +0100 Subject: Move item placement into item handlers (#5184) * Move item placement into item handlers + Add appropriate CanBeAt checks in cPlayer::PlaceBlocks, into which all placement handlers call. * Partly addresses #5157 * Fixes #4878 * Fixes #2919 * Fixes #4629 * Fixes #4239 * Fixes #4849 Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke * Review fixes * Update APIDesc.lua * Rename Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke --- src/Items/ItemSign.h | 89 +++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 50 deletions(-) (limited to 'src/Items/ItemSign.h') diff --git a/src/Items/ItemSign.h b/src/Items/ItemSign.h index 64d162f8d..fc5174e0b 100644 --- a/src/Items/ItemSign.h +++ b/src/Items/ItemSign.h @@ -3,8 +3,6 @@ #include "ItemHandler.h" #include "../World.h" -#include "../Blocks/BlockSignPost.h" -#include "../Blocks/BlockWallSign.h" #include "../ClientHandle.h" @@ -18,77 +16,68 @@ class cItemSignHandler: public: - cItemSignHandler(int a_ItemType): - Super(a_ItemType) - { - } - + using Super::Super; +private: + /** Converts the block face of the neighbor to which the wallsign is attached to the wallsign block's meta. */ + static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace) + { + switch (a_NeighborBlockFace) + { + case BLOCK_FACE_ZM: return 0x02; + case BLOCK_FACE_ZP: return 0x03; + case BLOCK_FACE_XM: return 0x04; + case BLOCK_FACE_XP: return 0x05; + case BLOCK_FACE_NONE: + case BLOCK_FACE_YP: + case BLOCK_FACE_YM: + { + break; + } + } + return 0x02; + } - virtual bool OnPlayerPlace( - cWorld & a_World, - cPlayer & a_Player, - const cItem & a_EquippedItem, - const Vector3i a_ClickedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos - ) override + virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) override { - // Check if placing on something ignoring build collision to edit the correct sign later on: - BLOCKTYPE ClickedBlockType; - NIBBLETYPE ClickedBlockMeta; - a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); - cChunkInterface ChunkInterface(a_World.GetChunkMap()); - bool IsReplacingClickedBlock = cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta); - - // If the regular placement doesn't work, do no further processing: - if (!Super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_ClickedBlockPos, a_ClickedBlockFace, a_CursorPos)) + if (a_ClickedBlockFace == BLOCK_FACE_TOP) + { + if (!a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_SIGN_POST, RotationToMetaData(a_Player.GetYaw()))) + { + return false; + } + } + else if (!a_Player.PlaceBlock(a_PlacePosition, E_BLOCK_WALLSIGN, BlockFaceToMetaData(a_ClickedBlockFace))) { return false; } - // Use IsReplacingClickedBlock to make sure we will edit the right sign: - auto SignPos = IsReplacingClickedBlock ? a_ClickedBlockPos : AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); - // After successfully placing the sign, open the sign editor for the player: - a_Player.GetClientHandle()->SendEditSign(SignPos.x, SignPos.y, SignPos.z); + a_Player.GetClientHandle()->SendEditSign(a_PlacePosition.x, a_PlacePosition.y, a_PlacePosition.z); return true; } - - - virtual bool IsPlaceable(void) override { return true; } - - - - virtual bool GetPlacementBlockTypeMeta( - cWorld * a_World, cPlayer * a_Player, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta - ) override + /** Converts the (player) rotation to placed-signpost block meta. */ + static NIBBLETYPE RotationToMetaData(double a_Rotation) { - if (a_ClickedBlockFace == BLOCK_FACE_TOP) + a_Rotation += 180 + (180.f / 16); // So it's not aligned with axis. + if (a_Rotation > 360) { - a_BlockMeta = cBlockSignPostHandler::RotationToMetaData(a_Player->GetYaw()); - a_BlockType = E_BLOCK_SIGN_POST; + a_Rotation -= 360; } - else - { - a_BlockMeta = cBlockWallSignHandler::BlockFaceToMetaData(a_ClickedBlockFace); - a_BlockType = E_BLOCK_WALLSIGN; - } - return true; + + a_Rotation = (a_Rotation / 360) * 16; + + return static_cast(a_Rotation) % 16; } } ; -- cgit v1.2.3