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(
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)
{

View File

@ -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(

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)
{
// Was upper part of flower

View File

@ -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
{

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.
// 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(
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(

View File

@ -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();
}
}
};

View File

@ -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.

View File

@ -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);

View File

@ -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;
}
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);
const auto Player = static_cast<const cPlayer *>(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);
}
} ;

View File

@ -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<const cPlayer *>(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);
}
}
} ;

View File

@ -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))
{

View File

@ -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;

View File

@ -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);

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;
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;
}

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;
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);

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
});

View File

@ -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);
}

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))
{
// 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);
}
}
@ -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;
}

View File

@ -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.