summaryrefslogtreecommitdiffstats
path: root/src/Items
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items')
-rw-r--r--src/Items/CMakeLists.txt4
-rw-r--r--src/Items/ItemBed.h15
-rw-r--r--src/Items/ItemBigFlower.h15
-rw-r--r--src/Items/ItemBow.h11
-rw-r--r--src/Items/ItemBucket.h20
-rw-r--r--src/Items/ItemChest.h75
-rw-r--r--src/Items/ItemDoor.h13
-rw-r--r--src/Items/ItemDye.h2
-rw-r--r--src/Items/ItemEmptyMap.h2
-rw-r--r--src/Items/ItemHandler.cpp71
-rw-r--r--src/Items/ItemHandler.h20
-rw-r--r--src/Items/ItemMobHead.h33
-rw-r--r--src/Items/ItemMushroomSoup.h2
-rw-r--r--src/Items/ItemSign.h2
14 files changed, 190 insertions, 95 deletions
diff --git a/src/Items/CMakeLists.txt b/src/Items/CMakeLists.txt
index c50ddb372..71f2d9ceb 100644
--- a/src/Items/CMakeLists.txt
+++ b/src/Items/CMakeLists.txt
@@ -56,6 +56,10 @@ SET (HDRS
ItemThrowable.h
)
+if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ set_source_files_properties(ItemHandler.cpp PROPERTIES COMPILE_FLAGS "-Wno-error=sign-conversion -Wno-error=conversion -Wno-error=old-style-cast -Wno-error=switch-enum")
+endif()
+
if(NOT MSVC)
add_library(Items ${SRCS} ${HDRS})
endif()
diff --git a/src/Items/ItemBed.h b/src/Items/ItemBed.h
index 77d51d744..15b924a08 100644
--- a/src/Items/ItemBed.h
+++ b/src/Items/ItemBed.h
@@ -25,10 +25,11 @@ public:
}
- virtual bool OnPlayerPlace(
+ virtual bool GetBlocksToPlace(
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
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ sSetBlockVector & a_BlocksToPlace
) override
{
// Can only be placed on the floor:
@@ -36,12 +37,10 @@ public:
{
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// The "foot" block:
- sSetBlockVector blks;
NIBBLETYPE BlockMeta = cBlockBedHandler::RotationToMetaData(a_Player.GetYaw());
- blks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BED, BlockMeta);
+ a_BlocksToPlace.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BED, BlockMeta);
// Check if there is empty space for the "head" block:
// (Vanilla only allows beds to be placed into air)
@@ -50,10 +49,8 @@ public:
{
return false;
}
- blks.emplace_back(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, BlockMeta | 0x08);
-
- // Place both bed blocks:
- return a_Player.PlaceBlocks(blks);
+ a_BlocksToPlace.emplace_back(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, BlockMeta | 0x08);
+ return true;
}
} ;
diff --git a/src/Items/ItemBigFlower.h b/src/Items/ItemBigFlower.h
index 4341a1a17..a052485e4 100644
--- a/src/Items/ItemBigFlower.h
+++ b/src/Items/ItemBigFlower.h
@@ -27,10 +27,11 @@ public:
}
- virtual bool OnPlayerPlace(
+ virtual bool GetBlocksToPlace(
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
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ sSetBlockVector & a_BlocksToSet
) override
{
// Can only be placed on the floor:
@@ -38,16 +39,14 @@ public:
{
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- // Place both blocks atomically:
- sSetBlockVector blks;
- blks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BIG_FLOWER, a_EquippedItem.m_ItemDamage & 0x07);
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+ a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BIG_FLOWER, a_EquippedItem.m_ItemDamage & 0x07);
if (a_BlockY < cChunkDef::Height - 1)
{
- blks.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_BIG_FLOWER, (a_EquippedItem.m_ItemDamage & 0x07) | 0x08);
+ a_BlocksToSet.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_BIG_FLOWER, (a_EquippedItem.m_ItemDamage & 0x07) | 0x08);
}
- return a_Player.PlaceBlocks(blks);
+ return true;
}
};
diff --git a/src/Items/ItemBow.h b/src/Items/ItemBow.h
index 5164ddf59..8bbaa3d8c 100644
--- a/src/Items/ItemBow.h
+++ b/src/Items/ItemBow.h
@@ -53,7 +53,7 @@ public:
ASSERT(a_Player != nullptr);
int BowCharge = a_Player->FinishChargingBow();
- double Force = (double)BowCharge / 20.0;
+ double Force = static_cast<double>(BowCharge) / 20.0;
Force = (Force * Force + 2.0 * Force) / 3.0; // This formula is used by the 1.6.2 client
if (Force < 0.1)
{
@@ -80,7 +80,14 @@ public:
Arrow = nullptr;
return;
}
- a_Player->GetWorld()->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY(), a_Player->GetPosZ(), 0.5, (float)Force);
+ a_Player->GetWorld()->BroadcastSoundEffect(
+ "random.bow",
+ a_Player->GetPosX(),
+ a_Player->GetPosY(),
+ a_Player->GetPosZ(),
+ 0.5,
+ static_cast<float>(Force)
+ );
if (!a_Player->IsGameModeCreative())
{
if (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchInfinity) == 0)
diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h
index 015720415..4d39bde82 100644
--- a/src/Items/ItemBucket.h
+++ b/src/Items/ItemBucket.h
@@ -80,6 +80,13 @@ public:
return false;
}
+ // Check to see if destination block is too far away
+ // Reach Distance Multiplayer = 5 Blocks
+ if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
+ {
+ return false;
+ }
+
// Remove water / lava block (unless plugins disagree)
if (!a_Player->PlaceBlock(BlockPos.x, BlockPos.y, BlockPos.z, E_BLOCK_AIR, 0))
{
@@ -96,7 +103,7 @@ public:
ASSERT(!"Inventory bucket mismatch");
return true;
}
- if (a_Player->GetInventory().AddItem(cItem(NewItem), true, true) != 1)
+ if (a_Player->GetInventory().AddItem(cItem(NewItem)) != 1)
{
// The bucket didn't fit, toss it as a pickup:
a_Player->TossPickup(cItem(NewItem));
@@ -126,6 +133,13 @@ public:
{
return false;
}
+
+ // Check to see if destination block is too far away
+ // Reach Distance Multiplayer = 5 Blocks
+ if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
+ {
+ return false;
+ }
if (a_Player->GetGameMode() != gmCreative)
{
@@ -137,7 +151,7 @@ public:
return false;
}
cItem Item(E_ITEM_BUCKET, 1);
- if (!a_Player->GetInventory().AddItem(Item, true, true))
+ if (!a_Player->GetInventory().AddItem(Item))
{
return false;
}
@@ -236,7 +250,7 @@ public:
m_EntryFace = static_cast<eBlockFace>(a_CBEntryFace);
if (!cFluidSimulator::CanWashAway(a_CBBlockType) && !IsBlockLiquid(a_CBBlockType))
{
- AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, (eBlockFace)a_CBEntryFace); // Was an unwashawayable block, can't overwrite it!
+ AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, static_cast<eBlockFace>(a_CBEntryFace)); // Was an unwashawayable block, can't overwrite it!
}
m_Pos.Set(a_CBBlockX, a_CBBlockY, a_CBBlockZ); // (Block could be washed away, replace it)
return true; // Abort tracing
diff --git a/src/Items/ItemChest.h b/src/Items/ItemChest.h
index 1d23975cd..3dd112c91 100644
--- a/src/Items/ItemChest.h
+++ b/src/Items/ItemChest.h
@@ -27,6 +27,8 @@ 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,
@@ -118,34 +120,32 @@ public:
} // for j
} // for i
- // If there's no chest neighbor, place the single block chest and bail out:
+ // Get the meta of the placed chest; take existing neighbors into account:
BLOCKTYPE ChestBlockType = static_cast<BLOCKTYPE>(m_ItemType);
- if (NeighborIdx < 0)
+ NIBBLETYPE Meta;
+ auto yaw = a_Player.GetYaw();
+ switch (NeighborIdx)
{
- NIBBLETYPE Meta = cBlockChestHandler::PlayerYawToMetaData(a_Player.GetYaw());
- return a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, ChestBlockType, Meta);
- }
-
- // There is a neighbor to which we need to adjust
- double yaw = a_Player.GetYaw();
- if ((NeighborIdx == 0) || (NeighborIdx == 2))
- {
- // The neighbor is in the X axis, form a X-axis-aligned dblchest:
- NIBBLETYPE Meta = ((yaw >= -90) && (yaw < 90)) ? E_META_CHEST_FACING_ZM : E_META_CHEST_FACING_ZP;
-
- // Place the new chest:
- if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, ChestBlockType, Meta))
+ case 0:
+ case 2:
{
- return false;
+ // The neighbor is in the X axis, form a X-axis-aligned dblchest:
+ Meta = ((yaw >= -90) && (yaw < 90)) ? E_META_CHEST_FACING_ZM : E_META_CHEST_FACING_ZP;
+ break;
}
-
- // Adjust the existing chest:
- a_World.FastSetBlock(a_BlockX + CrossCoords[NeighborIdx].x, a_BlockY, a_BlockZ + CrossCoords[NeighborIdx].z, ChestBlockType, Meta);
- return true;
- }
-
- // The neighbor is in the Z axis, form a Z-axis-aligned dblchest:
- NIBBLETYPE Meta = (yaw < 0) ? E_META_CHEST_FACING_XM : E_META_CHEST_FACING_XP;
+ case 1:
+ case 3:
+ {
+ // The neighbor is in the Z axis, form a Z-axis-aligned dblchest:
+ Meta = (yaw < 0) ? E_META_CHEST_FACING_XM : E_META_CHEST_FACING_XP;
+ break;
+ }
+ default:
+ {
+ Meta = cBlockChestHandler::PlayerYawToMetaData(yaw);
+ break;
+ }
+ } // switch (NeighborIdx)
// Place the new chest:
if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, ChestBlockType, Meta))
@@ -153,8 +153,31 @@ public:
return false;
}
- // Adjust the existing chest:
- a_World.FastSetBlock(a_BlockX + CrossCoords[NeighborIdx].x, a_BlockY, a_BlockZ + CrossCoords[NeighborIdx].z, ChestBlockType, Meta);
+ // Adjust the existing chest, if any:
+ if (NeighborIdx > 0)
+ {
+ a_World.FastSetBlock(a_BlockX + CrossCoords[NeighborIdx].x, a_BlockY, a_BlockZ + CrossCoords[NeighborIdx].z, ChestBlockType, Meta);
+ }
+
+ // Play the placement sound:
+ AString PlaceSound = cBlockInfo::GetPlaceSound(ChestBlockType);
+ float Volume = 1.0f, Pitch = 0.8f;
+ if (PlaceSound == "dig.metal")
+ {
+ Pitch = 1.2f;
+ PlaceSound = "dig.stone";
+ }
+ else if (PlaceSound == "random.anvil_land")
+ {
+ Volume = 0.65f;
+ }
+ a_World.BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
+
+ // Remove the "placed" item:
+ if (a_Player.IsGameModeSurvival())
+ {
+ a_Player.GetInventory().RemoveOneEquippedItem();
+ }
return true;
}
diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h
index ddd3d4e20..e92c567fb 100644
--- a/src/Items/ItemDoor.h
+++ b/src/Items/ItemDoor.h
@@ -20,10 +20,11 @@ public:
}
- virtual bool OnPlayerPlace(
+ virtual bool GetBlocksToPlace(
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
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ sSetBlockVector & a_BlocksToSet
) override
{
// Vanilla only allows door placement while clicking on the top face of the block below the door:
@@ -31,7 +32,6 @@ public:
{
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// Door (bottom block) can be placed in Y range of [1, 254]:
if ((a_BlockY < 1) || (a_BlockY >= cChunkDef::Height - 2))
@@ -107,10 +107,9 @@ public:
}
// Set the blocks:
- sSetBlockVector blks;
- blks.emplace_back(a_BlockX, a_BlockY, a_BlockZ, BlockType, LowerBlockMeta);
- blks.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, BlockType, UpperBlockMeta);
- return a_Player.PlaceBlocks(blks);
+ a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, BlockType, LowerBlockMeta);
+ a_BlocksToSet.emplace_back(a_BlockX, a_BlockY + 1, a_BlockZ, BlockType, UpperBlockMeta);
+ return true;
}
diff --git a/src/Items/ItemDye.h b/src/Items/ItemDye.h
index 273af826a..c2635bcb6 100644
--- a/src/Items/ItemDye.h
+++ b/src/Items/ItemDye.h
@@ -27,7 +27,7 @@ public:
) override
{
// Handle growing the plants:
- if (a_Item.m_ItemDamage == E_META_DYE_WHITE)
+ if ((a_Item.m_ItemDamage == E_META_DYE_WHITE) && (a_BlockFace != BLOCK_FACE_NONE))
{
if (a_World->GrowRipePlant(a_BlockX, a_BlockY, a_BlockZ, true))
{
diff --git a/src/Items/ItemEmptyMap.h b/src/Items/ItemEmptyMap.h
index 6e944b4da..fba8c0a2c 100644
--- a/src/Items/ItemEmptyMap.h
+++ b/src/Items/ItemEmptyMap.h
@@ -60,7 +60,7 @@ public:
return true;
}
- a_Player->GetInventory().AddItem(cItem(E_ITEM_MAP, 1, (short)(NewMap->GetID() & 0x7fff)), true, true);
+ a_Player->GetInventory().AddItem(cItem(E_ITEM_MAP, 1, (short)(NewMap->GetID() & 0x7fff)));
return true;
}
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index b7f89809e..a1fa67152 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -367,37 +367,51 @@ bool cItemHandler::OnPlayerPlace(
return false;
}
}
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!GetPlacementBlockTypeMeta(&a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
+
+ // Get all the blocks to place:
+ sSetBlockVector blocks;
+ if (!GetBlocksToPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, blocks))
{
// Handler refused the placement, send that information back to the client:
+ for (const auto & blk: blocks)
+ {
+ a_World.SendBlockTo(blk.GetX(), blk.GetY(), blk.GetZ(), &a_Player);
+ }
a_World.SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, &a_Player);
a_Player.GetInventory().SendEquippedSlot();
return false;
}
- if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta))
+ // Try to place the blocks:
+ if (!a_Player.PlaceBlocks(blocks))
{
- // The placement failed, the block has already been re-sent, re-send inventory:
+ // The placement failed, the blocks have already been re-sent, re-send inventory:
a_Player.GetInventory().SendEquippedSlot();
return false;
}
- AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType);
- float Volume = 1.0f, Pitch = 0.8f;
- if (PlaceSound == "dig.metal")
- {
- Pitch = 1.2f;
- PlaceSound = "dig.stone";
- }
- else if (PlaceSound == "random.anvil_land")
+ // Play the placement sound for the main block:
+ for (const auto & blk: blocks)
{
- Volume = 0.65f;
- }
-
- a_World.BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
+ // Find the main block by comparing the coords:
+ if ((blk.GetX() != a_BlockX) || (blk.GetY() != a_BlockY) || (blk.GetZ() != a_BlockZ))
+ {
+ continue;
+ }
+ AString PlaceSound = cBlockInfo::GetPlaceSound(blk.m_BlockType);
+ float Volume = 1.0f, Pitch = 0.8f;
+ if (PlaceSound == "dig.metal")
+ {
+ Pitch = 1.2f;
+ PlaceSound = "dig.stone";
+ }
+ else if (PlaceSound == "random.anvil_land")
+ {
+ Volume = 0.65f;
+ }
+ a_World.BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
+ break;
+ } // for blk - blocks[]
// Remove the "placed" item:
if (a_Player.IsGameModeSurvival())
@@ -411,6 +425,27 @@ bool cItemHandler::OnPlayerPlace(
+bool cItemHandler::GetBlocksToPlace(
+ 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,
+ sSetBlockVector & a_BlocksToSet
+)
+{
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ if (!GetPlacementBlockTypeMeta(&a_World, &a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
+ {
+ return false;
+ }
+ a_BlocksToSet.emplace_back(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
+ return true;
+}
+
+
+
+
+
bool cItemHandler::OnItemUse(
cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index ec88aeb99..684b55788 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -35,8 +35,9 @@ public:
/** Called when the player tries to place the item (right mouse button, IsPlaceable() == true).
- The default handler uses GetPlacementBlockTypeMeta and places the returned block.
- Override this function for advanced behavior such as placing multiple blocks.
+ The block coords are for the block that has been clicked.
+ The default handler uses GetBlocksToPlace() and places the returned blocks.
+ Override if the item needs advanced processing, such as spawning a mob based on the blocks being placed.
If the block placement is refused inside this call, it will automatically revert the client-side changes.
Returns true if the placement succeeded, false if the placement was aborted for any reason. */
virtual bool OnPlayerPlace(
@@ -46,7 +47,20 @@ public:
);
- /** Called when the player right-clicks with this item and IsPlaceable() == true, and OnPlace() is not overridden.
+ /** Called from OnPlayerPlace() to determine the blocks that the current placement operation should set.
+ The block coords are where the new (main) block should be placed.
+ The default handler uses GetPlacementBlockTypeMeta() and provides that as the single block at the specified coords.
+ Returns true if the placement succeeded, false if the placement was aborted for any reason.
+ If aborted, the server then sends all original blocks in the coords provided in a_BlocksToSet to the client. */
+ virtual bool GetBlocksToPlace(
+ 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,
+ sSetBlockVector & a_BlocksToSet
+ );
+
+
+ /** Called when the player right-clicks with this item and IsPlaceable() == true, and OnPlayerPlace() is not overridden.
This function should provide the block type and meta for the placed block, or refuse the placement.
Returns true to allow placement, false to refuse. */
virtual bool GetPlacementBlockTypeMeta(
diff --git a/src/Items/ItemMobHead.h b/src/Items/ItemMobHead.h
index 8780f7e4b..9a4044bc0 100644
--- a/src/Items/ItemMobHead.h
+++ b/src/Items/ItemMobHead.h
@@ -12,9 +12,11 @@
class cItemMobHeadHandler :
public cItemHandler
{
+ typedef cItemHandler super;
+
public:
cItemMobHeadHandler(int a_ItemType) :
- cItemHandler(a_ItemType)
+ super(a_ItemType)
{
}
@@ -30,34 +32,36 @@ public:
{
return true;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+ auto placedX = a_BlockX, placedY = a_BlockY, placedZ = a_BlockZ;
+ AddFaceDirection(placedY, placedY, placedZ, a_BlockFace);
// If the placed head is a wither, try to spawn the wither first:
if (a_EquippedItem.m_ItemDamage == E_META_HEAD_WITHER)
{
- if (TrySpawnWitherAround(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ))
+ if (TrySpawnWitherAround(a_World, a_Player, placedX, placedY, placedZ))
{
return true;
}
// Wither not created, proceed with regular head placement
}
- return PlaceRegularHead(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
+ cItem itemCopy(a_EquippedItem); // Make a copy in case this is the player's last head item and OnPlayerPlace removes it
+ if (!super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
+ {
+ return false;
+ }
+ RegularHeadPlaced(a_World, a_Player, itemCopy, placedX, placedY, placedZ, a_BlockFace);
+ return true;
}
- /** Places a regular head block with no mob spawning checking. */
- bool PlaceRegularHead(
+ /** Called after placing a regular head block with no mob spawning.
+ Adjusts the mob head entity based on the equipped item's data. */
+ void RegularHeadPlaced(
cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace
)
{
- // Place the block:
- if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_HEAD, BlockFaceToBlockMeta(a_BlockFace)))
- {
- return false;
- }
-
// Use a callback to set the properties of the mob head block entity:
class cCallback : public cBlockEntityCallback
{
@@ -71,7 +75,7 @@ public:
{
return false;
}
- cMobHeadEntity * MobHeadEntity = static_cast<cMobHeadEntity *>(a_BlockEntity);
+ auto MobHeadEntity = static_cast<cMobHeadEntity *>(a_BlockEntity);
int Rotation = 0;
if (m_BlockMeta == 1)
@@ -94,7 +98,6 @@ public:
};
cCallback Callback(a_Player, static_cast<eMobHeadType>(a_EquippedItem.m_ItemDamage), static_cast<NIBBLETYPE>(a_BlockFace));
a_World.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
- return true;
}
@@ -340,7 +343,7 @@ public:
) override
{
a_BlockType = E_BLOCK_HEAD;
- a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f);
+ a_BlockMeta = BlockFaceToBlockMeta(a_BlockFace);
return true;
}
} ;
diff --git a/src/Items/ItemMushroomSoup.h b/src/Items/ItemMushroomSoup.h
index dba313ec5..1a761cbf1 100644
--- a/src/Items/ItemMushroomSoup.h
+++ b/src/Items/ItemMushroomSoup.h
@@ -41,7 +41,7 @@ public:
// Return a bowl to the inventory
if (!a_Player->IsGameModeCreative())
{
- a_Player->GetInventory().AddItem(cItem(E_ITEM_BOWL), true, true);
+ a_Player->GetInventory().AddItem(cItem(E_ITEM_BOWL));
}
return true;
}
diff --git a/src/Items/ItemSign.h b/src/Items/ItemSign.h
index dabbdbba1..3da93e2f1 100644
--- a/src/Items/ItemSign.h
+++ b/src/Items/ItemSign.h
@@ -25,7 +25,7 @@ public:
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
- )
+ ) override
{
// If the regular placement doesn't work, do no further processing:
if (!super::OnPlayerPlace(a_World, a_Player, a_EquippedItem, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))