1
0

More TNT fixes.

Chain-reaction TNTs are spawned in proper coordinates (FS #390)
Centralized Primed TNT entity spawning and made available to the plugins.
Internal changes for better TNT performance.

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1604 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2013-06-18 19:09:51 +00:00
parent 547c341325
commit b2138b132c
14 changed files with 79 additions and 66 deletions

View File

@ -1497,13 +1497,12 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback
cVector3iArray * cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ) void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ, cVector3iArray & a_BlocksAffected)
{ {
cBlockArea area; cBlockArea area;
cVector3iArray * BlocksAffected = new cVector3iArray();
int ExplosionSizeInt = (int) ceil(a_ExplosionSize); int ExplosionSizeInt = (int) ceil(a_ExplosionSize);
int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt; int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt;
BlocksAffected->reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt); a_BlocksAffected.reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt);
area.Read(m_World, a_BlockX - ExplosionSizeInt, a_BlockX + ExplosionSizeInt, a_BlockY - ExplosionSizeInt, a_BlockY + ExplosionSizeInt, a_BlockZ - ExplosionSizeInt,a_BlockZ + ExplosionSizeInt); area.Read(m_World, a_BlockX - ExplosionSizeInt, a_BlockX + ExplosionSizeInt, a_BlockY - ExplosionSizeInt, a_BlockY + ExplosionSizeInt, a_BlockZ - ExplosionSizeInt,a_BlockZ + ExplosionSizeInt);
for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++) for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++)
{ {
@ -1516,43 +1515,42 @@ cVector3iArray * cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX,
} }
for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++) for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++)
{ {
if ((x * x + y * y + z * z) < ExplosionSizeSq) if ((x * x + y * y + z * z) > ExplosionSizeSq)
{ {
switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z)) // Too far away
{ continue;
case E_BLOCK_TNT:
{
// Activate the TNT, with a random fuse between 10 to 30 game ticks
float FuseTime = (float)(10 + m_World->GetTickRandomNumber(20)) / 20;
cTNTEntity * TNT = new cTNTEntity(a_BlockX, a_BlockY, a_BlockZ, FuseTime);
TNT->Initialize(m_World);
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
BlocksAffected->push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
break;
}
case E_BLOCK_OBSIDIAN:
case E_BLOCK_BEDROCK:
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_STATIONARY_LAVA:
case E_BLOCK_LAVA:
{
// These blocks are not affected by explosions
break;
}
default:
{
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
BlocksAffected->push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
}
}
} }
} switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z))
} {
case E_BLOCK_TNT:
} {
area.Write(m_World,a_BlockX - ExplosionSizeInt,a_BlockY - ExplosionSizeInt,a_BlockZ - ExplosionSizeInt); // Activate the TNT, with a random fuse between 10 to 30 game ticks
return BlocksAffected; float FuseTime = (float)(10 + m_World->GetTickRandomNumber(20)) / 20;
m_World->SpawnPrimedTNT(a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5, FuseTime);
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
break;
}
case E_BLOCK_OBSIDIAN:
case E_BLOCK_BEDROCK:
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_STATIONARY_LAVA:
case E_BLOCK_LAVA:
{
// These blocks are not affected by explosions
break;
}
default:
{
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
}
} // switch (BlockType)
} // for z
} // for y
} // for x
area.Write(m_World, a_BlockX - ExplosionSizeInt, a_BlockY - ExplosionSizeInt, a_BlockZ - ExplosionSizeInt);
} }

View File

@ -202,8 +202,8 @@ public:
/// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true /// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true
bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible
// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates /// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates
cVector3iArray * DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ); void DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ, cVector3iArray & a_BlockAffected);
/// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false.
bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible

View File

@ -1561,7 +1561,7 @@ void cClientHandle::SendEntityStatus(const cEntity & a_Entity, char a_Status)
void cClientHandle::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) void cClientHandle::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion)
{ {
m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion); m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion);
} }

View File

@ -98,7 +98,7 @@ public:
void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ); void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ);
void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item); void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item);
void SendEntityStatus (const cEntity & a_Entity, char a_Status); void SendEntityStatus (const cEntity & a_Entity, char a_Status);
void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion); void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion);
void SendGameMode (eGameMode a_GameMode); void SendGameMode (eGameMode a_GameMode);
void SendHealth (void); void SendHealth (void);
void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value); void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value);

View File

@ -34,8 +34,7 @@ public:
{ {
// Activate the TNT: // Activate the TNT:
a_World->BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); a_World->BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
cTNTEntity * TNT = new cTNTEntity(a_BlockX, a_BlockY, a_BlockZ, 4); // 4 seconds to boom a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
TNT->Initialize(a_World);
a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0); a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
break; break;
} }

View File

@ -67,7 +67,7 @@ public:
virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0;
virtual void SendGameMode (eGameMode a_GameMode) = 0; virtual void SendGameMode (eGameMode a_GameMode) = 0;
virtual void SendHealth (void) = 0; virtual void SendHealth (void) = 0;
virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) = 0; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) = 0;

View File

@ -352,7 +352,7 @@ void cProtocol125::SendEntityStatus(const cEntity & a_Entity, char a_Status)
void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion)
{ {
cCSLock Lock(m_CSPacket); cCSLock Lock(m_CSPacket);
WriteByte(PACKET_EXPLOSION); WriteByte(PACKET_EXPLOSION);

View File

@ -44,7 +44,7 @@ public:
virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override; virtual void SendHealth (void) override;
virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override;

View File

@ -267,7 +267,7 @@ void cProtocolRecognizer::SendEntityStatus(const cEntity & a_Entity, char a_Stat
void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion)
{ {
ASSERT(m_Protocol != NULL); ASSERT(m_Protocol != NULL);
m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion); m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion);

View File

@ -72,7 +72,7 @@ public:
virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override; virtual void SendHealth (void) override;
virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override;

View File

@ -8,22 +8,22 @@
cTNTEntity::cTNTEntity(int a_X,int a_Y,int a_Z,float a_MaxFuseTime) : cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec) :
super(etTNT, a_X + 0.5f, a_Y + 0.5f, a_Z + 0.5f) super(etTNT, a_X, a_Y, a_Z),
m_Counter(0),
m_MaxFuseTime(a_FuseTimeInSec)
{ {
m_MaxFuseTime = a_MaxFuseTime;
m_Counter = 0;
} }
cTNTEntity::cTNTEntity(const Vector3i a_Pos,float a_MaxFuseTime) : cTNTEntity::cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec) :
super(etTNT, a_Pos.x,a_Pos.y,a_Pos.z) super(etTNT, a_Pos.x, a_Pos.y, a_Pos.z),
m_Counter(0),
m_MaxFuseTime(a_FuseTimeInSec)
{ {
m_MaxFuseTime = a_MaxFuseTime;
m_Counter = 0;
} }

View File

@ -11,21 +11,22 @@
class cTNTEntity : class cTNTEntity :
public cEntity public cEntity
{ {
typedef cEntity super; typedef cEntity super;
public: public:
CLASS_PROTODEF(cTNTEntity); CLASS_PROTODEF(cTNTEntity);
cTNTEntity(int a_X,int a_Y,int a_Z,float a_MaxFuseTime); cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec);
cTNTEntity(const Vector3i a_Pos,float a_MaxFuseTime); cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec);
// cEntity overrides: // cEntity overrides:
virtual void Initialize(cWorld * a_World) override; virtual void Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
private:
float m_Counter; //In seconds too protected:
float m_MaxFuseTime; //in seconds float m_Counter; ///< How much time has elapsed since the object was created, in seconds
float m_MaxFuseTime; ///< How long the fuse is, in seconds
}; };

View File

@ -55,6 +55,7 @@
#include "PluginManager.h" #include "PluginManager.h"
#include "Blocks/BlockHandler.h" #include "Blocks/BlockHandler.h"
#include "Vector3d.h" #include "Vector3d.h"
#include "TNTEntity.h"
#include "tolua++.h" #include "tolua++.h"
@ -737,7 +738,8 @@ void cWorld::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, i
{ {
// TODO: Add damage to entities, add support for pickups, and implement block hardiness // TODO: Add damage to entities, add support for pickups, and implement block hardiness
Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ); Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ);
cVector3iArray * BlocksAffected = m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ); cVector3iArray BlocksAffected;
m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected);
BroadcastSoundEffect("random.explode", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f); BroadcastSoundEffect("random.explode", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f);
{ {
cCSLock Lock(m_CSPlayers); cCSLock Lock(m_CSPlayers);
@ -759,11 +761,10 @@ void cWorld::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, i
} }
distance_explosion.Normalize(); distance_explosion.Normalize();
distance_explosion *= power; distance_explosion *= power;
ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_ExplosionSize, *BlocksAffected, distance_explosion); ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_ExplosionSize, BlocksAffected, distance_explosion);
} }
} }
} }
delete BlocksAffected;
} }
@ -1314,6 +1315,17 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double
void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec)
{
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec);
TNT->Initialize(this);
// TODO: Add a bit of speed in horiz and vert axes
}
void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType) void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType)
{ {
m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType); m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType);

View File

@ -329,6 +329,9 @@ public:
/// Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: /// Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified:
void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ); void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ);
/// Spawns a new primed TNT entity at the specified block coords and specified fuse duration
void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec);
// tolua_end // tolua_end