From b75fc5f4e8dc837f069e89541b52144defa2d1b9 Mon Sep 17 00:00:00 2001 From: "keyboard.osh@gmail.com" Date: Thu, 18 Apr 2013 02:42:45 +0000 Subject: [PATCH] Initial implementation of explosions and TNT block git-svn-id: http://mc-server.googlecode.com/svn/trunk@1392 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Bindings.cpp | 3 +- source/Bindings.h | 2 +- source/Blocks/BlockHandler.cpp | 2 + source/Blocks/BlockTNT.h | 38 ++++++++++++++ source/ClientHandle.cpp | 9 ++++ source/ClientHandle.h | 1 + source/Entity.h | 1 + source/Protocol/Protocol.h | 1 + source/Protocol/Protocol125.cpp | 28 +++++++++++ source/Protocol/Protocol125.h | 1 + source/Protocol/ProtocolRecognizer.cpp | 10 ++++ source/Protocol/ProtocolRecognizer.h | 1 + source/TNTEntity.cpp | 70 ++++++++++++++++++++++++++ source/TNTEntity.h | 33 ++++++++++++ source/Vector3i.h | 3 ++ source/World.cpp | 62 +++++++++++++++++++++++ source/World.h | 3 ++ 17 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 source/Blocks/BlockTNT.h create mode 100644 source/TNTEntity.cpp create mode 100644 source/TNTEntity.h diff --git a/source/Bindings.cpp b/source/Bindings.cpp index be95a05b3..cd6a057e4 100644 --- a/source/Bindings.cpp +++ b/source/Bindings.cpp @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 04/13/13 22:59:55. +** Generated automatically by tolua++-1.0.92 on 04/17/13 19:40:39. */ #ifndef __cplusplus @@ -24409,6 +24409,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S) tolua_constant(tolua_S,"etMob",cEntity::etMob); tolua_constant(tolua_S,"etFallingBlock",cEntity::etFallingBlock); tolua_constant(tolua_S,"etMinecart",cEntity::etMinecart); + tolua_constant(tolua_S,"etTNT",cEntity::etTNT); tolua_constant(tolua_S,"eEntityType_Entity",cEntity::eEntityType_Entity); tolua_constant(tolua_S,"eEntityType_Player",cEntity::eEntityType_Player); tolua_constant(tolua_S,"eEntityType_Pickup",cEntity::eEntityType_Pickup); diff --git a/source/Bindings.h b/source/Bindings.h index 76098c6e4..ff29c1589 100644 --- a/source/Bindings.h +++ b/source/Bindings.h @@ -1,6 +1,6 @@ /* ** Lua binding: AllToLua -** Generated automatically by tolua++-1.0.92 on 04/13/13 22:59:55. +** Generated automatically by tolua++-1.0.92 on 04/17/13 19:40:39. */ /* Exported function */ diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp index 51051b7a6..4b7aa6fa2 100644 --- a/source/Blocks/BlockHandler.cpp +++ b/source/Blocks/BlockHandler.cpp @@ -56,6 +56,7 @@ #include "BlockCauldron.h" #include "BlockBrewingStand.h" #include "BlockCobWeb.h" +#include "BlockTNT.h" @@ -171,6 +172,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType) case E_BLOCK_STONE_SLAB: return new cBlockSlabHandler (a_BlockType); case E_BLOCK_SUGARCANE: return new cBlockSugarcaneHandler (a_BlockType); case E_BLOCK_TALL_GRASS: return new cBlockTallGrassHandler (a_BlockType); + case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType); case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType); case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType); case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); diff --git a/source/Blocks/BlockTNT.h b/source/Blocks/BlockTNT.h new file mode 100644 index 000000000..d9dcca67b --- /dev/null +++ b/source/Blocks/BlockTNT.h @@ -0,0 +1,38 @@ + +#pragma once + +#include "BlockHandler.h" +#include "../Player.h" +#include "../TNTEntity.h" + + + + +class cBlockTNTHandler : public cBlockHandler +{ +public: + cBlockTNTHandler(BLOCKTYPE a_BlockType) + : cBlockHandler(a_BlockType) + { + } + + virtual void OnUse(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override + { + if (a_Player->GetEquippedWeapon().m_ItemType == E_ITEM_FLINT_AND_STEEL) + { + 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->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0); + } + } + + virtual bool IsUseable() override + { + return true; + } +}; + + + + diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index 497639649..2a8ceabc7 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -1552,6 +1552,15 @@ 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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) +{ + m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotionX, a_PlayerMotionY,a_PlayerMotionZ); +} + + + + + void cClientHandle::SendMetadata(const cPawn & a_Pawn) { m_Protocol->SendMetadata(a_Pawn); diff --git a/source/ClientHandle.h b/source/ClientHandle.h index a43b0ca9b..0a228af3d 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -98,6 +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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ); void SendGameMode (eGameMode a_GameMode); void SendHealth (void); void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value); diff --git a/source/Entity.h b/source/Entity.h index 3d4d1244e..5871ce89c 100644 --- a/source/Entity.h +++ b/source/Entity.h @@ -67,6 +67,7 @@ public: etMob = etMonster, // DEPRECATED, use etMonster instead! etFallingBlock, etMinecart, + etTNT, // DEPRECATED older constants, left over for compatibility reasons (plugins) eEntityType_Entity = etEntity, diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h index 4cf041cdf..48d32384c 100644 --- a/source/Protocol/Protocol.h +++ b/source/Protocol/Protocol.h @@ -67,6 +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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) = 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; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index c3cfdfd81..e588bc595 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -352,6 +352,34 @@ 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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) +{ + cCSLock Lock(m_CSPacket); + WriteByte(PACKET_EXPLOSION); + WriteDouble (a_BlockX); + WriteDouble (a_BlockY); + WriteDouble (a_BlockZ); + WriteFloat (a_Radius); + WriteInt (a_BlocksAffected.size());//it should be a_RecordCount + /*WriteByte (0); //It should be the record + WriteByte (0); + WriteByte (0);*/ + for (cVector3iList::iterator itr = a_BlocksAffected.begin(); itr != a_BlocksAffected.end(); ++itr) + { + WriteByte ((Byte)((*itr)->x - a_BlockX)); + WriteByte ((Byte)((*itr)->y - a_BlockY)); + WriteByte ((Byte)((*itr)->z - a_BlockZ)); + } + WriteFloat (a_PlayerMotionX); + WriteFloat (a_PlayerMotionY); + WriteFloat (a_PlayerMotionZ); + Flush(); +} + + + + + void cProtocol125::SendEntRelMove(const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) { ASSERT(a_Entity.GetUniqueID() != m_Client->GetPlayer()->GetUniqueID()); // Must not send for self diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index 4191d0793..1cf03357d 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -44,6 +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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) 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; diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp index ad99839e4..ea60dafae 100644 --- a/source/Protocol/ProtocolRecognizer.cpp +++ b/source/Protocol/ProtocolRecognizer.cpp @@ -266,6 +266,16 @@ 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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) +{ + ASSERT(m_Protocol != NULL); + m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotionX, a_PlayerMotionY,a_PlayerMotionZ); +} + + + + + void cProtocolRecognizer::SendGameMode(eGameMode a_GameMode) { ASSERT(m_Protocol != NULL); diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h index 8218dbcaa..f897f1804 100644 --- a/source/Protocol/ProtocolRecognizer.h +++ b/source/Protocol/ProtocolRecognizer.h @@ -71,6 +71,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, cVector3iList a_BlocksAffected, float a_PlayerMotionX, float a_PlayerMotionY, float a_PlayerMotionZ) 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; diff --git a/source/TNTEntity.cpp b/source/TNTEntity.cpp new file mode 100644 index 000000000..636c9535c --- /dev/null +++ b/source/TNTEntity.cpp @@ -0,0 +1,70 @@ +#include "Globals.h" + +#include "TNTEntity.h" +#include "World.h" +#include "ClientHandle.h" + + + + + +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) +{ + 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) +{ + m_MaxFuseTime = a_MaxFuseTime; + m_Counter = 0; +} + + + + +void cTNTEntity::Initialize(cWorld * a_World) +{ + super::Initialize(a_World); + a_World->BroadcastSpawn(*this); +} + + + + + +void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle) +{ + a_ClientHandle.SendSpawnObject(*this,50,1,0,0); //50 means TNT + m_bDirtyPosition = false; + m_bDirtySpeed = false; + m_bDirtyOrientation = false; + m_bDirtyHead = false; +} + + + + + +void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk) +{ + float delta_time = a_Dt / 1000; //Convert miliseconds to seconds + m_Counter += delta_time; + if (m_Counter > m_MaxFuseTime) //Check if we go KABOOOM + { + Destroy(); + LOGD("BOOM at {%f,%f,%f}",GetPosX(),GetPosY(),GetPosZ()); + m_World->DoExplosiontAt(4.0,(int)floor(GetPosX()),(int)floor(GetPosY()),(int)floor(GetPosZ())); + return; + } +} + + + + diff --git a/source/TNTEntity.h b/source/TNTEntity.h new file mode 100644 index 000000000..8414b2430 --- /dev/null +++ b/source/TNTEntity.h @@ -0,0 +1,33 @@ + +#pragma once + +#include "Entity.h" +#include "Defines.h" + + + + + +class cTNTEntity : + public cEntity +{ +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); + + // 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 +}; + + + + diff --git a/source/Vector3i.h b/source/Vector3i.h index fd9b95305..820368c28 100644 --- a/source/Vector3i.h +++ b/source/Vector3i.h @@ -36,3 +36,6 @@ public: // tolua_export int x, y, z; // tolua_export }; // tolua_export + + +typedef std::list< Vector3i * > cVector3iList; \ No newline at end of file diff --git a/source/World.cpp b/source/World.cpp index 74a7ea399..6b1e5f8c8 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -703,6 +703,68 @@ bool cWorld::ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback +void cWorld::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ) +{ + //TODO implement explosion using cBlockArea, add damage to pawns, add support for pickups, and implement block hardiness + Vector3d explosion_pos = Vector3d(a_BlockX,a_BlockY,a_BlockZ); + cVector3iList BlocksAffected; + for (int i=0;iGetClientHandle(); + if ((ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + { + continue; + } + Vector3d distance_explosion = (*itr)->GetPosition() - explosion_pos; + if (distance_explosion.SqrLength() < 4096.0) + { + double real_distance = sqrt( distance_explosion.SqrLength()); + if (real_distance <= 0.0004) + real_distance = 0.0004; + double power = a_ExplosionSize / real_distance; + if (power <= 1) + power = 0; + distance_explosion.Normalize(); + distance_explosion *= power; + ch->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_ExplosionSize,BlocksAffected,(float)distance_explosion.x,(float)distance_explosion.y,(float)distance_explosion.z); + } + } + } +} + + + + + bool cWorld::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback) { return m_ChunkMap->DoWithChestAt(a_BlockX, a_BlockY, a_BlockZ, a_Callback); diff --git a/source/World.h b/source/World.h index 70e203bc3..c3aa0c25c 100644 --- a/source/World.h +++ b/source/World.h @@ -338,6 +338,9 @@ public: /// Calls the callback for each furnace in the specified chunk; returns true if all furnaces processed, false if the callback aborted by returning true bool ForEachFurnaceInChunk(int a_ChunkX, int a_ChunkZ, cFurnaceCallback & a_Callback); // Exported in ManualBindings.cpp + /// Does an explosion with the specified strength at the specified coordinate + void DoExplosiontAt (float a_ExplosionSzie, int a_BlockX, int a_BlockY, int a_BlockZ); // + /// Calls the callback for the chest at the specified coords; returns false if there's no chest at those coords, true if found bool DoWithChestAt (int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallback & a_Callback); // Exported in ManualBindings.cpp