1
0
Fork 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;
cVector3iArray * BlocksAffected = new cVector3iArray();
int ExplosionSizeInt = (int) ceil(a_ExplosionSize);
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);
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++)
{
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))
{
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));
}
}
// Too far away
continue;
}
}
}
}
area.Write(m_World,a_BlockX - ExplosionSizeInt,a_BlockY - ExplosionSizeInt,a_BlockZ - ExplosionSizeInt);
return BlocksAffected;
switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z))
{
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;
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
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
cVector3iArray * DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates
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.
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);
}

View File

@ -98,7 +98,7 @@ public:
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 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 SendHealth (void);
void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value);

View File

@ -34,8 +34,7 @@ public:
{
// Activate the TNT:
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
TNT->Initialize(a_World);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
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 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 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 SendHealth (void) = 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);
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 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 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 SendHealth (void) 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);
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 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 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 SendHealth (void) 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) :
super(etTNT, a_X + 0.5f, a_Y + 0.5f, a_Z + 0.5f)
cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec) :
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) :
super(etTNT, a_Pos.x,a_Pos.y,a_Pos.z)
cTNTEntity::cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec) :
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 :
public cEntity
{
typedef cEntity super;
typedef cEntity super;
public:
CLASS_PROTODEF(cTNTEntity);
cTNTEntity(int a_X,int a_Y,int a_Z,float a_MaxFuseTime);
cTNTEntity(const Vector3i a_Pos,float a_MaxFuseTime);
cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec);
cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec);
// cEntity overrides:
virtual void Initialize(cWorld * a_World) override;
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
private:
float m_Counter; //In seconds too
float m_MaxFuseTime; //in seconds
protected:
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 "Blocks/BlockHandler.h"
#include "Vector3d.h"
#include "TNTEntity.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
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);
{
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 *= 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)
{
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:
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