From 86c081190db89a03f8ff77bf5c05ba2093380283 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Fri, 13 Dec 2024 13:56:32 +0100 Subject: [PATCH] Planet: Split chunk creation and chunk generation Allows to generate only empty chunks --- include/CommonLib/Planet.hpp | 1 + src/CommonLib/Planet.cpp | 97 +++++++++++++---------- src/ServerLib/ServerPlanetEnvironment.cpp | 10 ++- 3 files changed, 62 insertions(+), 46 deletions(-) diff --git a/include/CommonLib/Planet.hpp b/include/CommonLib/Planet.hpp index 56a03de..024d653 100644 --- a/include/CommonLib/Planet.hpp +++ b/include/CommonLib/Planet.hpp @@ -34,6 +34,7 @@ namespace tsom ~Planet() = default; Chunk& AddChunk(const BlockLibrary& blockLibrary, const ChunkIndices& indices, const Nz::FunctionRef& initCallback = nullptr); + void AddChunks(const BlockLibrary& blockLibrary, const Nz::Vector3ui& chunkCount); GravityForce ComputeGravity(const Nz::Vector3f& position) const override; Nz::Vector3f ComputeUpDirection(const Nz::Vector3f& position) const; diff --git a/src/CommonLib/Planet.cpp b/src/CommonLib/Planet.cpp index 9eaa685..e7a36ef 100644 --- a/src/CommonLib/Planet.cpp +++ b/src/CommonLib/Planet.cpp @@ -92,6 +92,18 @@ namespace tsom return *it->second.chunk; } + void Planet::AddChunks(const BlockLibrary& blockLibrary, const Nz::Vector3ui& chunkCount) + { + for (int chunkZ = 0; chunkZ < chunkCount.z; ++chunkZ) + { + for (int chunkY = 0; chunkY < chunkCount.y; ++chunkY) + { + for (int chunkX = 0; chunkX < chunkCount.x; ++chunkX) + AddChunk(blockLibrary, { chunkX - int(chunkCount.x / 2), chunkY - int(chunkCount.y / 2), chunkZ - int(chunkCount.z / 2) }); + } + } + } + auto Planet::ComputeGravity(const Nz::Vector3f& position) const -> GravityForce { constexpr float PlanetGravityCenterStartDecrease = 16.f; @@ -488,62 +500,61 @@ namespace tsom sol::protected_function generationFunction; }; - std::mutex threadMutex; - std::unordered_map> threadStates; + struct GenerationContext + { + std::mutex threadMutex; + std::unordered_map> threadStates; + }; + + auto context = std::make_shared(); - for (int chunkZ = 0; chunkZ < chunkCount.z; ++chunkZ) + ForEachChunk([=, &taskScheduler](const ChunkIndices& chunkIndices, Chunk& chunk) { - for (int chunkY = 0; chunkY < chunkCount.y; ++chunkY) + if (chunk.HasContent()) + return; + + taskScheduler.AddTask([=, &chunk] { - for (int chunkX = 0; chunkX < chunkCount.x; ++chunkX) + ThreadState* currentThreadState = nullptr; { - auto& chunk = AddChunk(blockLibrary, { chunkX - int(chunkCount.x / 2), chunkY - int(chunkCount.y / 2), chunkZ - int(chunkCount.z / 2) }); - taskScheduler.AddTask([&] + std::unique_lock lock(context->threadMutex); + auto id = std::this_thread::get_id(); + auto it = context->threadStates.find(id); + if (it == context->threadStates.end()) { - ThreadState* currentThreadState = nullptr; - { - std::unique_lock lock(threadMutex); - auto id = std::this_thread::get_id(); - auto it = threadStates.find(id); - if (it == threadStates.end()) - { - lock.unlock(); + lock.unlock(); - std::unique_ptr threadState = std::make_unique(m_app); - threadState->scriptingContext.RegisterLibrary(); - threadState->scriptingContext.RegisterLibrary(); + std::unique_ptr threadState = std::make_unique(m_app); + threadState->scriptingContext.RegisterLibrary(); + threadState->scriptingContext.RegisterLibrary(); - Nz::Result execResult = threadState->scriptingContext.LoadFile(fmt::format("scripts/planets/{}.lua", scriptName)); - if (!execResult) - return; + Nz::Result execResult = threadState->scriptingContext.LoadFile(fmt::format("scripts/planets/{}.lua", scriptName)); + if (!execResult) + return; - threadState->generationFunction = execResult.GetValue(); + threadState->generationFunction = execResult.GetValue(); - currentThreadState = threadState.get(); + currentThreadState = threadState.get(); - lock.lock(); - threadStates.emplace(id, std::move(threadState)); - } - else - currentThreadState = it->second.get(); - } + lock.lock(); + context->threadStates.emplace(id, std::move(threadState)); + } + else + currentThreadState = it->second.get(); + } - chunk.LockWrite(); - NAZARA_DEFER({ chunk.UnlockWrite(); }); + chunk.LockWrite(); + NAZARA_DEFER({ chunk.UnlockWrite(); }); - auto result = currentThreadState->generationFunction(chunk, seed, chunkCount); - if (!result.valid()) - { - sol::error err = result; - fmt::print("chunk {};{};{} failed to generate: {}", chunkX, chunkY, chunkZ, err.what()); - return; - } - }); + auto result = currentThreadState->generationFunction(chunk, seed, chunkCount); + if (!result.valid()) + { + sol::error err = result; + fmt::print("chunk {};{};{} failed to generate: {}", chunkIndices.x, chunkIndices.y, chunkIndices.z, err.what()); + return; } - } - } - - taskScheduler.WaitForTasks(); + }); + }); } void Planet::GeneratePlatform(const BlockLibrary& blockLibrary, Direction upDirection, const BlockIndices& platformCenter) diff --git a/src/ServerLib/ServerPlanetEnvironment.cpp b/src/ServerLib/ServerPlanetEnvironment.cpp index 48dc0c7..77e0dce 100644 --- a/src/ServerLib/ServerPlanetEnvironment.cpp +++ b/src/ServerLib/ServerPlanetEnvironment.cpp @@ -56,15 +56,19 @@ namespace tsom auto& taskScheduler = app.GetComponent(); auto& planetComponent = m_planetEntity.get(); + planetComponent.planet->AddChunks(blockLibrary, chunkCount); + + if (!m_savePath.empty()) + LoadFromDirectory(); + planetComponent.planet->GenerateChunks(blockLibrary, taskScheduler, seed, chunkCount, "alice"); + taskScheduler.WaitForTasks(); + planetComponent.planet->GeneratePlatform(blockLibrary, tsom::Direction::Right, { 65, -18, -39 }); planetComponent.planet->GeneratePlatform(blockLibrary, tsom::Direction::Back, { -34, 2, 53 }); planetComponent.planet->GeneratePlatform(blockLibrary, tsom::Direction::Front, { 22, -35, -59 }); planetComponent.planet->GeneratePlatform(blockLibrary, tsom::Direction::Down, { 23, -62, 26 }); - if (!m_savePath.empty()) - LoadFromDirectory(); - planetComponent.planet->OnChunkUpdated.Connect([this](ChunkContainer* /*planet*/, Chunk* chunk, DirectionMask /*neighborMask*/) { m_dirtyChunks.insert(chunk->GetIndices());