diff options
-rw-r--r-- | src/BlockEntities/CommandBlockEntity.cpp | 25 | ||||
-rw-r--r-- | src/ChunkMap.cpp | 67 | ||||
-rw-r--r-- | src/Entities/ItemFrame.cpp | 1 | ||||
-rw-r--r-- | src/Items/ItemHandler.h | 2 | ||||
-rw-r--r-- | src/Root.cpp | 14 | ||||
-rw-r--r-- | src/Server.cpp | 55 | ||||
-rw-r--r-- | src/World.cpp | 9 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.cpp | 1 |
8 files changed, 91 insertions, 83 deletions
diff --git a/src/BlockEntities/CommandBlockEntity.cpp b/src/BlockEntities/CommandBlockEntity.cpp index 45f8a3e4d..fe2f5e60a 100644 --- a/src/BlockEntities/CommandBlockEntity.cpp +++ b/src/BlockEntities/CommandBlockEntity.cpp @@ -13,6 +13,7 @@ #include "../Root.h" #include "../Server.h" // ExecuteConsoleCommand() #include "../Chunk.h" +#include "../ChatColor.h" @@ -206,15 +207,27 @@ void cCommandBlockEntity::Execute() virtual void Out(const AString & a_Text) { // Overwrite field - m_CmdBlock->SetLastOutput(a_Text); + m_CmdBlock->SetLastOutput(cClientHandle::FormatChatPrefix(m_CmdBlock->GetWorld()->ShouldUseChatPrefixes(), "SUCCESS", cChatColor::Green, cChatColor::White) + a_Text); } } CmdBlockOutCb(this); - LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str()); - - cServer * Server = cRoot::Get()->GetServer(); - - Server->ExecuteConsoleCommand(m_Command, CmdBlockOutCb); + if ( // Administrator commands are not executable by command blocks + (m_Command != "stop") && + (m_Command != "restart") && + (m_Command != "kick") && + (m_Command != "ban") && + (m_Command != "ipban") + ) + { + cServer * Server = cRoot::Get()->GetServer(); + LOGD("cCommandBlockEntity: Executing command %s", m_Command.c_str()); + Server->ExecuteConsoleCommand(m_Command, CmdBlockOutCb); + } + else + { + SetLastOutput(cClientHandle::FormatChatPrefix(GetWorld()->ShouldUseChatPrefixes(), "FAILURE", cChatColor::Rose, cChatColor::White) + "Adminstration commands can not be executed"); + LOGD("cCommandBlockEntity: Prevented execution of administration command %s", m_Command.c_str()); + } // TODO 2014-01-18 xdot: Update the signal strength. m_Result = 0; diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index dd8be0631..8ca61e2cf 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1880,21 +1880,18 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_ } else if ((m_World->GetTNTShrapnelLevel() > slNone) && (m_World->GetTickRandomNumber(100) < 20)) // 20% chance of flinging stuff around { - if (!cBlockInfo::FullyOccupiesVoxel(Block)) + if ( + ((m_World->GetTNTShrapnelLevel() == slAll) && cBlockInfo::FullyOccupiesVoxel(Block)) || + ((m_World->GetTNTShrapnelLevel() == slGravityAffectedOnly) && ((Block == E_BLOCK_SAND) || (Block == E_BLOCK_GRAVEL))) + ) { - break; + m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, Block, area.GetBlockMeta(bx + x, by + y, bz + z)); } - else if ((m_World->GetTNTShrapnelLevel() == slGravityAffectedOnly) && ((Block != E_BLOCK_SAND) && (Block != E_BLOCK_GRAVEL))) - { - break; - } - m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, Block, area.GetBlockMeta(bx + x, by + y, bz + z)); } area.SetBlockTypeMeta(bx + x, by + y, bz + z, E_BLOCK_AIR, 0); a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z)); - break; - + break; } } // switch (BlockType) } // for z @@ -1916,51 +1913,31 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_ virtual bool Item(cEntity * a_Entity) override { - if (a_Entity->IsPickup()) - { - if (((cPickup *)a_Entity)->GetAge() < 20) // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned) - { - return false; - } - } - - Vector3d EntityPos = a_Entity->GetPosition(); - cBoundingBox bbEntity(EntityPos, a_Entity->GetWidth() / 2, a_Entity->GetHeight()); - - if (!m_bbTNT.IsInside(bbEntity)) // IsInside actually acts like DoesSurround + if (a_Entity->IsPickup() && (a_Entity->GetTicksAlive() < 20)) { + // If pickup age is smaller than one second, it is invincible (so we don't kill pickups that were just spawned) return false; } - - Vector3d AbsoluteEntityPos(abs(EntityPos.x), abs(EntityPos.y), abs(EntityPos.z)); - - // Work out how far we are from the edge of the TNT's explosive effect - AbsoluteEntityPos -= m_ExplosionPos; - - // All to positive - AbsoluteEntityPos.x = abs(AbsoluteEntityPos.x); - AbsoluteEntityPos.y = abs(AbsoluteEntityPos.y); - AbsoluteEntityPos.z = abs(AbsoluteEntityPos.z); - - double FinalDamage = (((1 / AbsoluteEntityPos.x) + (1 / AbsoluteEntityPos.y) + (1 / AbsoluteEntityPos.z)) * 2) * m_ExplosionSize; - - // Clip damage values - FinalDamage = Clamp(FinalDamage, 0.0, (double)a_Entity->GetMaxHealth()); + Vector3d DistanceFromExplosion = a_Entity->GetPosition() - m_ExplosionPos; + if (!a_Entity->IsTNT() && !a_Entity->IsFallingBlock()) // Don't apply damage to other TNT entities and falling blocks, they should be invincible { - a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0); - } + cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight()); - // Apply force to entities around the explosion - code modified from World.cpp DoExplosionAt() - Vector3d distance_explosion = a_Entity->GetPosition() - m_ExplosionPos; - if (distance_explosion.SqrLength() < 4096.0) - { - distance_explosion.Normalize(); - distance_explosion *= m_ExplosionSize * m_ExplosionSize; + if (!m_bbTNT.IsInside(bbEntity)) // If bbEntity is inside bbTNT, not vice versa! + { + return false; + } - a_Entity->AddSpeed(distance_explosion); + // Ensure that the damage dealt is inversely proportional to the distance to the TNT centre - the closer a player is, the harder they are hit + a_Entity->TakeDamage(dtExplosion, NULL, (int)((1 / DistanceFromExplosion.Length()) * 6 * m_ExplosionSize), 0); } + + // Apply force to entities around the explosion - code modified from World.cpp DoExplosionAt() + DistanceFromExplosion.Normalize(); + DistanceFromExplosion *= m_ExplosionSize * m_ExplosionSize; + a_Entity->AddSpeed(DistanceFromExplosion); return false; } diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp index f0b0c8c65..0bc10ec60 100644 --- a/src/Entities/ItemFrame.cpp +++ b/src/Entities/ItemFrame.cpp @@ -55,7 +55,6 @@ void cItemFrame::KilledBy(TakeDamageInfo & a_TDI) { if (m_Item.IsEmpty()) { - SetHealth(0); super::KilledBy(a_TDI); Destroy(); return; diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h index 8b554ee34..67c250a97 100644 --- a/src/Items/ItemHandler.h +++ b/src/Items/ItemHandler.h @@ -75,7 +75,7 @@ public: int FoodLevel; double Saturation; - FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) : + FoodInfo(int a_FoodLevel, double a_Saturation) : FoodLevel(a_FoodLevel), Saturation(a_Saturation) { diff --git a/src/Root.cpp b/src/Root.cpp index ef66f9870..f04cbf08b 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -468,16 +468,6 @@ void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCall void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd) { - // Some commands are built-in: - if (a_Cmd == "stop") - { - m_bStop = true; - } - else if (a_Cmd == "restart") - { - m_bRestart = true; - } - // Put the command into a queue (Alleviates FS #363): cCSLock Lock(m_CSPendingCommands); m_PendingCommands.push_back(cCommand(a_Cmd, new cLogCommandDeleteSelfOutputCallback)); @@ -489,14 +479,16 @@ void cRoot::QueueExecuteConsoleCommand(const AString & a_Cmd) void cRoot::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallback & a_Output) { - // Some commands are built-in: + // cRoot handles stopping and restarting due to our access to controlling variables if (a_Cmd == "stop") { m_bStop = true; + return; } else if (a_Cmd == "restart") { m_bRestart = true; + return; } LOG("Executing console command: \"%s\"", a_Cmd.c_str()); diff --git a/src/Server.cpp b/src/Server.cpp index 958fe83c8..069e2a169 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -458,56 +458,80 @@ void cServer::ExecuteConsoleCommand(const AString & a_Cmd, cCommandOutputCallbac return; } - // Special handling: "stop" and "restart" are built in - if ((split[0].compare("stop") == 0) || (split[0].compare("restart") == 0)) - { - return; - } + // "stop" and "restart" are handled in cRoot::ExecuteConsoleCommand, our caller, due to its access to controlling variables // "help" and "reload" are to be handled by MCS, so that they work no matter what if (split[0] == "help") { PrintHelp(split, a_Output); + a_Output.Finished(); return; } else if (split[0] == "reload") { cPluginManager::Get()->ReloadPlugins(); + a_Output.Finished(); return; } else if (split[0] == "reloadplugins") { cPluginManager::Get()->ReloadPlugins(); + a_Output.Out("Plugins reloaded"); + a_Output.Finished(); return; } else if (split[0] == "load") { if (split.size() > 1) { - cPluginManager::Get()->LoadPlugin(split[1]); - - return; + a_Output.Out(cPluginManager::Get()->LoadPlugin(split[1]) ? "Plugin loaded" : "Error occurred loading plugin"); } else { - a_Output.Out("No plugin given! Command: load <pluginname>"); - a_Output.Finished(); - return; + a_Output.Out("Usage: load <pluginname>"); } + a_Output.Finished(); + return; } else if (split[0] == "unload") { if (split.size() > 1) { cPluginManager::Get()->RemovePlugin(cPluginManager::Get()->GetPlugin(split[1])); - return; + a_Output.Out("Plugin unloaded"); } else { - a_Output.Out("No plugin given! Command: unload <pluginname>"); - a_Output.Finished(); - return; + a_Output.Out("Usage: unload <pluginname>"); } + a_Output.Finished(); + return; + } + if (split[0] == "destroyentities") + { + class WorldCallback : public cWorldListCallback + { + virtual bool Item(cWorld * a_World) override + { + class EntityCallback : public cEntityCallback + { + virtual bool Item(cEntity * a_Entity) override + { + if (!a_Entity->IsPlayer()) + { + a_Entity->Destroy(); + } + return false; + } + } EC; + a_World->ForEachEntity(EC); + return false; + } + } WC; + cRoot::Get()->ForEachWorld(WC); + a_Output.Out("Destroyed all entities"); + a_Output.Finished(); + return; } // There is currently no way a plugin can do these (and probably won't ever be): @@ -602,6 +626,7 @@ void cServer::BindBuiltInConsoleCommands(void) PlgMgr->BindConsoleCommand("chunkstats", NULL, " - Displays detailed chunk memory statistics"); PlgMgr->BindConsoleCommand("load <pluginname>", NULL, " - Adds and enables the specified plugin"); PlgMgr->BindConsoleCommand("unload <pluginname>", NULL, " - Disables the specified plugin"); + PlgMgr->BindConsoleCommand("destroyentities", NULL, " - Destroys all entities in all worlds"); #if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER) PlgMgr->BindConsoleCommand("dumpmem", NULL, " - Dumps all used memory blocks together with their callstacks into memdump.xml"); diff --git a/src/World.cpp b/src/World.cpp index 69d1217f1..4e9126193 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1226,24 +1226,26 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo return; } - // TODO: Add damage to entities and implement block hardiness + // TODO: Implement block hardiness Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ); cVector3iArray BlocksAffected; m_ChunkMap->DoExplosionAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected); BroadcastSoundEffect("random.explode", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 0.6f); + { cCSLock Lock(m_CSPlayers); for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { cClientHandle * ch = (*itr)->GetClientHandle(); - if ((ch == NULL) || !ch->IsLoggedIn() || ch->IsDestroyed()) + if (ch == NULL) { continue; } + Vector3d distance_explosion = (*itr)->GetPosition() - explosion_pos; if (distance_explosion.SqrLength() < 4096.0) { - double real_distance = std::max(0.004, sqrt(distance_explosion.SqrLength())); + double real_distance = std::max(0.004, distance_explosion.Length()); double power = a_ExplosionSize / real_distance; if (power <= 1) { @@ -1255,6 +1257,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo } } } + cPluginManager::Get()->CallHookExploded(*this, a_ExplosionSize, a_CanCauseFire, a_BlockX, a_BlockY, a_BlockZ, a_Source, a_SourceData); } diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index e435a1b1f..68e541eba 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -615,7 +615,6 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile) { m_Writer.BeginCompound(""); AddBasicEntity(a_Projectile, a_Projectile->GetMCAClassName()); - Vector3d Pos = a_Projectile->GetPosition(); m_Writer.AddByte("inGround", a_Projectile->IsInGround() ? 1 : 0); switch (a_Projectile->GetProjectileKind()) |