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/ItemHandler.cpp | 344 ++++++++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 147 deletions(-) (limited to 'src/Items/ItemHandler.cpp') diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp index bfeba1373..1c6300353 100644 --- a/src/Items/ItemHandler.cpp +++ b/src/Items/ItemHandler.cpp @@ -8,6 +8,7 @@ #include "../Chunk.h" // Handlers: +#include "ItemAnvil.h" #include "ItemArmor.h" #include "ItemAxe.h" #include "ItemBanner.h" @@ -17,23 +18,34 @@ #include "ItemBottle.h" #include "ItemBow.h" #include "ItemBucket.h" +#include "ItemButton.h" #include "ItemChest.h" #include "ItemCloth.h" #include "ItemComparator.h" #include "ItemCookedFish.h" #include "ItemDoor.h" +#include "ItemDropSpenser.h" #include "ItemDye.h" #include "ItemEmptyMap.h" #include "ItemEnchantingTable.h" #include "ItemEndCrystal.h" +#include "ItemEnderchest.h" +#include "ItemEndPortalFrame.h" #include "ItemEyeOfEnder.h" +#include "ItemFenceGate.h" #include "ItemFishingRod.h" #include "ItemFood.h" #include "ItemFoodSeeds.h" +#include "ItemFurnace.h" +#include "ItemGlazedTerracotta.h" #include "ItemGoldenApple.h" #include "ItemHoe.h" +#include "ItemHopper.h" #include "ItemItemFrame.h" +#include "ItemJackOLantern.h" +#include "ItemLadder.h" #include "ItemLeaves.h" +#include "ItemLever.h" #include "ItemLighter.h" #include "ItemLilypad.h" #include "ItemMap.h" @@ -41,11 +53,16 @@ #include "ItemMinecart.h" #include "ItemMobHead.h" #include "ItemNetherWart.h" +#include "ItemObserver.h" #include "ItemPainting.h" #include "ItemPickaxe.h" +#include "ItemPiston.h" +#include "ItemPlanks.h" #include "ItemPoisonousPotato.h" #include "ItemPotion.h" #include "ItemPumpkin.h" +#include "ItemQuartz.h" +#include "ItemRail.h" #include "ItemRawChicken.h" #include "ItemRawFish.h" #include "ItemRedstoneDust.h" @@ -55,13 +72,20 @@ #include "ItemSeeds.h" #include "ItemShears.h" #include "ItemShovel.h" +#include "ItemSideways.h" #include "ItemSign.h" #include "ItemSlab.h" +#include "ItemSnow.h" #include "ItemSoup.h" #include "ItemSpawnEgg.h" #include "ItemSpiderEye.h" +#include "ItemStairs.h" #include "ItemSword.h" #include "ItemThrowable.h" +#include "ItemTorch.h" +#include "ItemTrapdoor.h" +#include "ItemTripwireHook.h" +#include "ItemVine.h" #include "../Blocks/BlockHandler.h" #include "SimplePlaceableItemHandler.h" @@ -113,56 +137,87 @@ cItemHandler * cItemHandler::CreateItemHandler(int a_ItemType) default: return new cItemHandler(a_ItemType); // Single item per handler, alphabetically sorted: - case E_ITEM_BANNER: return new cItemBannerHandler(a_ItemType); - case E_BLOCK_BIG_FLOWER: return new cItemBigFlowerHandler; - case E_BLOCK_CHEST: return new cItemChestHandler(a_ItemType); - case E_BLOCK_ENCHANTMENT_TABLE: return new cItemEnchantingTableHandler(a_ItemType); - case E_BLOCK_LEAVES: return new cItemLeavesHandler(a_ItemType); - case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType); - case E_BLOCK_HEAD: return new cItemMobHeadHandler(a_ItemType); - case E_BLOCK_NEW_LEAVES: return new cItemLeavesHandler(a_ItemType); - case E_BLOCK_PUMPKIN: return new cItemPumpkinHandler; - case E_BLOCK_PURPUR_SLAB: return new cItemSlabHandler(E_BLOCK_PURPUR_SLAB, E_BLOCK_PURPUR_DOUBLE_SLAB); - case E_BLOCK_RED_SANDSTONE_SLAB: return new cItemSlabHandler(E_BLOCK_RED_SANDSTONE_SLAB, E_BLOCK_DOUBLE_RED_SANDSTONE_SLAB); - case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType); - case E_BLOCK_STONE_SLAB: return new cItemSlabHandler(E_BLOCK_STONE_SLAB, E_BLOCK_DOUBLE_STONE_SLAB); - case E_BLOCK_TRAPPED_CHEST: return new cItemChestHandler(a_ItemType); - case E_BLOCK_WOODEN_SLAB: return new cItemSlabHandler(E_BLOCK_WOODEN_SLAB, E_BLOCK_DOUBLE_WOODEN_SLAB); - case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType); - case E_ITEM_BED: return new cItemBedHandler(a_ItemType); - case E_ITEM_BOTTLE_O_ENCHANTING: return new cItemBottleOEnchantingHandler(); - case E_ITEM_BOW: return new cItemBowHandler(); - case E_ITEM_BREWING_STAND: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_BREWING_STAND); - case E_ITEM_CAKE: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_CAKE); - case E_ITEM_CAULDRON: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_CAULDRON); - case E_ITEM_COMPARATOR: return new cItemComparatorHandler(a_ItemType); - case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType); - case E_ITEM_EGG: return new cItemEggHandler(); - case E_ITEM_EMPTY_MAP: return new cItemEmptyMapHandler(); - case E_ITEM_ENDER_PEARL: return new cItemEnderPearlHandler(); - case E_ITEM_END_CRYSTAL: return new cItemEndCrystalHandler(a_ItemType); - case E_ITEM_EYE_OF_ENDER: return new cItemEyeOfEnderHandler(); - case E_ITEM_FIRE_CHARGE: return new cItemLighterHandler(a_ItemType); - case E_ITEM_FIREWORK_ROCKET: return new cItemFireworkHandler(); - case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType); - case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType); - case E_ITEM_FLOWER_POT: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_FLOWER_POT); - case E_ITEM_GLASS_BOTTLE: return new cItemBottleHandler(); - case E_ITEM_MAP: return new cItemMapHandler(); - case E_ITEM_MILK: return new cItemMilkHandler(); - case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType); - case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType); - case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType); - case E_ITEM_POTIONS: return new cItemPotionHandler(); - case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType); - case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); - case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType); - case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType); - case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType); - case E_ITEM_SNOWBALL: return new cItemSnowballHandler(); - case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType); - case E_ITEM_STRING: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_TRIPWIRE); - case E_ITEM_SUGARCANE: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_SUGARCANE); + case E_BLOCK_ACTIVATOR_RAIL: return new cItemRailHandler(a_ItemType); + case E_BLOCK_ANVIL: return new cItemAnvilHandler(a_ItemType); + case E_BLOCK_BIG_FLOWER: return new cItemBigFlowerHandler; + case E_BLOCK_CHEST: return new cItemChestHandler(a_ItemType); + case E_BLOCK_DETECTOR_RAIL: return new cItemRailHandler(a_ItemType); + case E_BLOCK_DISPENSER: return new cItemDropSpenserHandler(a_ItemType); + case E_BLOCK_DROPPER: return new cItemDropSpenserHandler(a_ItemType); + case E_BLOCK_ENCHANTMENT_TABLE: return new cItemEnchantingTableHandler(a_ItemType); + case E_BLOCK_ENDER_CHEST: return new cItemEnderchestHandler(a_ItemType); + case E_BLOCK_END_PORTAL_FRAME: return new cItemEndPortalFrameHandler(a_ItemType); + case E_BLOCK_FURNACE: return new cItemFurnaceHandler(a_ItemType); + case E_BLOCK_HAY_BALE: return new cItemSidewaysHandler(a_ItemType); + case E_BLOCK_HEAD: return new cItemMobHeadHandler(a_ItemType); + case E_BLOCK_HOPPER: return new cItemHopperHandler(a_ItemType); + case E_BLOCK_IRON_TRAPDOOR: return new cItemTrapdoorHandler(a_ItemType); + case E_BLOCK_JACK_O_LANTERN: return new cItemJackOLanternHandler(a_ItemType); + case E_BLOCK_LADDER: return new cItemLadderHandler(a_ItemType); + case E_BLOCK_LEAVES: return new cItemLeavesHandler(a_ItemType); + case E_BLOCK_LEVER: return new cItemLeverHandler(a_ItemType); + case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType); + case E_BLOCK_LOG: return new cItemSidewaysHandler(a_ItemType); + case E_BLOCK_NEW_LEAVES: return new cItemLeavesHandler(a_ItemType); + case E_BLOCK_NEW_LOG: return new cItemSidewaysHandler(a_ItemType); + case E_BLOCK_OBSERVER: return new cItemObserverHandler(a_ItemType); + case E_BLOCK_PISTON: return new cItemPistonHandler(a_ItemType); + case E_BLOCK_PLANKS: return new cItemPlanksHandler(a_ItemType); + case E_BLOCK_POWERED_RAIL: return new cItemRailHandler(a_ItemType); + case E_BLOCK_PUMPKIN: return new cItemPumpkinHandler(a_ItemType); + case E_BLOCK_PURPUR_SLAB: return new cItemSlabHandler(a_ItemType); + case E_BLOCK_QUARTZ_BLOCK: return new cItemQuartzHandler(a_ItemType); + case E_BLOCK_RAIL: return new cItemRailHandler(a_ItemType); + case E_BLOCK_REDSTONE_TORCH_ON: return new cItemTorchHandler(a_ItemType); + case E_BLOCK_RED_SANDSTONE_SLAB: return new cItemSlabHandler(a_ItemType); + case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType); + case E_BLOCK_SNOW: return new cItemSnowHandler(a_ItemType); + case E_BLOCK_STICKY_PISTON: return new cItemPistonHandler(a_ItemType); + case E_BLOCK_STONE_BUTTON: return new cItemButtonHandler(a_ItemType); + case E_BLOCK_STONE_SLAB: return new cItemSlabHandler(a_ItemType); + case E_BLOCK_TORCH: return new cItemTorchHandler(a_ItemType); + case E_BLOCK_TRAPDOOR: return new cItemTrapdoorHandler(a_ItemType); + case E_BLOCK_TRAPPED_CHEST: return new cItemChestHandler(a_ItemType); + case E_BLOCK_TRIPWIRE_HOOK: return new cItemTripwireHookHandler(a_ItemType); + case E_BLOCK_VINES: return new cItemVineHandler(a_ItemType); + case E_BLOCK_WOODEN_BUTTON: return new cItemButtonHandler(a_ItemType); + case E_BLOCK_WOODEN_SLAB: return new cItemSlabHandler(a_ItemType); + case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType); + case E_ITEM_BANNER: return new cItemBannerHandler(a_ItemType); + case E_ITEM_BED: return new cItemBedHandler(a_ItemType); + case E_ITEM_BOTTLE_O_ENCHANTING: return new cItemBottleOEnchantingHandler(); + case E_ITEM_BOW: return new cItemBowHandler(); + case E_ITEM_BREWING_STAND: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_BREWING_STAND); + case E_ITEM_CAKE: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_CAKE); + case E_ITEM_CAULDRON: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_CAULDRON); + case E_ITEM_COMPARATOR: return new cItemComparatorHandler(a_ItemType); + case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType); + case E_ITEM_EGG: return new cItemEggHandler(); + case E_ITEM_EMPTY_MAP: return new cItemEmptyMapHandler(); + case E_ITEM_ENDER_PEARL: return new cItemEnderPearlHandler(); + case E_ITEM_END_CRYSTAL: return new cItemEndCrystalHandler(a_ItemType); + case E_ITEM_EYE_OF_ENDER: return new cItemEyeOfEnderHandler(); + case E_ITEM_FIREWORK_ROCKET: return new cItemFireworkHandler(); + case E_ITEM_FIRE_CHARGE: return new cItemLighterHandler(a_ItemType); + case E_ITEM_FISHING_ROD: return new cItemFishingRodHandler(a_ItemType); + case E_ITEM_FLINT_AND_STEEL: return new cItemLighterHandler(a_ItemType); + case E_ITEM_FLOWER_POT: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_FLOWER_POT); + case E_ITEM_GLASS_BOTTLE: return new cItemBottleHandler(); + case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType); + case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType); + case E_ITEM_MAP: return new cItemMapHandler(); + case E_ITEM_MILK: return new cItemMilkHandler(); + case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType); + case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType); + case E_ITEM_POTIONS: return new cItemPotionHandler(); + case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType); + case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType); + case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType); + case E_ITEM_SIGN: return new cItemSignHandler(a_ItemType); + case E_ITEM_SNOWBALL: return new cItemSnowballHandler(); + case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType); + case E_ITEM_STRING: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_TRIPWIRE); + case E_ITEM_SUGARCANE: return new cSimplePlaceableItemHandler(a_ItemType, E_BLOCK_SUGARCANE); case E_ITEM_WOODEN_HOE: case E_ITEM_STONE_HOE: @@ -247,6 +302,54 @@ cItemHandler * cItemHandler::CreateItemHandler(int a_ItemType) return new cItemMinecartHandler(a_ItemType); } + case E_BLOCK_ACACIA_FENCE_GATE: + case E_BLOCK_BIRCH_FENCE_GATE: + case E_BLOCK_DARK_OAK_FENCE_GATE: + case E_BLOCK_JUNGLE_FENCE_GATE: + case E_BLOCK_OAK_FENCE_GATE: + case E_BLOCK_SPRUCE_FENCE_GATE: + { + return new cItemFenceGateHandler(a_ItemType); + } + + case E_BLOCK_ACACIA_WOOD_STAIRS: + case E_BLOCK_BIRCH_WOOD_STAIRS: + case E_BLOCK_BRICK_STAIRS: + case E_BLOCK_COBBLESTONE_STAIRS: + case E_BLOCK_DARK_OAK_WOOD_STAIRS: + case E_BLOCK_JUNGLE_WOOD_STAIRS: + case E_BLOCK_NETHER_BRICK_STAIRS: + case E_BLOCK_OAK_WOOD_STAIRS: + case E_BLOCK_PURPUR_STAIRS: + case E_BLOCK_QUARTZ_STAIRS: + case E_BLOCK_RED_SANDSTONE_STAIRS: + case E_BLOCK_SANDSTONE_STAIRS: + case E_BLOCK_SPRUCE_WOOD_STAIRS: + case E_BLOCK_STONE_BRICK_STAIRS: + { + return new cItemStairsHandler(a_ItemType); + } + + case E_BLOCK_WHITE_GLAZED_TERRACOTTA: + case E_BLOCK_ORANGE_GLAZED_TERRACOTTA: + case E_BLOCK_MAGENTA_GLAZED_TERRACOTTA: + case E_BLOCK_LIGHT_BLUE_GLAZED_TERRACOTTA: + case E_BLOCK_YELLOW_GLAZED_TERRACOTTA: + case E_BLOCK_LIME_GLAZED_TERRACOTTA: + case E_BLOCK_PINK_GLAZED_TERRACOTTA: + case E_BLOCK_GRAY_GLAZED_TERRACOTTA: + case E_BLOCK_LIGHT_GRAY_GLAZED_TERRACOTTA: + case E_BLOCK_CYAN_GLAZED_TERRACOTTA: + case E_BLOCK_PURPLE_GLAZED_TERRACOTTA: + case E_BLOCK_BLUE_GLAZED_TERRACOTTA: + case E_BLOCK_BROWN_GLAZED_TERRACOTTA: + case E_BLOCK_GREEN_GLAZED_TERRACOTTA: + case E_BLOCK_RED_GLAZED_TERRACOTTA: + case E_BLOCK_BLACK_GLAZED_TERRACOTTA: + { + return new cItemGlazedTerracottaHandler(a_ItemType); + } + // Food (please keep alpha-sorted): case E_ITEM_BAKED_POTATO: return new cItemFoodHandler(a_ItemType, FoodInfo(5, 6)); case E_ITEM_BEETROOT: return new cItemFoodHandler(a_ItemType, FoodInfo(1, 1.2)); @@ -347,84 +450,66 @@ cItemHandler::cItemHandler(int a_ItemType) -bool cItemHandler::OnPlayerPlace( - cWorld & a_World, - cPlayer & a_Player, - const cItem & a_EquippedItem, - const Vector3i a_ClickedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos -) +void cItemHandler::OnPlayerPlace(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_ClickedBlockPosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) { if (a_ClickedBlockFace == BLOCK_FACE_NONE) { // Clicked in the air, no placement possible - return false; + return; } - if (!cChunkDef::IsValidHeight(a_ClickedBlockPos.y)) + if (!cChunkDef::IsValidHeight(a_ClickedBlockPosition.y)) { - // The clicked block is outside the world, ignore this call altogether (#128) - return false; + // The clicked block is outside the world, ignore this call altogether (GH #128): + return; } + const auto & World = *a_Player.GetWorld(); BLOCKTYPE ClickedBlockType; NIBBLETYPE ClickedBlockMeta; - - a_World.GetBlockTypeMeta(a_ClickedBlockPos, ClickedBlockType, ClickedBlockMeta); - cChunkInterface ChunkInterface(a_World.GetChunkMap()); + World.GetBlockTypeMeta(a_ClickedBlockPosition, ClickedBlockType, ClickedBlockMeta); // Check if the block ignores build collision (water, grass etc.): - auto PlacedBlockPos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace); - if (cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(ChunkInterface, a_ClickedBlockPos, a_Player, ClickedBlockMeta)) + if (cBlockHandler::For(ClickedBlockType).DoesIgnoreBuildCollision(World, a_HeldItem, a_ClickedBlockPosition, ClickedBlockMeta, a_ClickedBlockFace, true)) { - // Replace the clicked block: - a_World.DropBlockAsPickups(a_ClickedBlockPos, &a_Player, nullptr); - PlacedBlockPos = a_ClickedBlockPos; + // Try to place the block at the clicked position: + if (!CommitPlacement(a_Player, a_HeldItem, a_ClickedBlockPosition, a_ClickedBlockFace, a_CursorPosition)) + { + // The placement failed, the blocks have already been re-sent, re-send inventory: + a_Player.GetInventory().SendEquippedSlot(); + return; + } } else { - if (!cChunkDef::IsValidHeight(PlacedBlockPos.y)) + const auto PlacedPosition = AddFaceDirection(a_ClickedBlockPosition, a_ClickedBlockFace); + + if (!cChunkDef::IsValidHeight(PlacedPosition.y)) { - // The block is being placed outside the world, ignore this packet altogether (#128) - return false; + // The block is being placed outside the world, ignore this packet altogether (GH #128): + return; } NIBBLETYPE PlaceMeta; BLOCKTYPE PlaceBlock; - a_World.GetBlockTypeMeta(PlacedBlockPos, PlaceBlock, PlaceMeta); + World.GetBlockTypeMeta(PlacedPosition, 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 (!cBlockHandler::For(PlaceBlock).DoesIgnoreBuildCollision(ChunkInterface, PlacedBlockPos, a_Player, PlaceMeta)) + if (!cBlockHandler::For(PlaceBlock).DoesIgnoreBuildCollision(World, a_HeldItem, PlacedPosition, PlaceMeta, a_ClickedBlockFace, false)) { // 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; + return; } - } - // Get all the blocks to place: - sSetBlockVector blocks; - if (!GetBlocksToPlace(a_World, a_Player, a_EquippedItem, PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, blocks)) - { - // Handler refused the placement, send that information back to the client: - for (const auto & blk: blocks) + // Try to place the block: + if (!CommitPlacement(a_Player, a_HeldItem, PlacedPosition, a_ClickedBlockFace, a_CursorPosition)) { - const auto & AbsPos = blk.GetAbsolutePos(); - a_World.SendBlockTo(AbsPos, a_Player); + // The placement failed, the blocks have already been re-sent, re-send inventory: + a_Player.GetInventory().SendEquippedSlot(); + return; } - a_World.SendBlockTo(PlacedBlockPos, a_Player); - a_Player.GetInventory().SendEquippedSlot(); - return false; - } - - // Try to place the blocks: - if (!a_Player.PlaceBlocks(blocks)) - { - // The placement failed, the blocks have already been re-sent, re-send inventory: - a_Player.GetInventory().SendEquippedSlot(); - return false; } // Remove the "placed" item: @@ -432,29 +517,6 @@ bool cItemHandler::OnPlayerPlace( { a_Player.GetInventory().RemoveOneEquippedItem(); } - return true; -} - - - - - -bool cItemHandler::GetBlocksToPlace( - cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem, - const Vector3i a_PlacedBlockPos, - eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - sSetBlockVector & a_BlocksToSet -) -{ - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!GetPlacementBlockTypeMeta(&a_World, &a_Player, a_PlacedBlockPos, a_ClickedBlockFace, a_CursorPos, BlockType, BlockMeta)) - { - return false; - } - a_BlocksToSet.emplace_back(a_PlacedBlockPos, BlockType, BlockMeta); - return true; } @@ -821,34 +883,6 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType) -bool cItemHandler::GetPlacementBlockTypeMeta( - cWorld * a_World, cPlayer * a_Player, - const Vector3i a_PlacedBlockPos, eBlockFace a_ClickedBlockFace, - const Vector3i a_CursorPos, - BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta -) -{ - ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers - - if (m_ItemType >= 256) - { - LOGERROR("%s: Item %d is not eligible for direct block placement!", __FUNCTION__, m_ItemType); - return false; - } - - cChunkInterface ChunkInterface(a_World->GetChunkMap()); - return cBlockHandler::For(static_cast(m_ItemType)).GetPlacementBlockTypeMeta( - ChunkInterface, *a_Player, - a_PlacedBlockPos, a_ClickedBlockFace, - a_CursorPos, - a_BlockType, a_BlockMeta - ); -} - - - - - bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item) { auto FoodInfo = GetFoodInfo(a_Item); @@ -873,3 +907,19 @@ float cItemHandler::GetBlockBreakingStrength(BLOCKTYPE a_Block) { return 1.0f; } + + + + + +bool cItemHandler::CommitPlacement(cPlayer & a_Player, const cItem & a_HeldItem, const Vector3i a_PlacePosition, const eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPosition) +{ + ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers. + + // By default, all blocks can be placed and the meta is copied over from the item's damage value: + return a_Player.PlaceBlock( + a_PlacePosition, + static_cast(m_ItemType), + static_cast(a_HeldItem.m_ItemDamage & 0x0f) + ); +} -- cgit v1.2.3