Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/CommonLib/Chunk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ namespace tsom
Chunk& operator=(const Chunk&) = delete;
Chunk& operator=(Chunk&&) = delete;

NazaraSignal(OnBlockUpdated, Chunk* /*emitter*/, const Nz::Vector3ui& /*indices*/, BlockIndex /*newBlock*/, std::size_t /*prevLayerIndex*/, std::size_t /*newLayerIndex*/);
NazaraSignal(OnBlockUpdated, Chunk* /*emitter*/, const Nz::Vector3ui& /*indices*/, BlockIndex /*oldBlock*/, BlockIndex /*newBlock*/, std::size_t /*prevLayerIndex*/, std::size_t /*newLayerIndex*/);
NazaraSignal(OnLayerRegistered, Chunk* /*emitter*/, std::size_t /*layerIndex*/);
NazaraSignal(OnLayerUnregistered, Chunk* /*emitter*/, std::size_t /*layerIndex*/);
NazaraSignal(OnReset, Chunk* /*emitter*/);
Expand Down
2 changes: 1 addition & 1 deletion include/CommonLib/Components/PlanetComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace tsom
{
struct PlanetComponent
{
std::unique_ptr<Planet> planet;
std::shared_ptr<Planet> planet;
std::array<std::unique_ptr<ChunkEntities>, Constants::MaxChunkLayerCount> planetEntities;
};
}
Expand Down
8 changes: 5 additions & 3 deletions include/CommonLib/Planet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include <tsl/hopscotch_map.h>
#include <memory>
#include <mutex>
#include <vector>

namespace Nz
{
Expand Down Expand Up @@ -44,13 +43,14 @@ namespace tsom
void ForEachChunk(Nz::FunctionRef<void(const ChunkIndices& chunkIndices, Chunk& chunk)> callback) override;
void ForEachChunk(Nz::FunctionRef<void(const ChunkIndices& chunkIndices, const Chunk& chunk)> callback) const override;

void GenerateChunk(const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName);
void GenerateChunks(const BlockLibrary& blockLibrary, Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName);
void GenerateChunk(Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName);
void GenerateChunks(Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName);
void GeneratePlatform(const BlockLibrary& blockLibrary, Direction upDirection, const BlockIndices& platformCenter);

inline Nz::Vector3f GetCenter() const override;
inline Chunk* GetChunk(const ChunkIndices& chunkIndices) override;
inline const Chunk* GetChunk(const ChunkIndices& chunkIndices) const override;
inline DirectionMask GetChunkVisibilityMask(const ChunkIndices& chunkIndices) const;
inline std::size_t GetChunkCount() const override;
inline float GetCornerRadius() const;
inline float GetGravity() const;
Expand All @@ -67,7 +67,9 @@ namespace tsom
protected:
struct ChunkData
{
Nz::EnumArray<Direction, Nz::UInt16> directionHoleCount;
std::shared_ptr<Chunk> chunk;
DirectionMask visibilityMask;

NazaraSlot(Chunk, OnBlockUpdated, onUpdated);
NazaraSlot(Chunk, OnLayerRegistered, onLayerRegistered);
Expand Down
8 changes: 8 additions & 0 deletions include/CommonLib/Planet.inl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ namespace tsom
return it->second.chunk.get();
}

inline DirectionMask Planet::GetChunkVisibilityMask(const ChunkIndices& chunkIndices) const
{
auto it = m_chunks.find(chunkIndices);
NazaraAssert(it != m_chunks.end());

return it->second.visibilityMask;
}

inline std::size_t Planet::GetChunkCount() const
{
return m_chunks.size();
Expand Down
4 changes: 3 additions & 1 deletion include/ServerLib/Database/ServerDatabase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ namespace tsom
void GetAllPlanets(Nz::FunctionRef<bool(Database::Planet&& /*planet*/)> callback) const;
void GetAllPlanetEntities(Nz::UInt32 planetEntityId, Nz::FunctionRef<bool(Database::PlanetEntity&& /*planetEntities*/)> callback) const;
void GetAllPlanetLinks(Nz::FunctionRef<bool(Database::PlanetLink&& /*planetLink*/)> callback) const;
void GetPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;
void GetAllPlanetChunks(Nz::UInt32 planetId, Nz::FunctionRef<bool(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;
bool GetPlanetChunk(Nz::UInt32 planetId, const Nz::Vector3i32& chunkIndices, Nz::FunctionRef<void(Database::PlanetChunk&& /*PlanetChunk*/)> callback) const;

void StorePlanet(const Database::Planet& planetChunk);
void StorePlanetChunk(const Database::PlanetChunk& planetChunk);
Expand Down Expand Up @@ -70,6 +71,7 @@ namespace tsom

SQLite::Statement getAllPlanetQuery;
SQLite::Statement getAllPlanetLinkQuery;
SQLite::Statement getAllPlanetChunksQuery;
SQLite::Statement getPlanetChunkQuery;
SQLite::Statement storePlanetQuery;
SQLite::Statement storePlanetChunkQuery;
Expand Down
3 changes: 2 additions & 1 deletion include/ServerLib/ServerInstance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <ServerLib/ServerPlayer.hpp>
#include <ServerLib/Database/ServerDatabase.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/ThreadLocalData.hpp>
#include <Nazara/Core/TimerManager.hpp>
#include <NazaraUtils/Bitset.hpp>
#include <NazaraUtils/MemoryPool.hpp>
Expand Down Expand Up @@ -133,6 +134,7 @@ namespace tsom
Nz::Bitset<> m_newPlayers;
Nz::MemoryPool<ServerPlayer> m_players;
Nz::MillisecondClock m_saveClock;
Nz::ThreadLocalData<ServerDatabase> m_serverDatabase;
Nz::Time m_tickAccumulator;
Nz::Time m_tickDuration;
Nz::TimerManager m_tickedTimerManager;
Expand All @@ -142,7 +144,6 @@ namespace tsom
Config m_config;
ScriptingContext m_scriptingContext;
EntityRegistry m_entityRegistry;
ServerDatabase m_serverDatabase;
Spawnpoint m_defaultSpawnpoint;
};
}
Expand Down
2 changes: 1 addition & 1 deletion include/ServerLib/ServerInstance.inl
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ namespace tsom

inline ServerDatabase& ServerInstance::GetServerDatabase()
{
return m_serverDatabase;
return m_serverDatabase.GetOrCreate(m_application, m_config.databaseFile);
}

inline Nz::Time ServerInstance::GetTickDuration() const
Expand Down
21 changes: 21 additions & 0 deletions include/ServerLib/ServerPlanetEnvironment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
#include <CommonLib/Chunk.hpp>
#include <ServerLib/ServerAtmosphere.hpp>
#include <ServerLib/ServerEnvironment.hpp>
#include <tsl/hopscotch_set.h>
#include <atomic>
#include <filesystem>
#include <mutex>
#include <optional>
#include <queue>

namespace tsom
{
Expand Down Expand Up @@ -41,6 +45,7 @@ namespace tsom
inline entt::handle GetPlanetEntity() const;

void OnSave() override;
void OnTick(Nz::Time elapsedTime) override;

ServerPlanetEnvironment& operator=(const ServerPlanetEnvironment&) = delete;
ServerPlanetEnvironment& operator=(ServerPlanetEnvironment&&) = delete;
Expand All @@ -50,11 +55,27 @@ namespace tsom
void LoadChunksFromDatabase();
void LoadEntitiesFromDatabase();

struct ChunkLoadingData
{
Nz::Vector3ui chunkCount;
std::atomic_uint chunkLoadingCount;
std::mutex mutex;
std::shared_ptr<Planet> planet;
std::queue<ChunkIndices> remainingChunks;
tsl::hopscotch_set<ChunkIndices> visitedChunks;

void HandleChunkLoaded(const ChunkIndices& chunkIndices);
};

ServerAtmosphere m_atmosphere;
std::filesystem::path m_savePath;
std::optional<Nz::UInt32> m_databaseId;
std::shared_ptr<ChunkLoadingData> m_chunkLoadingData;
std::string m_generatorName;
std::unordered_set<ChunkIndices /*chunkIndex*/> m_dirtyChunks;
entt::handle m_planetEntity;
Nz::UInt32 m_generationSeed;
Nz::Vector3ui m_chunkCount;
};
}

Expand Down
8 changes: 4 additions & 4 deletions src/CommonLib/Chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ namespace tsom
const auto& newBlockData = m_blockLibrary.GetBlockData(newBlock);

unsigned int blockIndex = GetBlockLocalIndex(indices);
BlockIndex oldContent = m_blocks[blockIndex];
const auto& oldBlockData = m_blockLibrary.GetBlockData(oldContent);
BlockIndex oldBlock = m_blocks[blockIndex];
const auto& oldBlockData = m_blockLibrary.GetBlockData(oldBlock);
assert(IsLayerRegistered(oldBlockData.layerIndex));
m_blocks[blockIndex] = newBlock;

Expand All @@ -432,13 +432,13 @@ namespace tsom
m_layers[newBlockData.layerIndex]->collisionCellMasks[blockIndex] = newBlockData.hasCollisions;
m_layers[newBlockData.layerIndex]->blockCount++;

m_blockTypeCount[oldContent]--;
m_blockTypeCount[oldBlock]--;
if (newBlock >= m_blockTypeCount.size())
m_blockTypeCount.resize(newBlock + 1);

m_blockTypeCount[newBlock]++;

OnBlockUpdated(this, indices, newBlock, oldBlockData.layerIndex, newBlockData.layerIndex);
OnBlockUpdated(this, indices, oldBlock, newBlock, oldBlockData.layerIndex, newBlockData.layerIndex);

// Unregister layer only after update to avoid triggering chunk update (OnBlockUpodated)
assert(m_layers[oldBlockData.layerIndex]->blockCount > 0);
Expand Down
2 changes: 1 addition & 1 deletion src/CommonLib/Entities/ChunkClassLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace tsom
Nz::EnttWorld* world = entity.registry()->ctx().get<Nz::EnttWorld*>();

auto& planetComponent = entity.emplace<PlanetComponent>();
planetComponent.planet = std::make_unique<Planet>(m_app, cellSize, cornerRadius, gravity);
planetComponent.planet = std::make_shared<Planet>(m_app, cellSize, cornerRadius, gravity);
for (std::size_t layerIndex = 0; layerIndex < planetComponent.planetEntities.size(); ++layerIndex)
{
if (!m_blockLibrary.IsValidLayer(layerIndex))
Expand Down
115 changes: 109 additions & 6 deletions src/CommonLib/Planet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,83 @@ namespace tsom
OnChunkLayerRemove(this, chunk, layerIndex);
});

chunkData.onReset.Connect(chunkData.chunk->OnReset, [this](Chunk* chunk)
chunkData.onReset.Connect(chunkData.chunk->OnReset, [this, &blockLibrary](Chunk* chunk)
{
// Build direction blockers
auto chunkIt = m_chunks.find(chunk->GetIndices());
NazaraAssert(chunkIt != m_chunks.end());
ChunkData& chunkData = chunkIt.value();
chunkData.directionHoleCount.fill(0);

if (chunk->HasContent())
{
// Left / right
for (unsigned int z = 0; z < ChunkSize; ++z)
{
for (unsigned int y = 0; y < ChunkSize; ++y)
{
BlockIndex leftBlockIndex = chunk->GetBlockContent({ 0, y, z });
BlockIndex rightBlockIndex = chunk->GetBlockContent({ ChunkSize - 1, y, z });

auto& leftBlockData = blockLibrary.GetBlockData(leftBlockIndex);
if (leftBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Left]++;

auto& rightBlockData = blockLibrary.GetBlockData(rightBlockIndex);
if (rightBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Right]++;
}
}

// Front / back
for (unsigned int z = 0; z < ChunkSize; ++z)
{
for (unsigned int x = 0; x < ChunkSize; ++x)
{
BlockIndex frontBlockIndex = chunk->GetBlockContent({ x, 0, z });
BlockIndex backBlockIndex = chunk->GetBlockContent({ x, ChunkSize - 1, z });

auto& frontBlockData = blockLibrary.GetBlockData(frontBlockIndex);
if (frontBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Front]++;

auto& backBlockData = blockLibrary.GetBlockData(backBlockIndex);
if (backBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Back]++;
}
}

// Down / up
for (unsigned int y = 0; y < ChunkSize; ++y)
{
for (unsigned int x = 0; x < ChunkSize; ++x)
{
BlockIndex downBlockIndex = chunk->GetBlockContent({ x, y, 0 });
BlockIndex upBlockIndex = chunk->GetBlockContent({ x, y, ChunkSize - 1 });

auto& downBlockData = blockLibrary.GetBlockData(downBlockIndex);
if (downBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Down]++;

auto& upBlockData = blockLibrary.GetBlockData(upBlockIndex);
if (upBlockData.isTransparent)
chunkData.directionHoleCount[Direction::Up]++;
}
}

for (auto&& [direction, holeCount] : chunkData.directionHoleCount.iter_kv())
{
if (holeCount > 0)
chunkData.visibilityMask |= direction;
}
}

// FIXME: Nz::Signal operator() is not thread-safe!
std::lock_guard lock(m_chunkUpdatedSignalMutex);
OnChunkUpdated(this, chunk, DirectionMask_All, chunk->GetActiveLayerMask());
});

chunkData.onUpdated.Connect(chunkData.chunk->OnBlockUpdated, [this](Chunk* chunk, const Nz::Vector3ui& indices, BlockIndex newBlock, std::size_t oldLayerIndex, std::size_t newLayerIndex)
chunkData.onUpdated.Connect(chunkData.chunk->OnBlockUpdated, [this, &blockLibrary](Chunk* chunk, const Nz::Vector3ui& indices, BlockIndex oldBlock, BlockIndex newBlock, std::size_t oldLayerIndex, std::size_t newLayerIndex)
{
DirectionMask neighborMask;
if (indices.x == 0)
Expand All @@ -91,6 +160,39 @@ namespace tsom
else if (indices.z == chunk->GetSize().z - 1)
neighborMask |= Direction::Up;

if (neighborMask != 0)
{
auto& previousBlockData = blockLibrary.GetBlockData(oldBlock);
auto& newBlockData = blockLibrary.GetBlockData(newBlock);

if (previousBlockData.isTransparent != newBlockData.isTransparent)
{
auto chunkIt = m_chunks.find(chunk->GetIndices());
NazaraAssert(chunkIt != m_chunks.end());
ChunkData& chunkData = chunkIt.value();

if (previousBlockData.isTransparent)
{
// We're putting an opaque block on a transparent one
for (Direction direction : neighborMask)
{
NazaraAssert(chunkData.directionHoleCount[direction] > 0);
if (--chunkData.directionHoleCount[direction] == 0)
chunkData.visibilityMask.Clear(direction);
}
}
else
{
// Replacing an opaque block by a transparent one
for (Direction direction : neighborMask)
{
chunkData.directionHoleCount[direction]++;
chunkData.visibilityMask |= direction;
}
}
}
}

Nz::UInt32 layerMask = 0;
layerMask |= 1u << oldLayerIndex;
if (newBlock != EmptyBlockIndex)
Expand Down Expand Up @@ -228,11 +330,11 @@ namespace tsom
callback(chunkIndices, *chunkData.chunk);
}

void Planet::GenerateChunk(const BlockLibrary& blockLibrary, Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName)
void Planet::GenerateChunk(Chunk& chunk, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName)
{
ChunkIndices chunkIndices = chunk.GetIndices();

ScriptingContext scriptingContext = ScriptingContext(m_app);
ScriptingContext scriptingContext(m_app);
scriptingContext.RegisterLibrary<MathScriptingLibrary>();
scriptingContext.RegisterLibrary<ChunkScriptingLibrary>();

Expand All @@ -254,7 +356,7 @@ namespace tsom
}
}

void Planet::GenerateChunks(const BlockLibrary& blockLibrary, Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string scriptName)
void Planet::GenerateChunks(Nz::TaskScheduler& taskScheduler, Nz::UInt32 seed, const Nz::Vector3ui& chunkCount, std::string_view scriptName)
{
struct ThreadState
{
Expand All @@ -274,6 +376,7 @@ namespace tsom
};

auto context = std::make_shared<GenerationContext>();
std::string scriptPath = fmt::format("scripts/planets/{}.lua", scriptName);

ForEachChunk([=, this, &taskScheduler](const ChunkIndices& chunkIndices, Chunk& chunk)
{
Expand All @@ -295,7 +398,7 @@ namespace tsom
threadState->scriptingContext.RegisterLibrary<MathScriptingLibrary>();
threadState->scriptingContext.RegisterLibrary<ChunkScriptingLibrary>();

Nz::Result execResult = threadState->scriptingContext.LoadFile(fmt::format("scripts/planets/{}.lua", scriptName));
Nz::Result execResult = threadState->scriptingContext.LoadFile(scriptPath);
if (!execResult)
return;

Expand Down
2 changes: 1 addition & 1 deletion src/CommonLib/Ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace tsom
OnChunkUpdated(this, chunk, DirectionMask_All, chunk->GetActiveLayerMask());
});

chunkData.onUpdated.Connect(chunkData.chunk->OnBlockUpdated, [this](Chunk* chunk, const Nz::Vector3ui& indices, BlockIndex newBlock, std::size_t prevLayerIndex, std::size_t newLayerIndex)
chunkData.onUpdated.Connect(chunkData.chunk->OnBlockUpdated, [this](Chunk* chunk, const Nz::Vector3ui& indices, BlockIndex /*oldBlock*/, BlockIndex newBlock, std::size_t prevLayerIndex, std::size_t newLayerIndex)
{
DirectionMask neighborMask;
if (indices.x == 0)
Expand Down
2 changes: 1 addition & 1 deletion src/Game/States/PlanetEditorState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ namespace tsom

m_planet->ClearChunks();
m_planet->AddChunks(*stateData.blockLibrary, m_planetSettings.chunkCount);
m_planet->GenerateChunks(*stateData.blockLibrary, taskScheduler, m_planetSettings.seed, m_planetSettings.chunkCount, m_planetSettings.scriptName);
m_planet->GenerateChunks(taskScheduler, m_planetSettings.seed, m_planetSettings.chunkCount, m_planetSettings.scriptName);
}

void PlanetEditorState::LayoutWidgets(const Nz::Vector2f& /*newSize*/)
Expand Down
Loading
Loading