diff options
Diffstat (limited to 'src/World.cpp')
-rw-r--r-- | src/World.cpp | 111 |
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) |