From 3381c0f6d6671a485283c889b036c0a431e2a2b9 Mon Sep 17 00:00:00 2001 From: 12xx12 <44411062+12xx12@users.noreply.github.com> Date: Thu, 8 Oct 2020 21:13:44 +0200 Subject: Merged OnBreak with OnPlayerBreak (#4967) Co-authored-by: 12xx12 <12xx12100@gmail.com> Co-authored-by: Tiger Wang --- src/Blocks/BlockBed.cpp | 4 +++- src/Blocks/BlockBed.h | 3 ++- src/Blocks/BlockBigFlower.h | 8 +++++++- src/Blocks/BlockCake.h | 2 +- src/Blocks/BlockDoor.cpp | 8 +++++++- src/Blocks/BlockDoor.h | 3 ++- src/Blocks/BlockFence.h | 5 +++-- src/Blocks/BlockHandler.h | 19 +++++-------------- src/Blocks/BlockIce.h | 7 ++++++- src/Blocks/BlockMobSpawner.h | 22 ++++++++++++++-------- src/Blocks/BlockOre.h | 33 ++++++++++++++++++++------------- src/Blocks/BlockPiston.cpp | 10 +++++++--- src/Blocks/BlockPiston.h | 6 ++++-- src/Blocks/BlockRail.h | 5 +++-- src/Blocks/ChunkInterface.cpp | 4 ++-- src/Blocks/ChunkInterface.h | 2 +- src/ClientHandle.cpp | 12 ++++++------ src/Items/ItemLighter.h | 2 +- src/Physics/Explodinator.cpp | 34 +++++++++++++++++----------------- src/Physics/Explodinator.h | 5 +++-- src/World.cpp | 28 ++++++++++++++++++++++++---- src/World.h | 6 +++--- 22 files changed, 141 insertions(+), 87 deletions(-) diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp index fb6bb29c7..58ff720c8 100644 --- a/src/Blocks/BlockBed.cpp +++ b/src/Blocks/BlockBed.cpp @@ -18,9 +18,11 @@ void cBlockBedHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const { + UNUSED(a_Digger); auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03); if ((a_OldBlockMeta & 0x08) != 0) { diff --git a/src/Blocks/BlockBed.h b/src/Blocks/BlockBed.h index eb36ede5c..266fa7d69 100644 --- a/src/Blocks/BlockBed.h +++ b/src/Blocks/BlockBed.h @@ -57,7 +57,8 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override; virtual bool OnUse( diff --git a/src/Blocks/BlockBigFlower.h b/src/Blocks/BlockBigFlower.h index e6e7f58fa..c3adf8dc7 100644 --- a/src/Blocks/BlockBigFlower.h +++ b/src/Blocks/BlockBigFlower.h @@ -115,8 +115,14 @@ private: - virtual void OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) const override + virtual void OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + const Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger + ) const override { + UNUSED(a_Digger); if ((a_OldBlockMeta & 0x8) != 0) { // Was upper part of flower diff --git a/src/Blocks/BlockCake.h b/src/Blocks/BlockCake.h index b67da5222..b93814955 100644 --- a/src/Blocks/BlockCake.h +++ b/src/Blocks/BlockCake.h @@ -36,7 +36,7 @@ private: a_Player.GetStatManager().AddValue(Statistic::EatCakeSlice); if (Meta >= 5) { - a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos); + a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos, &a_Player); } else { diff --git a/src/Blocks/BlockDoor.cpp b/src/Blocks/BlockDoor.cpp index fbd236b1d..d97bd9696 100644 --- a/src/Blocks/BlockDoor.cpp +++ b/src/Blocks/BlockDoor.cpp @@ -7,8 +7,14 @@ -void cBlockDoorHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta) const +void cBlockDoorHandler::OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, + NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger +) const { + UNUSED(a_Digger); // A part of the multiblock door was broken; the relevant half will drop any pickups as required. // All that is left to do is to delete the other half of the multiblock. diff --git a/src/Blocks/BlockDoor.h b/src/Blocks/BlockDoor.h index 097bdba40..56493321f 100644 --- a/src/Blocks/BlockDoor.h +++ b/src/Blocks/BlockDoor.h @@ -142,7 +142,8 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override; virtual bool OnUse( diff --git a/src/Blocks/BlockFence.h b/src/Blocks/BlockFence.h index c6cad0198..cc4f35fea 100644 --- a/src/Blocks/BlockFence.h +++ b/src/Blocks/BlockFence.h @@ -156,9 +156,11 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override { + UNUSED(a_Digger); // Destroy any leash knot tied to the fence: auto leashKnot = cLeashKnot::FindKnotAtPos(a_WorldInterface, a_BlockPos); if (leashKnot != nullptr) @@ -166,7 +168,6 @@ private: leashKnot->SetShouldSelfDestroy(); } } - }; diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index 13c3a84af..772536003 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -73,24 +73,15 @@ public: cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange ) const {} - /** Called just after the player breaks the block. + /** Called after a block gets broken (replaced with air), by natural means. The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta. - By default does nothing special, descendants may provide further behavior. */ - virtual void OnPlayerBrokeBlock( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - cPlayer & a_Player, - Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta - ) const {} - - /** Called after a block gets broken (replaced with air), either by player or by natural means. - If by player, it is called before the OnPlayerBrokeBlock() callback. - The block is already dug up in the world, the original block type and meta is passed in a_OldBlockType and a_OldBlockMeta. - By default notifies all direct neighbors via their OnNeighborChanged() callbacks. */ + By default notifies all direct neighbors via their OnNeighborChanged() callbacks. + You can determine what kind of entity broke the block (e.g. player) by checking a_Digger! */ virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const {} /** Called when a direct neighbor of this block has been changed. diff --git a/src/Blocks/BlockIce.h b/src/Blocks/BlockIce.h index c61abef57..8ff6415fb 100644 --- a/src/Blocks/BlockIce.h +++ b/src/Blocks/BlockIce.h @@ -81,7 +81,8 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override { // If there's a solid block or a liquid underneath, convert to water, rather than air @@ -97,6 +98,10 @@ private: } } + + + + virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override { UNUSED(a_Meta); diff --git a/src/Blocks/BlockMobSpawner.h b/src/Blocks/BlockMobSpawner.h index a002a4eb9..27d3d61de 100644 --- a/src/Blocks/BlockMobSpawner.h +++ b/src/Blocks/BlockMobSpawner.h @@ -54,21 +54,27 @@ private: - virtual void OnPlayerBrokeBlock( + virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - cPlayer & a_Player, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override { - auto handler = a_Player.GetEquippedItem().GetHandler(); - if (!a_Player.IsGameModeSurvival() || !handler->CanHarvestBlock(E_BLOCK_MOB_SPAWNER)) + if (!a_Digger->IsPlayer()) + { + return; + } + + const auto Player = static_cast(a_Digger); + auto Handler = Player->GetEquippedItem().GetHandler(); + if (!Player->IsGameModeSurvival() || !Handler->CanHarvestBlock(E_BLOCK_MOB_SPAWNER)) { return; } - auto & random = GetRandomProvider(); - int reward = 15 + random.RandInt(14) + random.RandInt(14); - a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, reward); + auto & Random = GetRandomProvider(); + int Reward = 15 + Random.RandInt(14) + Random.RandInt(14); + a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, Reward); } } ; diff --git a/src/Blocks/BlockOre.h b/src/Blocks/BlockOre.h index 023e149d9..6d6c2a097 100644 --- a/src/Blocks/BlockOre.h +++ b/src/Blocks/BlockOre.h @@ -64,26 +64,33 @@ private: - virtual void OnPlayerBrokeBlock( + virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - cPlayer & a_Player, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override { - if (!a_Player.IsGameModeSurvival()) + if (!a_Digger->IsPlayer()) + { + return; + } + + const auto Player = static_cast(a_Digger); + if (!Player->IsGameModeSurvival()) { // Don't drop XP unless the player is in survival mode. return; } - if (a_Player.GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) != 0) + if (Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) != 0) { // Don't drop XP when the ore is mined with the Silk Touch enchantment return; } - auto & random = GetRandomProvider(); - int reward = 0; + auto & Random = GetRandomProvider(); + int Reward = 0; switch (a_OldBlockType) { @@ -91,36 +98,36 @@ private: case E_BLOCK_LAPIS_ORE: { // Lapis and nether quartz get 2 - 5 experience - reward = random.RandInt(2, 5); + Reward = Random.RandInt(2, 5); break; } case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE_GLOWING: { // Redstone gets 1 - 5 experience - reward = random.RandInt(1, 5); + Reward = Random.RandInt(1, 5); break; } case E_BLOCK_DIAMOND_ORE: case E_BLOCK_EMERALD_ORE: { // Diamond and emerald get 3 - 7 experience - reward = random.RandInt(3, 7); + Reward = Random.RandInt(3, 7); break; } case E_BLOCK_COAL_ORE: { // Coal gets 0 - 2 experience - reward = random.RandInt(2); + Reward = Random.RandInt(2); break; } default: break; } - if (reward > 0) + if (Reward > 0) { - a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, reward); + a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, Reward); } } } ; diff --git a/src/Blocks/BlockPiston.cpp b/src/Blocks/BlockPiston.cpp index 7e6ff5e3f..20863cdf3 100644 --- a/src/Blocks/BlockPiston.cpp +++ b/src/Blocks/BlockPiston.cpp @@ -289,9 +289,11 @@ bool cBlockPistonHandler::CanPushBlock( void cBlockPistonHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const { + UNUSED(a_Digger); if (!IsExtended(a_OldBlockMeta)) { return; @@ -301,7 +303,7 @@ void cBlockPistonHandler::OnBroken( if ( cChunkDef::IsValidHeight(Extension.y) && (a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION) - ) + ) { // If the piston is extended, destroy the extension as well: a_ChunkInterface.SetBlock(Extension, E_BLOCK_AIR, 0); @@ -318,9 +320,11 @@ void cBlockPistonHandler::OnBroken( void cBlockPistonHeadHandler::OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const { + UNUSED(a_Digger); const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta); if (!cChunkDef::IsValidHeight(Base.y)) { diff --git a/src/Blocks/BlockPiston.h b/src/Blocks/BlockPiston.h index fd8f3fe8a..2c3ee4f6a 100644 --- a/src/Blocks/BlockPiston.h +++ b/src/Blocks/BlockPiston.h @@ -128,7 +128,8 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override; /** Moves a list of blocks in a specific direction */ @@ -156,7 +157,8 @@ public: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override; virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override; diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index af85e0afc..7c147d48a 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -77,10 +77,11 @@ private: virtual void OnBroken( cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger ) const override { - Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta); + Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); // Alert diagonal rails: NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); diff --git a/src/Blocks/ChunkInterface.cpp b/src/Blocks/ChunkInterface.cpp index 3af085c2a..37ed70615 100644 --- a/src/Blocks/ChunkInterface.cpp +++ b/src/Blocks/ChunkInterface.cpp @@ -101,7 +101,7 @@ bool cChunkInterface::WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a -bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos) +bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, cEntity * a_Digger) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; @@ -112,7 +112,7 @@ bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_Bl return false; } - cBlockHandler::For(BlockType).OnBroken(*this, a_WorldInterface, a_BlockPos, BlockType, BlockMeta); + cBlockHandler::For(BlockType).OnBroken(*this, a_WorldInterface, a_BlockPos, BlockType, BlockMeta, a_Digger); return true; } diff --git a/src/Blocks/ChunkInterface.h b/src/Blocks/ChunkInterface.h index a8ebb7a41..a8fcd6187 100644 --- a/src/Blocks/ChunkInterface.h +++ b/src/Blocks/ChunkInterface.h @@ -69,7 +69,7 @@ public: virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; - bool DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos); + bool DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, cEntity * a_Digger); /** Digs the block and spawns the relevant pickups, as if a_Digger used a_Tool to dig the block. */ void DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr, const cItem * a_Tool = nullptr); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 0ef041f32..2dd622b93 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1398,7 +1398,12 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo return; } + // Apply hunger: m_Player->AddFoodExhaustion(0.025); + + // Damage the tool, but not for 0 hardness blocks: + m_Player->UseEquippedItem(cBlockInfo::IsOneHitDig(a_OldBlock) ? cItemHandler::dlaBreakBlockInstant : cItemHandler::dlaBreakBlock); + cChunkInterface ChunkInterface(World->GetChunkMap()); Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ); if (m_Player->IsGameModeSurvival()) @@ -1407,15 +1412,10 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo } else { - World->DigBlock(absPos); + World->DigBlock(absPos, m_Player); } - // Damage the tool, but not for 0 hardness blocks: - auto dlAction = cBlockInfo::IsOneHitDig(a_OldBlock) ? cItemHandler::dlaBreakBlockInstant : cItemHandler::dlaBreakBlock; - m_Player->UseEquippedItem(dlAction); - World->BroadcastSoundParticleEffect(EffectID::PARTICLE_SMOKE, absPos, a_OldBlock, this); - cBlockHandler::For(a_OldBlock).OnPlayerBrokeBlock(ChunkInterface, *World, *m_Player, absPos, a_OldBlock, a_OldMeta); cRoot::Get()->GetPluginManager()->CallHookPlayerBrokenBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta); } diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h index a7e192ee6..064671c2e 100644 --- a/src/Items/ItemLighter.h +++ b/src/Items/ItemLighter.h @@ -65,7 +65,7 @@ public: case E_BLOCK_TNT: { // Activate the TNT: - a_World->DigBlock(a_ClickedBlockPos); + a_World->DigBlock(a_ClickedBlockPos, a_Player); a_World->SpawnPrimedTNT(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom break; } diff --git a/src/Physics/Explodinator.cpp b/src/Physics/Explodinator.cpp index d68dc8541..1c6d61949 100644 --- a/src/Physics/Explodinator.cpp +++ b/src/Physics/Explodinator.cpp @@ -102,7 +102,7 @@ namespace Explodinator } /** Sets the block at the given position, updating surroundings. */ - static void DestroyBlock(cWorld & a_World, cChunk & a_Chunk, const Vector3i a_AbsolutePosition, const Vector3i a_RelativePosition, const BLOCKTYPE a_DestroyedBlock, const BLOCKTYPE a_NewBlock) + static void DestroyBlock(cWorld & a_World, cChunk & a_Chunk, const Vector3i a_AbsolutePosition, const Vector3i a_RelativePosition, const BLOCKTYPE a_DestroyedBlock, const BLOCKTYPE a_NewBlock, const cEntity * const a_ExplodingEntity) { const auto DestroyedMeta = a_Chunk.GetMeta(a_RelativePosition); @@ -113,12 +113,12 @@ namespace Explodinator a_Chunk.SetBlock(a_RelativePosition, a_NewBlock, 0); cChunkInterface Interface(a_World.GetChunkMap()); - cBlockHandler::For(a_DestroyedBlock).OnBroken(Interface, a_World, a_AbsolutePosition, a_DestroyedBlock, DestroyedMeta); + cBlockHandler::For(a_DestroyedBlock).OnBroken(Interface, a_World, a_AbsolutePosition, a_DestroyedBlock, DestroyedMeta, a_ExplodingEntity); } /** Sets the block at the given Position to air, updates surroundings, and spawns pickups, fire, shrapnel according to Minecraft rules. OK, _mostly_ Minecraft rules. */ - static void DestroyBlock(cChunk & a_Chunk, const Vector3i a_Position, const unsigned a_Power, const bool a_Fiery) + static void DestroyBlock(cChunk & a_Chunk, const Vector3i a_Position, const unsigned a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { const auto DestroyedBlock = a_Chunk.GetBlock(a_Position); if (DestroyedBlock == E_BLOCK_AIR) @@ -150,7 +150,7 @@ namespace Explodinator if ((Below.y >= 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(Below))) { // Start a fire: - DestroyBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_FIRE); + DestroyBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_FIRE, a_ExplodingEntity); return; } } @@ -169,11 +169,11 @@ namespace Explodinator } } - DestroyBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_AIR); + DestroyBlock(World, a_Chunk, Absolute, a_Position, DestroyedBlock, E_BLOCK_AIR, a_ExplodingEntity); } /** Traces the path taken by one Explosion Lazor (tm) with given direction and intensity, that will destroy blocks until it is exhausted. */ - static void DestructionTrace(cChunk * a_Chunk, Vector3f a_Origin, const Vector3f a_Destination, const unsigned a_Power, const bool a_Fiery, float a_Intensity) + static void DestructionTrace(cChunk * a_Chunk, Vector3f a_Origin, const Vector3f a_Destination, const unsigned a_Power, const bool a_Fiery, float a_Intensity, const cEntity * const a_ExplodingEntity) { // The current position the ray is at. auto Checkpoint = a_Origin; @@ -206,7 +206,7 @@ namespace Explodinator break; } - DestroyBlock(*Neighbour, Position, a_Power, a_Fiery); + DestroyBlock(*Neighbour, Position, a_Power, a_Fiery, a_ExplodingEntity); // Adjust coordinates to be relative to the neighbour chunk: Checkpoint = RebaseRelativePosition(a_Chunk->GetPos(), Neighbour->GetPos(), Checkpoint); @@ -220,7 +220,7 @@ namespace Explodinator } /** Sends out Explosion Lazors (tm) originating from the given position that destroy blocks. */ - static void DamageBlocks(cChunk & a_Chunk, const Vector3f a_Position, const unsigned a_Power, const bool a_Fiery) + static void DamageBlocks(cChunk & a_Chunk, const Vector3f a_Position, const unsigned a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { const auto Intensity = a_Power * (0.7f + GetRandomProvider().RandReal(0.6f)); const auto ExplosionRadius = CeilC((Intensity / StepAttenuation) * StepUnit); @@ -236,8 +236,8 @@ namespace Explodinator { for (int OffsetZ = -HalfSide; OffsetZ < HalfSide; OffsetZ++) { - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(OffsetX, +ExplosionRadius, OffsetZ), a_Power, a_Fiery, Intensity); - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(OffsetX, -ExplosionRadius, OffsetZ), a_Power, a_Fiery, Intensity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(OffsetX, +ExplosionRadius, OffsetZ), a_Power, a_Fiery, Intensity, a_ExplodingEntity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(OffsetX, -ExplosionRadius, OffsetZ), a_Power, a_Fiery, Intensity, a_ExplodingEntity); } } @@ -263,10 +263,10 @@ namespace Explodinator { for (int OffsetY = -HalfSide + 1; OffsetY < HalfSide - 1; OffsetY++) { - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(ExplosionRadius, OffsetY, Offset + 1), a_Power, a_Fiery, Intensity); - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(-ExplosionRadius, OffsetY, Offset), a_Power, a_Fiery, Intensity); - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(Offset, OffsetY, ExplosionRadius), a_Power, a_Fiery, Intensity); - DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(Offset + 1, OffsetY, -ExplosionRadius), a_Power, a_Fiery, Intensity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(ExplosionRadius, OffsetY, Offset + 1), a_Power, a_Fiery, Intensity, a_ExplodingEntity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(-ExplosionRadius, OffsetY, Offset), a_Power, a_Fiery, Intensity, a_ExplodingEntity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(Offset, OffsetY, ExplosionRadius), a_Power, a_Fiery, Intensity, a_ExplodingEntity); + DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(Offset + 1, OffsetY, -ExplosionRadius), a_Power, a_Fiery, Intensity, a_ExplodingEntity); } } } @@ -280,13 +280,13 @@ namespace Explodinator } } - void Kaboom(cWorld & a_World, const Vector3f a_Position, const unsigned a_Power, const bool a_Fiery) + void Kaboom(cWorld & a_World, const Vector3f a_Position, const unsigned a_Power, const bool a_Fiery, const cEntity * const a_ExplodingEntity) { - a_World.DoWithChunkAt(a_Position.Floor(), [a_Position, a_Power, a_Fiery](cChunk & a_Chunk) + a_World.DoWithChunkAt(a_Position.Floor(), [a_Position, a_Power, a_Fiery, a_ExplodingEntity](cChunk & a_Chunk) { LagTheClient(a_Chunk, a_Position, a_Power); DamageEntities(a_Chunk, a_Position, a_Power); - DamageBlocks(a_Chunk, AbsoluteToRelative(a_Position, a_Chunk.GetPos()), a_Power, a_Fiery); + DamageBlocks(a_Chunk, AbsoluteToRelative(a_Position, a_Chunk.GetPos()), a_Power, a_Fiery, a_ExplodingEntity); return false; }); diff --git a/src/Physics/Explodinator.h b/src/Physics/Explodinator.h index daf86456a..4772618de 100644 --- a/src/Physics/Explodinator.h +++ b/src/Physics/Explodinator.h @@ -5,16 +5,17 @@ +class cEntity; class cWorld; - namespace Explodinator { /** Creates an explosion of Power, centred at Position, with ability to set fires as provided. For maximum efficiency, Position should be in the centre of the entity or block that exploded. + The entity pointer is used to trigger OnBreak for the destroyed blocks. Kaboom indeed, you drunken wretch. */ - void Kaboom(cWorld & World, Vector3f Position, unsigned Power, bool Fiery); + void Kaboom(cWorld & World, Vector3f Position, unsigned Power, bool Fiery, const cEntity * a_ExplodingEntity); } diff --git a/src/World.cpp b/src/World.cpp index 32ce7b4f9..88e76c817 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1394,7 +1394,27 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo if (!cPluginManager::Get()->CallHookExploding(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData) && (a_ExplosionSize > 0)) { // TODO: CanCauseFire gets reset to false for some reason - Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire); + + const cEntity * Entity; + switch (a_Source) + { + case eExplosionSource::esEnderCrystal: + case eExplosionSource::esGhastFireball: + case eExplosionSource::esMonster: + case eExplosionSource::esPrimedTNT: + case eExplosionSource::esWitherBirth: + case eExplosionSource::esWitherSkull: + { + Entity = static_cast(a_SourceData); + break; + } + default: + { + Entity = nullptr; + } + } + + Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC(a_ExplosionSize), a_CanCauseFire, Entity); cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData); } } @@ -2166,7 +2186,7 @@ bool cWorld::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure) -bool cWorld::DigBlock(Vector3i a_BlockPos) +bool cWorld::DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger) { BLOCKTYPE BlockType; NIBBLETYPE BlockMeta; @@ -2178,7 +2198,7 @@ bool cWorld::DigBlock(Vector3i a_BlockPos) } cChunkInterface ChunkInterface(GetChunkMap()); - cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_BlockPos, BlockType, BlockMeta); + cBlockHandler::For(BlockType).OnBroken(ChunkInterface, *this, a_BlockPos, BlockType, BlockMeta, a_Digger); return true; } @@ -2190,7 +2210,7 @@ bool cWorld::DigBlock(Vector3i a_BlockPos) bool cWorld::DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool) { auto pickups = PickupsFromBlock(a_BlockPos, a_Digger, a_Tool); - if (!DigBlock(a_BlockPos)) + if (!DigBlock(a_BlockPos, a_Digger)) { return false; } diff --git a/src/World.h b/src/World.h index b6b8ad8bc..a0e2d0dbc 100644 --- a/src/World.h +++ b/src/World.h @@ -667,16 +667,16 @@ public: /** Replaces the specified block with air, and calls the OnBroken block handler. Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead. Returns true on success, false if the chunk is not loaded. */ - bool DigBlock(Vector3i a_BlockPos); + bool DigBlock(Vector3i a_BlockPos, const cEntity * a_Digger); /** OBSOLETE, use the Vector3-based overload instead. Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()). Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead. Returns true on success, false if the chunk is not loaded. */ - bool DigBlock(int a_X, int a_Y, int a_Z) + bool DigBlock(int a_X, int a_Y, int a_Z, cEntity * a_Digger) { - return DigBlock({a_X, a_Y, a_Z}); + return DigBlock({a_X, a_Y, a_Z}, a_Digger); } /** Digs the specified block, and spawns the appropriate pickups for it. -- cgit v1.2.3