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/ItemChest.h | 83 ++++++++++----------------------------------------- 1 file changed, 15 insertions(+), 68 deletions(-) (limited to 'src/Items/ItemChest.h') diff --git a/src/Items/ItemChest.h b/src/Items/ItemChest.h index 8548f8d25..a714045ee 100644 --- a/src/Items/ItemChest.h +++ b/src/Items/ItemChest.h @@ -2,8 +2,7 @@ #pragma once #include "ItemHandler.h" -#include "../BlockInfo.h" -#include "../Blocks/BlockChest.h" +#include "Blocks/BlockChest.h" @@ -21,59 +20,12 @@ public: { } + cItemChestHandler(const cItemChestHandler &) = delete; - /** We need an OnPlayerPlace override because we're processing neighbor chests and changing their metas, - the parent class cannot do that. */ - 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 - { - if (a_ClickedBlockFace < 0) - { - // Clicked in air - return false; - } - - if (!cChunkDef::IsValidHeight(a_ClickedBlockPos.y)) - { - // The clicked block is outside the world, ignore this call altogether (#128) - return false; - } - - // Check if the block ignores build collision (water, grass etc.): - BLOCKTYPE ClickedBlockType; - NIBBLETYPE ClickedBlockMeta; - a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); - cChunkInterface ChunkInterface(a_World.GetChunkMap()); - Vector3i PlacePos; - if (cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta)) - { - PlacePos = a_ClickedBlockPos; - } - else - { - PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); - if (!cChunkDef::IsValidHeight(PlacePos.y)) - { - // The block is being placed outside the world, ignore this packet altogether (#128) - return false; - } - - // Check if the chest can overwrite the block at PlacePos: - BLOCKTYPE PlaceBlock; - NIBBLETYPE PlaceMeta; - a_World.GetBlockTypeMeta(PlacePos, PlaceBlock, PlaceMeta); - if (!cBlockHandler::For(PlaceBlock).DoesIgnoreBuildCollision(ChunkInterface, PlacePos, a_Player, PlaceMeta)) - { - return false; - } - } +private: + virtual bool CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) override + { // Check that there is at most one single neighbor of the same chest type: static const Vector3i CrossCoords[] = { @@ -82,11 +34,14 @@ public: { 1, 0, 0}, { 0, 0, 1}, }; + + auto & World = *a_Player.GetWorld(); int NeighborIdx = -1; + for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++) { - auto NeighborPos = PlacePos + CrossCoords[i]; - if (a_World.GetBlock(NeighborPos) != m_ItemType) + const auto NeighborPos = a_PlacePosition + CrossCoords[i]; + if (World.GetBlock(NeighborPos) != m_ItemType) { continue; } @@ -100,7 +55,7 @@ public: // Check that this neighbor is a single chest: for (size_t j = 0; j < ARRAYCOUNT(CrossCoords); j++) { - if (a_World.GetBlock(NeighborPos + CrossCoords[j]) == m_ItemType) + if (World.GetBlock(NeighborPos + CrossCoords[j]) == m_ItemType) { // Trying to place next to a dblchest return false; @@ -111,7 +66,7 @@ public: // Get the meta of the placed chest; take existing neighbors into account: BLOCKTYPE ChestBlockType = static_cast(m_ItemType); NIBBLETYPE Meta; - auto yaw = a_Player.GetYaw(); + const auto yaw = a_Player.GetYaw(); switch (NeighborIdx) { case 0: @@ -131,13 +86,13 @@ public: default: { // No neighbor, place based on yaw: - Meta = cBlockChestHandler::PlayerYawToMetaData(yaw); + Meta = cBlockChestHandler::YawToMetaData(yaw); break; } } // switch (NeighborIdx) // Place the new chest: - if (!a_Player.PlaceBlock(PlacePos.x, PlacePos.y, PlacePos.z, ChestBlockType, Meta)) + if (!a_Player.PlaceBlock(a_PlacePosition, ChestBlockType, Meta)) { return false; } @@ -145,17 +100,9 @@ public: // Adjust the existing chest, if any: if (NeighborIdx != -1) { - a_World.FastSetBlock(PlacePos + CrossCoords[NeighborIdx], ChestBlockType, Meta); + World.FastSetBlock(a_PlacePosition + CrossCoords[NeighborIdx], ChestBlockType, Meta); } - // Remove the "placed" item from inventory: - if (a_Player.IsGameModeSurvival()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } return true; } - -private: - cItemChestHandler(const cItemChestHandler &) = delete; }; -- cgit v1.2.3