From 547c34132530a4dba841879595bd0762ef52a22d Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Tue, 18 Jun 2013 08:24:34 +0000 Subject: [PATCH] TNT fixes. Other blocks can be placed next to TNT. Explosions activate nearby TNT blocks. TNT doesn't destroy bedrock, obsidian and liquid blocks. Server doesn't crash when a TNT (or other entity) leaves the valid Y range. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1603 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- VC2008/MCServer.vcproj | 4 --- source/Blocks/BlockHandler.cpp | 2 -- source/Blocks/BlockTNT.h | 38 ---------------------------- source/ChunkMap.cpp | 45 +++++++++++++++++++++++++++++----- source/Entity.cpp | 26 ++++++++++++++------ source/Items/ItemLighter.h | 23 ++++++++++++++--- source/TNTEntity.cpp | 12 ++++----- source/World.cpp | 4 +-- 8 files changed, 85 insertions(+), 69 deletions(-) delete mode 100644 source/Blocks/BlockTNT.h diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj index 83e9137e7..90ceec0ac 100644 --- a/VC2008/MCServer.vcproj +++ b/VC2008/MCServer.vcproj @@ -2008,10 +2008,6 @@ RelativePath="..\source\blocks\BlockTallGrass.h" > - - diff --git a/source/Blocks/BlockHandler.cpp b/source/Blocks/BlockHandler.cpp index 20f42d0c5..a853c6f68 100644 --- a/source/Blocks/BlockHandler.cpp +++ b/source/Blocks/BlockHandler.cpp @@ -56,7 +56,6 @@ #include "BlockCauldron.h" #include "BlockBrewingStand.h" #include "BlockCobWeb.h" -#include "BlockTNT.h" #include "BlockDeadBush.h" #include "BlockHopper.h" @@ -177,7 +176,6 @@ 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 deleted file mode 100644 index d9dcca67b..000000000 --- a/source/Blocks/BlockTNT.h +++ /dev/null @@ -1,38 +0,0 @@ - -#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/ChunkMap.cpp b/source/ChunkMap.cpp index a4ca99c9f..1aa8dcb8b 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -12,6 +12,7 @@ #include "Generating/Trees.h" // used in cChunkMap::ReplaceTreeBlocks() for tree block discrimination #include "BlockArea.h" #include "PluginManager.h" +#include "TNTEntity.h" #ifndef _WIN32 #include // abs @@ -1496,23 +1497,55 @@ 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) +cVector3iArray * cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ) { cBlockArea area; - cVector3iArray *BlocksAffected = new cVector3iArray(); + cVector3iArray * BlocksAffected = new cVector3iArray(); int ExplosionSizeInt = (int) ceil(a_ExplosionSize); + int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt; 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 y = -ExplosionSizeInt; y < ExplosionSizeInt; y++) { + if ((a_BlockY + y >= cChunkDef::Height) || (a_BlockY + y < 0)) + { + // Outside of the world + continue; + } for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++) { - if ((x*x + y*y + z*z) < (ExplosionSizeInt * ExplosionSizeInt)) + if ((x * x + y * y + z * z) < ExplosionSizeSq) { - 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: + { + // 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)); + } + } } } } diff --git a/source/Entity.cpp b/source/Entity.cpp index 09cb3d030..082e1e925 100644 --- a/source/Entity.cpp +++ b/source/Entity.cpp @@ -211,26 +211,35 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) { - //TODO Add collision detection with entities. + // TODO Add collision detection with entities. a_Dt /= 1000; Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ()); Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ()); int BlockX = (int) floor(NextPos.x); int BlockY = (int) floor(NextPos.y); int BlockZ = (int) floor(NextPos.z); - //Make sure we got the correct chunk and a valid one. No one ever knows... + + if ((BlockY >= cChunkDef::Height) || (BlockY < 0)) + { + // Outside of the world + // TODO: Current speed should still be added to the entity position + // Otherwise TNT explosions in the void will still effect the bottommost layers of the world + return; + } + + // Make sure we got the correct chunk and a valid one. No one ever knows... cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX,BlockZ); if (NextChunk != NULL) { int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width); int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width); BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ ); - if(!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block + if (!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block { - if( m_bOnGround ) // check if it's still on the ground + if (m_bOnGround) // check if it's still on the ground { BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ ); - if(!g_BlockIsSolid[BlockBelow]) //Check if block below is air or water. + if (!g_BlockIsSolid[BlockBelow]) // Check if block below is air or water. { m_bOnGround = false; } @@ -353,14 +362,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) NextPos += (NextSpeed * a_Dt); } else - { // We didn't hit anything, so move =] + { + // We didn't hit anything, so move =] NextPos += (NextSpeed * a_Dt); } } BlockX = (int) floor(NextPos.x); - BlockZ = (int) floor(NextPos.z); + BlockZ = (int) floor(NextPos.z); NextChunk = NextChunk->GetNeighborChunk(BlockX,BlockZ); - //See if we can commit our changes. If not, we will discard them. + // See if we can commit our changes. If not, we will discard them. if (NextChunk != NULL) { if (NextPos.x != GetPosX()) SetPosX(NextPos.x); diff --git a/source/Items/ItemLighter.h b/source/Items/ItemLighter.h index fe8cd1370..bcea8545f 100644 --- a/source/Items/ItemLighter.h +++ b/source/Items/ItemLighter.h @@ -4,6 +4,7 @@ #include "ItemHandler.h" #include "../World.h" #include "../Player.h" +#include "../TNTEntity.h" @@ -27,9 +28,25 @@ public: a_Player->UseEquippedItem(); - AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); - - a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); //0 -> new fire + switch (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)) + { + case E_BLOCK_TNT: + { + // 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->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0); + break; + } + default: + { + // Light a fire next to the block: + AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); + a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); + break; + } + } return false; } diff --git a/source/TNTEntity.cpp b/source/TNTEntity.cpp index 4541a7c7f..ec4bc6dfa 100644 --- a/source/TNTEntity.cpp +++ b/source/TNTEntity.cpp @@ -41,7 +41,7 @@ void cTNTEntity::Initialize(cWorld * a_World) void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle) { - a_ClientHandle.SendSpawnObject(*this,50,1,0,0); //50 means TNT + a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT m_bDirtyPosition = false; m_bDirtySpeed = false; m_bDirtyOrientation = false; @@ -54,15 +54,15 @@ void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle) void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk) { - super::Tick(a_Dt,a_Chunk); + super::Tick(a_Dt, a_Chunk); BroadcastMovementUpdate(); - float delta_time = a_Dt / 1000; //Convert miliseconds to seconds + float delta_time = a_Dt / 1000; // Convert miliseconds to seconds m_Counter += delta_time; - if (m_Counter > m_MaxFuseTime) //Check if we go KABOOOM + 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())); + 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/World.cpp b/source/World.cpp index f9da43ed2..51863919f 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -736,8 +736,8 @@ 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: 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); + Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ); + cVector3iArray * BlocksAffected = m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ); BroadcastSoundEffect("random.explode", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f); { cCSLock Lock(m_CSPlayers);