summaryrefslogtreecommitdiffstats
path: root/src/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World.cpp')
-rw-r--r--src/World.cpp111
1 files changed, 91 insertions, 20 deletions
diff --git a/src/World.cpp b/src/World.cpp
index 474f77b81..7d63a8a52 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -259,9 +259,9 @@ void cWorld::cTickThread::Execute(void)
////////////////////////////////////////////////////////////////////////////////
// cWorld:
-cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_OverworldName) :
+cWorld::cWorld(const AString & a_WorldName, eDimension a_Dimension, const AString & a_LinkedOverworldName) :
m_WorldName(a_WorldName),
- m_OverworldName(a_OverworldName),
+ m_LinkedOverworldName(a_LinkedOverworldName),
m_IniFileName(m_WorldName + "/world.ini"),
m_StorageSchema("Default"),
#ifdef __arm__
@@ -604,12 +604,12 @@ void cWorld::Start(void)
if (GetDimension() == dimOverworld)
{
- m_NetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether");
- m_EndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end");
+ m_LinkedNetherWorldName = IniFile.GetValueSet("LinkedWorlds", "NetherWorldName", GetName() + "_nether");
+ m_LinkedEndWorldName = IniFile.GetValueSet("LinkedWorlds", "EndWorldName", GetName() + "_end");
}
else
{
- m_OverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
+ m_LinkedOverworldName = IniFile.GetValueSet("LinkedWorlds", "OverworldName", GetLinkedOverworldName());
}
// Adjust the enum-backed variables into their respective bounds:
@@ -667,18 +667,23 @@ void cWorld::Start(void)
void cWorld::GenerateRandomSpawn(void)
{
LOGD("Generating random spawnpoint...");
-
+ bool foundSpawnPoint = false;
// Look for a spawn point at most 100 chunks away from map center:
for (int i = 0; i < 100; i++)
{
EMCSBiome biome = GetBiomeAt((int)m_SpawnX, (int)m_SpawnZ);
+
if (
(biome != biOcean) && (biome != biFrozenOcean) && // The biome is acceptable (don't want a small ocean island)
!IsBlockWaterOrIce(GetBlock((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ)) // The terrain is acceptable (don't want to spawn inside a lake / river)
)
{
- // A good spawnpoint was found
- break;
+ if (CheckPlayerSpawnPoint((int)m_SpawnX, GetHeight((int)m_SpawnX, (int)m_SpawnZ), (int)m_SpawnZ))
+ {
+ // A good spawnpoint was found
+ foundSpawnPoint = true;
+ break;
+ }
}
// Try a neighboring chunk:
if ((GetTickRandomNumber(4) % 2) == 0) // Randomise whether to increment X or Z coords
@@ -692,8 +697,60 @@ void cWorld::GenerateRandomSpawn(void)
} // for i - 100*
m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // 1.6f to accomodate player height
+ if (foundSpawnPoint)
+ {
+ LOGINFO("Generated random spawnpoint position at {%i, %i, %i}", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ);
+ }
+ else
+ {
+ LOGINFO("Did not find an acceptable spawnpoint. Generated a random spawnpoint position at {%i, %i, %i}", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ);
+ } // Maybe widen the search instead?
+
+}
+
+
+
+
+
+bool cWorld::CheckPlayerSpawnPoint(int a_PosX, int a_PosY, int a_PosZ)
+{
+ // Check that spawnblock and surrounding blocks are neither solid nor water / lava
+ static const struct
+ {
+ int x, z;
+ } Coords[] =
+ {
+ { 0, 0 },
+ { -1, 0 },
+ { 1, 0 },
+ { 0, -1 },
+ { 0, 1 },
+ };
+ for (size_t i = 0; i < ARRAYCOUNT(Coords); i++)
+ {
+ BLOCKTYPE BlockType = GetBlock(a_PosX + Coords[i].x, a_PosY, a_PosZ + Coords[i].x);
+ if (cBlockInfo::IsSolid(BlockType) || IsBlockLiquid(BlockType))
+ {
+ return false;
+ }
+ } // for i - Coords[]
- LOGINFO("Generated random spawnpoint position {%i, %i, %i}", (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ);
+ // Check that the block below is solid:
+ if (!cBlockInfo::IsSolid(GetBlock(a_PosX, a_PosY - 1, a_PosZ)))
+ {
+ return false;
+ }
+
+ // Check that all the blocks above the spawnpoint are not solid:
+ for (int i = a_PosY; i < cChunkDef::Height; i++)
+ {
+ BLOCKTYPE BlockType = GetBlock(a_PosX, i, a_PosZ);
+ if (cBlockInfo::IsSolid(BlockType))
+ {
+ return false;
+ }
+ }
+ return true;
}
@@ -827,18 +884,18 @@ void cWorld::Stop(void)
IniFile.ReadFile(m_IniFileName);
if (GetDimension() == dimOverworld)
{
- IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_NetherWorldName);
- IniFile.SetValue("LinkedWorlds", "EndWorldName", m_EndWorldName);
+ IniFile.SetValue("LinkedWorlds", "NetherWorldName", m_LinkedNetherWorldName);
+ IniFile.SetValue("LinkedWorlds", "EndWorldName", m_LinkedEndWorldName);
}
else
{
- IniFile.SetValue("LinkedWorlds", "OverworldName", m_OverworldName);
+ IniFile.SetValue("LinkedWorlds", "OverworldName", m_LinkedOverworldName);
}
- IniFile.SetValueI("Physics", "TNTShrapnelLevel", (int)m_TNTShrapnelLevel);
+ IniFile.SetValueI("Physics", "TNTShrapnelLevel", static_cast<int>(m_TNTShrapnelLevel));
IniFile.SetValueB("Mechanics", "CommandBlocksEnabled", m_bCommandBlocksEnabled);
IniFile.SetValueB("Mechanics", "UseChatPrefixes", m_bUseChatPrefixes);
IniFile.SetValueB("General", "IsDaylightCycleEnabled", m_IsDaylightCycleEnabled);
- IniFile.SetValueI("General", "Weather", (int)m_Weather);
+ IniFile.SetValueI("General", "Weather", static_cast<int>(m_Weather));
IniFile.SetValueI("General", "TimeInTicks", GetTimeOfDay());
IniFile.WriteFile(m_IniFileName);
@@ -2851,6 +2908,20 @@ bool cWorld::ForEachEntityInBox(const cBoundingBox & a_Box, cEntityCallback & a_
bool cWorld::DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback)
{
+ // First check the entities-to-add:
+ {
+ cCSLock Lock(m_CSEntitiesToAdd);
+ for (auto & ent: m_EntitiesToAdd)
+ {
+ if (ent->GetUniqueID() == a_UniqueID)
+ {
+ a_Callback.Item(ent);
+ return true;
+ }
+ } // for ent - m_EntitiesToAdd[]
+ }
+
+ // Then check the chunkmap:
return m_ChunkMap->DoWithEntityByID(a_UniqueID, a_Callback);
}
@@ -3096,14 +3167,14 @@ void cWorld::SaveAllChunks(void)
void cWorld::QueueSaveAllChunks(void)
{
- QueueTask(make_unique<cWorld::cTaskSaveAllChunks>());
+ QueueTask(std::make_shared<cWorld::cTaskSaveAllChunks>());
}
-void cWorld::QueueTask(std::unique_ptr<cTask> a_Task)
+void cWorld::QueueTask(cTaskPtr a_Task)
{
cCSLock Lock(m_CSTasks);
m_Tasks.push_back(std::move(a_Task));
@@ -3113,7 +3184,7 @@ void cWorld::QueueTask(std::unique_ptr<cTask> a_Task)
-void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
+void cWorld::ScheduleTask(int a_DelayTicks, cTaskPtr a_Task)
{
Int64 TargetTick = a_DelayTicks + std::chrono::duration_cast<cTickTimeLong>(m_WorldAge).count();
@@ -3123,11 +3194,11 @@ void cWorld::ScheduleTask(int a_DelayTicks, cTask * a_Task)
{
if ((*itr)->m_TargetTick >= TargetTick)
{
- m_ScheduledTasks.insert(itr, make_unique<cScheduledTask>(TargetTick, a_Task));
+ m_ScheduledTasks.insert(itr, cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
return;
}
}
- m_ScheduledTasks.push_back(make_unique<cScheduledTask>(TargetTick, a_Task));
+ m_ScheduledTasks.push_back(cScheduledTaskPtr(new cScheduledTask(TargetTick, a_Task)));
}
@@ -3578,7 +3649,7 @@ void cWorld::cTaskUnloadUnusedChunks::Run(cWorld & a_World)
////////////////////////////////////////////////////////////////////////////////
-// cWorld::cTaskSendBlockTo
+// cWorld::cTaskSendBlockToAllPlayers
cWorld::cTaskSendBlockToAllPlayers::cTaskSendBlockToAllPlayers(std::vector<Vector3i> & a_SendQueue) :
m_SendQueue(a_SendQueue)