1
0
Fork 0

Merged OnBreak with OnPlayerBreak (#4967)

Co-authored-by: 12xx12 <12xx12100@gmail.com>
Co-authored-by: Tiger Wang <ziwei.tiger@outlook.com>
This commit is contained in:
12xx12 2020-10-08 21:13:44 +02:00 committed by GitHub
parent a9031b6bae
commit 3381c0f6d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 141 additions and 87 deletions

View File

@ -18,9 +18,11 @@
void cBlockBedHandler::OnBroken( void cBlockBedHandler::OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
const Vector3i a_BlockPos, const Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const ) const
{ {
UNUSED(a_Digger);
auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03); auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03);
if ((a_OldBlockMeta & 0x08) != 0) if ((a_OldBlockMeta & 0x08) != 0)
{ {

View File

@ -57,7 +57,8 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
const Vector3i a_BlockPos, const Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override; ) const override;
virtual bool OnUse( virtual bool OnUse(

View File

@ -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) if ((a_OldBlockMeta & 0x8) != 0)
{ {
// Was upper part of flower // Was upper part of flower

View File

@ -36,7 +36,7 @@ private:
a_Player.GetStatManager().AddValue(Statistic::EatCakeSlice); a_Player.GetStatManager().AddValue(Statistic::EatCakeSlice);
if (Meta >= 5) if (Meta >= 5)
{ {
a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos); a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos, &a_Player);
} }
else else
{ {

View File

@ -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. // 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. // All that is left to do is to delete the other half of the multiblock.

View File

@ -142,7 +142,8 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override; ) const override;
virtual bool OnUse( virtual bool OnUse(

View File

@ -156,9 +156,11 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override ) const override
{ {
UNUSED(a_Digger);
// Destroy any leash knot tied to the fence: // Destroy any leash knot tied to the fence:
auto leashKnot = cLeashKnot::FindKnotAtPos(a_WorldInterface, a_BlockPos); auto leashKnot = cLeashKnot::FindKnotAtPos(a_WorldInterface, a_BlockPos);
if (leashKnot != nullptr) if (leashKnot != nullptr)
@ -166,7 +168,6 @@ private:
leashKnot->SetShouldSelfDestroy(); leashKnot->SetShouldSelfDestroy();
} }
} }
}; };

View File

@ -73,24 +73,15 @@ public:
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, const sSetBlock & a_BlockChange
) const {} ) 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. 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. */ By default notifies all direct neighbors via their OnNeighborChanged() callbacks.
virtual void OnPlayerBrokeBlock( You can determine what kind of entity broke the block (e.g. player) by checking a_Digger! */
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. */
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const {} ) const {}
/** Called when a direct neighbor of this block has been changed. /** Called when a direct neighbor of this block has been changed.

View File

@ -81,7 +81,8 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override ) const override
{ {
// If there's a solid block or a liquid underneath, convert to water, rather than air // 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 virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) const override
{ {
UNUSED(a_Meta); UNUSED(a_Meta);

View File

@ -54,21 +54,27 @@ private:
virtual void OnPlayerBrokeBlock( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
cPlayer & a_Player,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override ) const override
{ {
auto handler = a_Player.GetEquippedItem().GetHandler(); if (!a_Digger->IsPlayer())
if (!a_Player.IsGameModeSurvival() || !handler->CanHarvestBlock(E_BLOCK_MOB_SPAWNER))
{ {
return; return;
} }
auto & random = GetRandomProvider(); const auto Player = static_cast<const cPlayer *>(a_Digger);
int reward = 15 + random.RandInt(14) + random.RandInt(14); auto Handler = Player->GetEquippedItem().GetHandler();
a_WorldInterface.SpawnSplitExperienceOrbs(Vector3d(0.5, 0.5, 0.5) + a_BlockPos, reward); 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);
} }
} ; } ;

View File

@ -64,26 +64,33 @@ private:
virtual void OnPlayerBrokeBlock( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
cPlayer & a_Player, Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override ) const override
{ {
if (!a_Player.IsGameModeSurvival()) if (!a_Digger->IsPlayer())
{
return;
}
const auto Player = static_cast<const cPlayer *>(a_Digger);
if (!Player->IsGameModeSurvival())
{ {
// Don't drop XP unless the player is in survival mode. // Don't drop XP unless the player is in survival mode.
return; 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 // Don't drop XP when the ore is mined with the Silk Touch enchantment
return; return;
} }
auto & random = GetRandomProvider(); auto & Random = GetRandomProvider();
int reward = 0; int Reward = 0;
switch (a_OldBlockType) switch (a_OldBlockType)
{ {
@ -91,36 +98,36 @@ private:
case E_BLOCK_LAPIS_ORE: case E_BLOCK_LAPIS_ORE:
{ {
// Lapis and nether quartz get 2 - 5 experience // Lapis and nether quartz get 2 - 5 experience
reward = random.RandInt(2, 5); Reward = Random.RandInt(2, 5);
break; break;
} }
case E_BLOCK_REDSTONE_ORE: case E_BLOCK_REDSTONE_ORE:
case E_BLOCK_REDSTONE_ORE_GLOWING: case E_BLOCK_REDSTONE_ORE_GLOWING:
{ {
// Redstone gets 1 - 5 experience // Redstone gets 1 - 5 experience
reward = random.RandInt(1, 5); Reward = Random.RandInt(1, 5);
break; break;
} }
case E_BLOCK_DIAMOND_ORE: case E_BLOCK_DIAMOND_ORE:
case E_BLOCK_EMERALD_ORE: case E_BLOCK_EMERALD_ORE:
{ {
// Diamond and emerald get 3 - 7 experience // Diamond and emerald get 3 - 7 experience
reward = random.RandInt(3, 7); Reward = Random.RandInt(3, 7);
break; break;
} }
case E_BLOCK_COAL_ORE: case E_BLOCK_COAL_ORE:
{ {
// Coal gets 0 - 2 experience // Coal gets 0 - 2 experience
reward = random.RandInt(2); Reward = Random.RandInt(2);
break; break;
} }
default: 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);
} }
} }
} ; } ;

View File

@ -289,9 +289,11 @@ bool cBlockPistonHandler::CanPushBlock(
void cBlockPistonHandler::OnBroken( void cBlockPistonHandler::OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const ) const
{ {
UNUSED(a_Digger);
if (!IsExtended(a_OldBlockMeta)) if (!IsExtended(a_OldBlockMeta))
{ {
return; return;
@ -301,7 +303,7 @@ void cBlockPistonHandler::OnBroken(
if ( if (
cChunkDef::IsValidHeight(Extension.y) && cChunkDef::IsValidHeight(Extension.y) &&
(a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION) (a_ChunkInterface.GetBlock(Extension) == E_BLOCK_PISTON_EXTENSION)
) )
{ {
// If the piston is extended, destroy the extension as well: // If the piston is extended, destroy the extension as well:
a_ChunkInterface.SetBlock(Extension, E_BLOCK_AIR, 0); a_ChunkInterface.SetBlock(Extension, E_BLOCK_AIR, 0);
@ -318,9 +320,11 @@ void cBlockPistonHandler::OnBroken(
void cBlockPistonHeadHandler::OnBroken( void cBlockPistonHeadHandler::OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const ) const
{ {
UNUSED(a_Digger);
const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta); const auto Base = a_BlockPos - cBlockPistonHandler::MetadataToOffset(a_OldBlockMeta);
if (!cChunkDef::IsValidHeight(Base.y)) if (!cChunkDef::IsValidHeight(Base.y))
{ {

View File

@ -128,7 +128,8 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override; ) const override;
/** Moves a list of blocks in a specific direction */ /** Moves a list of blocks in a specific direction */
@ -156,7 +157,8 @@ public:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override; ) const override;
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override; virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cEntity * a_Digger, const cItem * a_Tool) const override;

View File

@ -77,10 +77,11 @@ private:
virtual void OnBroken( virtual void OnBroken(
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
Vector3i a_BlockPos, Vector3i a_BlockPos,
BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
const cEntity * a_Digger
) const override ) 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: // Alert diagonal rails:
NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE);

View File

@ -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; BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta; NIBBLETYPE BlockMeta;
@ -112,7 +112,7 @@ bool cChunkInterface::DigBlock(cWorldInterface & a_WorldInterface, Vector3i a_Bl
return false; 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; return true;
} }

View File

@ -69,7 +69,7 @@ public:
virtual bool WriteBlockArea(cBlockArea & a_Area, int a_MinBlockX, int a_MinBlockY, int a_MinBlockZ, int a_DataTypes) override; 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. */ /** 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); void DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger = nullptr, const cItem * a_Tool = nullptr);

View File

@ -1398,7 +1398,12 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
return; return;
} }
// Apply hunger:
m_Player->AddFoodExhaustion(0.025); 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()); cChunkInterface ChunkInterface(World->GetChunkMap());
Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ); Vector3i absPos(a_BlockX, a_BlockY, a_BlockZ);
if (m_Player->IsGameModeSurvival()) if (m_Player->IsGameModeSurvival())
@ -1407,15 +1412,10 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
} }
else 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); 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); cRoot::Get()->GetPluginManager()->CallHookPlayerBrokenBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta);
} }

View File

@ -65,7 +65,7 @@ public:
case E_BLOCK_TNT: case E_BLOCK_TNT:
{ {
// Activate the 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 a_World->SpawnPrimedTNT(Vector3d(a_ClickedBlockPos) + Vector3d(0.5, 0.5, 0.5)); // 80 ticks to boom
break; break;
} }

View File

@ -102,7 +102,7 @@ namespace Explodinator
} }
/** Sets the block at the given position, updating surroundings. */ /** 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); const auto DestroyedMeta = a_Chunk.GetMeta(a_RelativePosition);
@ -113,12 +113,12 @@ namespace Explodinator
a_Chunk.SetBlock(a_RelativePosition, a_NewBlock, 0); a_Chunk.SetBlock(a_RelativePosition, a_NewBlock, 0);
cChunkInterface Interface(a_World.GetChunkMap()); 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. /** Sets the block at the given Position to air, updates surroundings, and spawns pickups, fire, shrapnel according to Minecraft rules.
OK, _mostly_ 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); const auto DestroyedBlock = a_Chunk.GetBlock(a_Position);
if (DestroyedBlock == E_BLOCK_AIR) if (DestroyedBlock == E_BLOCK_AIR)
@ -150,7 +150,7 @@ namespace Explodinator
if ((Below.y >= 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(Below))) if ((Below.y >= 0) && cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(Below)))
{ {
// Start a fire: // 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; 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. */ /** 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. // The current position the ray is at.
auto Checkpoint = a_Origin; auto Checkpoint = a_Origin;
@ -206,7 +206,7 @@ namespace Explodinator
break; 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: // Adjust coordinates to be relative to the neighbour chunk:
Checkpoint = RebaseRelativePosition(a_Chunk->GetPos(), Neighbour->GetPos(), Checkpoint); 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. */ /** 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 Intensity = a_Power * (0.7f + GetRandomProvider().RandReal(0.6f));
const auto ExplosionRadius = CeilC((Intensity / StepAttenuation) * StepUnit); const auto ExplosionRadius = CeilC((Intensity / StepAttenuation) * StepUnit);
@ -236,8 +236,8 @@ namespace Explodinator
{ {
for (int OffsetZ = -HalfSide; OffsetZ < HalfSide; OffsetZ++) 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, a_ExplodingEntity);
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);
} }
} }
@ -263,10 +263,10 @@ namespace Explodinator
{ {
for (int OffsetY = -HalfSide + 1; OffsetY < HalfSide - 1; OffsetY++) 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 + 1), a_Power, a_Fiery, Intensity, a_ExplodingEntity);
DestructionTrace(&a_Chunk, a_Position, a_Position + Vector3f(-ExplosionRadius, OffsetY, Offset), a_Power, a_Fiery, Intensity); 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); 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); 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); LagTheClient(a_Chunk, a_Position, a_Power);
DamageEntities(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; return false;
}); });

View File

@ -5,16 +5,17 @@
class cEntity;
class cWorld; class cWorld;
namespace Explodinator namespace Explodinator
{ {
/** Creates an explosion of Power, centred at Position, with ability to set fires as provided. /** 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. 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. */ 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);
} }

View File

@ -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)) 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 // TODO: CanCauseFire gets reset to false for some reason
Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC<unsigned>(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<const cEntity *>(a_SourceData);
break;
}
default:
{
Entity = nullptr;
}
}
Explodinator::Kaboom(*this, Vector3d(a_BlockX, a_BlockY, a_BlockZ), FloorC<unsigned>(a_ExplosionSize), a_CanCauseFire, Entity);
cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData); 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; BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta; NIBBLETYPE BlockMeta;
@ -2178,7 +2198,7 @@ bool cWorld::DigBlock(Vector3i a_BlockPos)
} }
cChunkInterface ChunkInterface(GetChunkMap()); 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; 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) bool cWorld::DropBlockAsPickups(Vector3i a_BlockPos, const cEntity * a_Digger, const cItem * a_Tool)
{ {
auto pickups = PickupsFromBlock(a_BlockPos, a_Digger, a_Tool); auto pickups = PickupsFromBlock(a_BlockPos, a_Digger, a_Tool);
if (!DigBlock(a_BlockPos)) if (!DigBlock(a_BlockPos, a_Digger))
{ {
return false; return false;
} }

View File

@ -667,16 +667,16 @@ public:
/** Replaces the specified block with air, and calls the OnBroken block handler. /** 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. Wakes up the simulators. Doesn't produce pickups, use DropBlockAsPickups() for that instead.
Returns true on success, false if the chunk is not loaded. */ 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. /** OBSOLETE, use the Vector3-based overload instead.
Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()). Replaces the specified block with air, and calls the apropriate block handlers (OnBreaking(), OnBroken()).
Wakes up the simulators. Wakes up the simulators.
Doesn't produce pickups, use DropBlockAsPickups() for that instead. Doesn't produce pickups, use DropBlockAsPickups() for that instead.
Returns true on success, false if the chunk is not loaded. */ 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. /** Digs the specified block, and spawns the appropriate pickups for it.