summaryrefslogtreecommitdiffstats
path: root/src/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World.cpp')
-rw-r--r--src/World.cpp142
1 files changed, 123 insertions, 19 deletions
diff --git a/src/World.cpp b/src/World.cpp
index 8e7b6171c..5205c2616 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -12,6 +12,7 @@
#include "ChunkMap.h"
#include "Generating/ChunkDesc.h"
#include "OSSupport/Timer.h"
+#include "WorldStorage/ScoreboardSerializer.h"
// Entities (except mobs):
#include "Entities/ExpOrb.h"
@@ -21,6 +22,8 @@
#include "Entities/Player.h"
#include "Entities/TNTEntity.h"
+#include "BlockEntities/CommandBlockEntity.h"
+
// Simulators:
#include "Simulator/SimulatorManager.h"
#include "Simulator/FloodyFluidSimulator.h"
@@ -231,7 +234,11 @@ cWorld::cWorld(const AString & a_WorldName) :
m_WorldName(a_WorldName),
m_IniFileName(m_WorldName + "/world.ini"),
m_StorageSchema("Default"),
+#ifdef _arm_
+ m_StorageCompressionFactor(0),
+#else
m_StorageCompressionFactor(6),
+#endif
m_IsSpawnExplicitlySet(false),
m_WorldAgeSecs(0),
m_TimeOfDaySecs(0),
@@ -242,11 +249,16 @@ cWorld::cWorld(const AString & a_WorldName) :
m_Weather(eWeather_Sunny),
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
m_GeneratorCallbacks(*this),
- m_TickThread(*this)
+ m_TickThread(*this),
+ m_Scoreboard(this)
{
LOGD("cWorld::cWorld(\"%s\")", a_WorldName.c_str());
cFile::CreateFolder(FILE_IO_PREFIX + m_WorldName);
+
+ // Load the scoreboard
+ cScoreboardSerializer Serializer(m_WorldName, &m_Scoreboard);
+ Serializer.Load();
}
@@ -266,6 +278,10 @@ cWorld::~cWorld()
m_Storage.WaitForFinish();
+ // Unload the scoreboard
+ cScoreboardSerializer Serializer(m_WorldName, &m_Scoreboard);
+ Serializer.Save();
+
delete m_ChunkMap;
}
@@ -513,7 +529,7 @@ void cWorld::Start(void)
}
m_StorageSchema = IniFile.GetValueSet ("Storage", "Schema", m_StorageSchema);
- m_StorageCompressionFactor = IniFile.GetValueSetI ("Storage", "CompressionFactor", m_StorageCompressionFactor);
+ m_StorageCompressionFactor = IniFile.GetValueSetI("Storage", "CompressionFactor", m_StorageCompressionFactor);
m_MaxCactusHeight = IniFile.GetValueSetI("Plants", "MaxCactusHeight", 3);
m_MaxSugarcaneHeight = IniFile.GetValueSetI("Plants", "MaxSugarcaneHeight", 3);
m_IsCactusBonemealable = IniFile.GetValueSetB("Plants", "IsCactusBonemealable", false);
@@ -530,6 +546,7 @@ void cWorld::Start(void)
m_bEnabledPVP = IniFile.GetValueSetB("PVP", "Enabled", true);
m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", false);
m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
+ m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false);
m_GameMode = (eGameMode)IniFile.GetValueSetI("GameMode", "GameMode", m_GameMode);
@@ -865,28 +882,27 @@ void cWorld::TickQueuedTasks(void)
} // for itr - m_Tasks[]
}
-void cWorld::TickScheduledTasks()
+
+
+
+
+void cWorld::TickScheduledTasks(void)
{
- ScheduledTaskList Tasks;
// Make a copy of the tasks to avoid deadlocks on accessing m_Tasks
+ cScheduledTasks Tasks;
{
cCSLock Lock(m_CSScheduledTasks);
- ScheduledTaskList::iterator itr = m_ScheduledTasks.begin();
- while (itr != m_ScheduledTasks.end() && (*itr)->Ticks > 0)
+ while (!m_ScheduledTasks.empty() && (m_ScheduledTasks.front()->m_TargetTick < m_WorldAge))
{
Tasks.push_back(m_ScheduledTasks.front());
m_ScheduledTasks.pop_front();
}
- for(;itr != m_ScheduledTasks.end(); itr++)
- {
- (*itr)->Ticks--;
- }
}
// Execute and delete each task:
- for (ScheduledTaskList::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
+ for (cScheduledTasks::iterator itr = Tasks.begin(), end = Tasks.end(); itr != end; ++itr)
{
- (*itr)->Run(*this);
+ (*itr)->m_Task->Run(*this);
delete *itr;
} // for itr - m_Tasks[]
}
@@ -1982,6 +1998,60 @@ void cWorld::BroadcastRemoveEntityEffect(const cEntity & a_Entity, int a_EffectI
+void cWorld::BroadcastScoreboardObjective(const AString & a_Name, const AString & a_DisplayName, Byte a_Mode)
+{
+ 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())
+ {
+ continue;
+ }
+ ch->SendScoreboardObjective(a_Name, a_DisplayName, a_Mode);
+ }
+}
+
+
+
+
+
+void cWorld::BroadcastScoreUpdate(const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode)
+{
+ 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())
+ {
+ continue;
+ }
+ ch->SendScoreUpdate(a_Objective, a_Player, a_Score, a_Mode);
+ }
+}
+
+
+
+
+
+void cWorld::BroadcastDisplayObjective(const AString & a_Objective, cScoreboard::eDisplaySlot a_Display)
+{
+ 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())
+ {
+ continue;
+ }
+ ch->SendDisplayObjective(a_Objective, a_Display);
+ }
+}
+
+
+
+
+
void cWorld::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch, const cClientHandle * a_Exclude)
{
m_ChunkMap->BroadcastSoundEffect(a_SoundName, a_SrcX, a_SrcY, a_SrcZ, a_Volume, a_Pitch, a_Exclude);
@@ -2353,7 +2423,7 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCa
// TODO: This interface is dangerous!
-cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit)
+cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit, bool a_CheckLineOfSight)
{
cTracer LineOfSight(this);
@@ -2368,7 +2438,12 @@ cPlayer * cWorld::FindClosestPlayer(const Vector3f & a_Pos, float a_SightLimit)
if (Distance < ClosestDistance)
{
- if (!LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length()))
+ if (a_CheckLineOfSight && !LineOfSight.Trace(a_Pos,(Pos - a_Pos),(int)(Pos - a_Pos).Length()))
+ {
+ ClosestDistance = Distance;
+ ClosestPlayer = *itr;
+ }
+ else
{
ClosestDistance = Distance;
ClosestPlayer = *itr;
@@ -2548,6 +2623,28 @@ bool cWorld::UpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString
+bool cWorld::SetCommandBlockCommand(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Command)
+{
+ class cUpdateCommandBlock : public cCommandBlockCallback
+ {
+ AString m_Command;
+ public:
+ cUpdateCommandBlock(const AString & a_Command) : m_Command(a_Command) {}
+
+ virtual bool Item(cCommandBlockEntity * a_CommandBlock) override
+ {
+ a_CommandBlock->SetCommand(m_Command);
+ return false;
+ }
+ } CmdBlockCB (a_Command);
+
+ return DoWithCommandBlockAt(a_BlockX, a_BlockY, a_BlockZ, CmdBlockCB);
+}
+
+
+
+
+
void cWorld::ChunksStay(const cChunkCoordsList & a_Chunks, bool a_Stay)
{
m_ChunkMap->ChunksStay(a_Chunks, a_Stay);
@@ -2632,18 +2729,25 @@ void cWorld::QueueTask(cTask * a_Task)
m_Tasks.push_back(a_Task);
}
-void cWorld::ScheduleTask(cScheduledTask * a_Task)
+
+
+
+
+void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
{
+ Int64 TargetTick = a_DelayTicks + m_WorldAge;
+
+ // Insert the task into the list of scheduled tasks, ordered by its target tick
cCSLock Lock(m_CSScheduledTasks);
- for(ScheduledTaskList::iterator itr = m_ScheduledTasks.begin(); itr != m_ScheduledTasks.end(); itr++)
+ for (cScheduledTasks::iterator itr = m_ScheduledTasks.begin(), end = m_ScheduledTasks.end(); itr != end; ++itr)
{
- if((*itr)->Ticks >= a_Task->Ticks)
+ if ((*itr)->m_TargetTick >= TargetTick)
{
- m_ScheduledTasks.insert(itr, a_Task);
+ m_ScheduledTasks.insert(itr, new cScheduledTask(TargetTick, a_Task));
return;
}
}
- m_ScheduledTasks.push_back(a_Task);
+ m_ScheduledTasks.push_back(new cScheduledTask(TargetTick, a_Task));
}