summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/BlockEntities/CommandBlockEntity.cpp25
-rw-r--r--src/ChunkMap.cpp67
-rw-r--r--src/Entities/ItemFrame.cpp1
-rw-r--r--src/Items/ItemHandler.h2
-rw-r--r--src/Root.cpp14
-rw-r--r--src/Server.cpp55
-rw-r--r--src/World.cpp9
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp1
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())