diff options
Diffstat (limited to 'src/Items/ItemChest.h')
-rw-r--r-- | src/Items/ItemChest.h | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/src/Items/ItemChest.h b/src/Items/ItemChest.h index b8807e5d8..014ccc3e6 100644 --- a/src/Items/ItemChest.h +++ b/src/Items/ItemChest.h @@ -25,56 +25,57 @@ public: /** 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, - int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, - int a_CursorX, int a_CursorY, int a_CursorZ + cWorld & a_World, + cPlayer & a_Player, + const cItem & a_EquippedItem, + const Vector3i a_ClickedBlockPos, + eBlockFace a_ClickedBlockFace, + const Vector3i a_CursorPos ) override { - if (a_BlockFace < 0) + if (a_ClickedBlockFace < 0) { // Clicked in air return false; } - if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) + 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 clickedBlock; - NIBBLETYPE clickedBlockMeta; - Vector3i blockPos(a_BlockX, a_BlockY, a_BlockZ); - a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, clickedBlock, clickedBlockMeta); + BLOCKTYPE ClickedBlockType; + NIBBLETYPE ClickedBlockMeta; + a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); cChunkInterface ChunkInterface(a_World.GetChunkMap()); - auto blockHandler = BlockHandler(clickedBlock); - if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, blockPos, a_Player, clickedBlockMeta)) + auto blockHandler = BlockHandler(ClickedBlockType); + Vector3i PlacePos; + if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta)) { - blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, blockPos); + blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, a_ClickedBlockPos); + PlacePos = a_ClickedBlockPos; } else { - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height)) + 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; } - NIBBLETYPE PlaceMeta; + // Check if the chest can overwrite the block at PlacePos: BLOCKTYPE PlaceBlock; - a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta); - - // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed. - // No need to do combinability (dblslab) checks, client will do that here. - if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, blockPos, a_Player, clickedBlockMeta)) + NIBBLETYPE PlaceMeta; + a_World.GetBlockTypeMeta(PlacePos, PlaceBlock, PlaceMeta); + blockHandler = BlockHandler(PlaceBlock); + if (!blockHandler->DoesIgnoreBuildCollision(ChunkInterface, PlacePos, a_Player, PlaceMeta)) { - // Tried to place a block into another? - // Happens when you place a block aiming at side of block with a torch on it or stem beside it return false; } + blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, PlacePos); } // Check that there is at most one single neighbor of the same chest type: @@ -88,7 +89,8 @@ public: int NeighborIdx = -1; for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++) { - if (a_World.GetBlock(a_BlockX + CrossCoords[i].x, a_BlockY, a_BlockZ + CrossCoords[i].z) != m_ItemType) + auto NeighborPos = PlacePos + CrossCoords[i]; + if (a_World.GetBlock(NeighborPos) != m_ItemType) { continue; } @@ -100,12 +102,11 @@ public: NeighborIdx = static_cast<int>(i); // Check that this neighbor is a single chest: - int bx = a_BlockX + CrossCoords[i].x; - int bz = a_BlockZ + CrossCoords[i].z; for (size_t j = 0; j < ARRAYCOUNT(CrossCoords); j++) { - if (a_World.GetBlock(bx + CrossCoords[j].x, a_BlockY, bz + CrossCoords[j].z) == m_ItemType) + if (a_World.GetBlock(NeighborPos + CrossCoords[j]) == m_ItemType) { + // Trying to place next to a dblchest return false; } } // for j @@ -133,13 +134,14 @@ public: } default: { + // No neighbor, place based on yaw: Meta = cBlockChestHandler::PlayerYawToMetaData(yaw); break; } } // switch (NeighborIdx) // Place the new chest: - if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, ChestBlockType, Meta)) + if (!a_Player.PlaceBlock(PlacePos.x, PlacePos.y, PlacePos.z, ChestBlockType, Meta)) { return false; } @@ -147,10 +149,10 @@ public: // Adjust the existing chest, if any: if (NeighborIdx != -1) { - a_World.FastSetBlock(a_BlockX + CrossCoords[NeighborIdx].x, a_BlockY, a_BlockZ + CrossCoords[NeighborIdx].z, ChestBlockType, Meta); + a_World.FastSetBlock(PlacePos + CrossCoords[NeighborIdx], ChestBlockType, Meta); } - // Remove the "placed" item: + // Remove the "placed" item from inventory: if (a_Player.IsGameModeSurvival()) { a_Player.GetInventory().RemoveOneEquippedItem(); |