Skip to content

Commit

Permalink
Basic world storing
Browse files Browse the repository at this point in the history
Deprecate ChunkUpdatePool
  • Loading branch information
AdamYuan committed Nov 30, 2023
1 parent ef23be5 commit ba84bfd
Show file tree
Hide file tree
Showing 26 changed files with 358 additions and 344 deletions.
1 change: 0 additions & 1 deletion client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ add_executable(HyperCraft_client
src/WorldWorker.cpp
src/ChunkPool.cpp
src/ChunkTaskPool.cpp
src/ChunkUpdatePool.cpp
src/ChunkGenerateTask.cpp
src/ChunkMeshTask.cpp
src/ChunkSetSunlightTask.cpp
Expand Down
19 changes: 5 additions & 14 deletions client/include/client/ChunkFloodSunlightTask.inl
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,15 @@ template <>
class ChunkTaskData<ChunkTaskType::kFloodSunlight> final : public ChunkTaskDataBase<ChunkTaskType::kFloodSunlight> {
private:
std::vector<InnerIndex2> m_xz_updates;
bool m_high_priority{false};

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kFloodSunlight;

inline void Push(InnerIndex2 xz_update, bool high_priority = false) {
m_xz_updates.push_back(xz_update);
m_high_priority |= high_priority;
}
inline void Push(std::span<const InnerIndex2> xz_updates, bool high_priority = false) {
inline void Push(InnerIndex2 xz_update) { m_xz_updates.push_back(xz_update); }
inline void Push(std::span<const InnerIndex2> xz_updates) {
m_xz_updates.insert(m_xz_updates.end(), xz_updates.begin(), xz_updates.end());
m_high_priority |= high_priority;
}
inline ChunkTaskPriority GetPriority() const {
return m_high_priority ? ChunkTaskPriority::kHigh : ChunkTaskPriority::kLow;
}
inline ChunkTaskPriority GetPriority() const { return ChunkTaskPriority::kLow; }
inline bool IsQueued() const { return !m_xz_updates.empty(); }
std::optional<ChunkTaskRunnerData<ChunkTaskType::kFloodSunlight>> Pop(const ChunkTaskPoolLocked &task_pool,
const ChunkPos3 &chunk_pos);
Expand All @@ -33,19 +26,17 @@ template <> class ChunkTaskRunnerData<ChunkTaskType::kFloodSunlight> {
private:
std::shared_ptr<Chunk> m_chunk_ptr, m_up_chunk_ptr;
std::vector<InnerIndex2> m_xz_updates;
bool m_high_priority;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kFloodSunlight;

inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr, std::shared_ptr<Chunk> up_chunk_ptr,
std::vector<InnerIndex2> &&xz_updates, bool high_priority)
std::vector<InnerIndex2> &&xz_updates)
: m_chunk_ptr{std::move(chunk_ptr)}, m_up_chunk_ptr{std::move(up_chunk_ptr)},
m_xz_updates{std::move(xz_updates)}, m_high_priority{high_priority} {}
m_xz_updates{std::move(xz_updates)} {}
inline const ChunkPos3 &GetChunkPos() const { return m_chunk_ptr->GetPosition(); }
inline const std::shared_ptr<Chunk> &GetChunkPtr() const { return m_chunk_ptr; }
inline const std::shared_ptr<Chunk> &GetUpChunkPtr() const { return m_up_chunk_ptr; }
inline bool IsHighPriority() const { return m_high_priority; }
inline const auto &GetXZUpdates() const { return m_xz_updates; }
};

Expand Down
21 changes: 18 additions & 3 deletions client/include/client/ChunkGenerateTask.inl
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
#include <client/Chunk.hpp>

#include <common/Data.hpp>

namespace hc::client {

class ClientBase;

template <> class ChunkTaskRunnerData<ChunkTaskType::kGenerate> {
private:
std::shared_ptr<Chunk> m_chunk_ptr;
PackedChunkEntry m_chunk_entry;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kGenerate;
inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr) : m_chunk_ptr{std::move(chunk_ptr)} {}
inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr, PackedChunkEntry &&chunk_entry)
: m_chunk_ptr{std::move(chunk_ptr)}, m_chunk_entry{std::move(chunk_entry)} {}
inline const ChunkPos3 &GetChunkPos() const { return m_chunk_ptr->GetPosition(); }
inline const std::shared_ptr<Chunk> &GetChunkPtr() const { return m_chunk_ptr; }
inline const PackedChunkEntry &GetChunkEntry() const { return m_chunk_entry; }
};

template <> class ChunkTaskData<ChunkTaskType::kGenerate> final : public ChunkTaskDataBase<ChunkTaskType::kGenerate> {
private:
bool m_queued{false};
PackedChunkEntry m_chunk_entry;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kGenerate;

inline void Push() { m_queued = true; }
inline void Push(PackedChunkEntry &&chunk_entry) {
m_chunk_entry = std::move(chunk_entry);
m_queued = true;
}
inline constexpr ChunkTaskPriority GetPriority() const { return ChunkTaskPriority::kLow; }
inline bool IsQueued() const { return m_queued; }
std::optional<ChunkTaskRunnerData<ChunkTaskType::kGenerate>> Pop(const ChunkTaskPoolLocked &task_pool,
const ChunkPos3 &chunk_pos);

inline void OnUnload() { m_queued = false; }
inline void OnUnload() {
m_chunk_entry.sunlights.clear();
m_chunk_entry.sunlights.shrink_to_fit();
m_chunk_entry.blocks.clear();
m_chunk_entry.blocks.shrink_to_fit();
m_queued = false;
}
};

template <> class ChunkTaskRunner<ChunkTaskType::kGenerate> {
Expand Down
41 changes: 21 additions & 20 deletions client/include/client/ChunkSetBlockTask.inl
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
#include <client/Chunk.hpp>
#include <client/ChunkUpdate.hpp>

#include <common/Data.hpp>

namespace hc::client {

class ClientBase;

template <> class ChunkTaskData<ChunkTaskType::kSetBlock> final : public ChunkTaskDataBase<ChunkTaskType::kSetBlock> {
private:
std::vector<ChunkSetBlock> m_set_blocks;
bool m_high_priority{false};
std::unordered_map<InnerIndex3, ChunkUpdate<block::Block>> m_set_block_map;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kSetBlock;

inline void Push(ChunkSetBlock set_block, bool high_priority = false) {
m_set_blocks.emplace_back(set_block);
m_high_priority |= high_priority;
}
inline void Push(std::span<const ChunkSetBlock> set_blocks, bool high_priority = false) {
m_set_blocks.insert(m_set_blocks.end(), set_blocks.begin(), set_blocks.end());
m_high_priority |= high_priority;
}
inline ChunkTaskPriority GetPriority() const {
return m_high_priority ? ChunkTaskPriority::kHigh : ChunkTaskPriority::kLow;
inline void Push(std::span<const ChunkBlockEntry> set_blocks, ChunkUpdateType type, bool push_back = true) {
if (push_back) {
for (const auto &entry : set_blocks)
m_set_block_map[entry.index].Get(type) = entry.block;
} else {
for (const auto &entry : set_blocks) {
auto &update = m_set_block_map[entry.index];
if (!update.Get(type).has_value())
m_set_block_map[entry.index].Get(type) = entry.block;
}
}
}
inline bool IsQueued() const { return !m_set_blocks.empty(); }
inline ChunkTaskPriority GetPriority() const { return ChunkTaskPriority::kHigh; }
inline bool IsQueued() const { return !m_set_block_map.empty(); }
std::optional<ChunkTaskRunnerData<ChunkTaskType::kSetBlock>> Pop(const ChunkTaskPoolLocked &task_pool,
const ChunkPos3 &chunk_pos);

Expand All @@ -34,18 +37,16 @@ public:
template <> class ChunkTaskRunnerData<ChunkTaskType::kSetBlock> {
private:
std::shared_ptr<Chunk> m_chunk_ptr;
std::vector<ChunkSetBlock> m_set_blocks;
bool m_high_priority{false};
std::unordered_map<InnerIndex3, ChunkUpdate<block::Block>> m_set_block_map;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kSetBlock;
inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr, std::vector<ChunkSetBlock> &&set_blocks,
bool high_priority)
: m_chunk_ptr{std::move(chunk_ptr)}, m_set_blocks{std::move(set_blocks)}, m_high_priority{high_priority} {}
inline bool IsHighPriority() const { return m_high_priority; }
inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr,
std::unordered_map<InnerIndex3, ChunkUpdate<block::Block>> &&set_block_map)
: m_chunk_ptr{std::move(chunk_ptr)}, m_set_block_map{std::move(set_block_map)} {}
inline const ChunkPos3 &GetChunkPos() const { return m_chunk_ptr->GetPosition(); }
inline const std::shared_ptr<Chunk> &GetChunkPtr() const { return m_chunk_ptr; }
inline const auto &GetSetBlocks() const { return m_set_blocks; }
inline const auto &GetSetBlockMap() const { return m_set_block_map; }
};

template <> class ChunkTaskRunner<ChunkTaskType::kSetBlock> {
Expand Down
40 changes: 19 additions & 21 deletions client/include/client/ChunkSetSunlightTask.inl
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@ namespace hc::client {
template <>
class ChunkTaskData<ChunkTaskType::kSetSunlight> final : public ChunkTaskDataBase<ChunkTaskType::kSetSunlight> {
private:
std::vector<ChunkSetSunlight> m_set_sunlights;
bool m_high_priority = false;
std::unordered_map<InnerIndex2, ChunkUpdate<InnerPos1>> m_set_sunlight_map;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kSetSunlight;

inline void Push(ChunkSetSunlight set_sunlight, bool high_priority = false) {
m_set_sunlights.emplace_back(set_sunlight);
m_high_priority |= high_priority;
inline void Push(std::span<const ChunkSunlightEntry> set_sunlights, ChunkUpdateType type, bool push_back = true) {
if (push_back) {
for (const auto &entry : set_sunlights)
m_set_sunlight_map[entry.index].Get(type) = entry.sunlight;
} else {
for (const auto &entry : set_sunlights) {
auto &update = m_set_sunlight_map[entry.index];
if (!update.Get(type).has_value())
m_set_sunlight_map[entry.index].Get(type) = entry.sunlight;
}
}
}
inline void Push(std::span<const ChunkSetSunlight> set_sunlights, bool high_priority = false) {
m_set_sunlights.insert(m_set_sunlights.end(), set_sunlights.begin(), set_sunlights.end());
m_high_priority |= high_priority;
}
inline ChunkTaskPriority GetPriority() const {
return m_high_priority ? ChunkTaskPriority::kHigh : ChunkTaskPriority::kLow;
}
inline bool IsQueued() const { return !m_set_sunlights.empty(); }
inline ChunkTaskPriority GetPriority() const { return ChunkTaskPriority::kLow; }
inline bool IsQueued() const { return !m_set_sunlight_map.empty(); }
std::optional<ChunkTaskRunnerData<ChunkTaskType::kSetSunlight>> Pop(const ChunkTaskPoolLocked &task_pool,
const ChunkPos3 &chunk_pos);

Expand All @@ -33,20 +34,17 @@ public:
template <> class ChunkTaskRunnerData<ChunkTaskType::kSetSunlight> {
private:
std::shared_ptr<Chunk> m_chunk_ptr;
std::vector<ChunkSetSunlight> m_set_sunlights;
bool m_high_priority;
std::unordered_map<InnerIndex2, ChunkUpdate<InnerPos1>> m_set_sunlight_map;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kSetSunlight;

inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr, std::vector<ChunkSetSunlight> &&set_sunlights,
bool high_priority)
: m_chunk_ptr{std::move(chunk_ptr)}, m_set_sunlights{std::move(set_sunlights)}, m_high_priority{high_priority} {
}
inline ChunkTaskRunnerData(std::shared_ptr<Chunk> chunk_ptr,
std::unordered_map<InnerIndex2, ChunkUpdate<InnerPos1>> &&set_sunlight_map)
: m_chunk_ptr{std::move(chunk_ptr)}, m_set_sunlight_map{std::move(set_sunlight_map)} {}
inline const ChunkPos3 &GetChunkPos() const { return m_chunk_ptr->GetPosition(); }
inline const std::shared_ptr<Chunk> &GetChunkPtr() const { return m_chunk_ptr; }
inline const auto &GetSetSunlights() const { return m_set_sunlights; }
inline bool IsHighPriority() const { return m_high_priority; }
inline const auto &GetSetSunlightMap() const { return m_set_sunlight_map; }
};

template <> class ChunkTaskRunner<ChunkTaskType::kSetSunlight> {
Expand Down
34 changes: 21 additions & 13 deletions client/include/client/ChunkTaskPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ template <ChunkTaskType Type> class ChunkTaskDataBase {
friend class ChunkTaskPoolLocked;

public:
[[nodiscard]] inline bool NotIdle() const { return static_cast<const ChunkTaskData<Type> *>(this)->IsQueued() || m_running; }
[[nodiscard]] inline bool NotIdle() const {
return static_cast<const ChunkTaskData<Type> *>(this)->IsQueued() || m_running;
}
[[nodiscard]] inline bool IsRunning() const { return m_running; }
};

} // namespace hc::client
Expand Down Expand Up @@ -107,10 +110,9 @@ class ChunkTaskPool {

template <ChunkTaskType TaskType, typename... Args> inline void Push(const ChunkPos3 &chunk_pos, Args &&...args) {
bool high_priority = false;
m_data_map.uprase_fn(chunk_pos, [&high_priority, ... args = std::forward<Args>(args)](
DataTuple &data_tuple, libcuckoo::UpsertContext) {
m_data_map.uprase_fn(chunk_pos, [&](DataTuple &data_tuple, libcuckoo::UpsertContext) {
auto &data = std::get<static_cast<std::size_t>(TaskType)>(data_tuple);
data.Push(args...);
data.Push(std::forward<Args>(args)...);
high_priority = data.GetPriority() == ChunkTaskPriority::kHigh;
return false;
});
Expand Down Expand Up @@ -149,24 +151,30 @@ class ChunkTaskPoolLocked {

template <ChunkTaskType... TaskTypes> [[nodiscard]] inline bool AllNotIdle(const ChunkPos3 &chunk_pos) const {
auto it = m_data_map.find(chunk_pos);
return !(it == m_data_map.end()) &&
(std::get<static_cast<std::size_t>(TaskTypes)>(it->second).NotIdle() && ...);
return it != m_data_map.end() && (std::get<static_cast<std::size_t>(TaskTypes)>(it->second).NotIdle() && ...);
}
template <ChunkTaskType... TaskTypes> [[nodiscard]] inline bool AnyNotIdle(const ChunkPos3 &chunk_pos) const {
auto it = m_data_map.find(chunk_pos);
return !(it == m_data_map.end()) &&
(std::get<static_cast<std::size_t>(TaskTypes)>(it->second).NotIdle() || ...);
return it != m_data_map.end() && (std::get<static_cast<std::size_t>(TaskTypes)>(it->second).NotIdle() || ...);
}
template <ChunkTaskType... TaskTypes> [[nodiscard]] inline bool AllRunning(const ChunkPos3 &chunk_pos) const {
auto it = m_data_map.find(chunk_pos);
return it != m_data_map.end() && (std::get<static_cast<std::size_t>(TaskTypes)>(it->second).IsRunning() && ...);
}
template <ChunkTaskType... TaskTypes> [[nodiscard]] inline bool AnyRunning(const ChunkPos3 &chunk_pos) const {
auto it = m_data_map.find(chunk_pos);
return it != m_data_map.end() && (std::get<static_cast<std::size_t>(TaskTypes)>(it->second).IsRunning() || ...);
}
template <ChunkTaskType TaskType, typename... Args> inline void Push(const ChunkPos3 &chunk_pos, Args &&...args) {
auto it = m_data_map.insert(chunk_pos).first;
auto &data = std::get<static_cast<std::size_t>(TaskType)>(it->second);
data.Push(args...);
data.Push(std::forward<Args>(args)...);
}
template <ChunkTaskType TaskType, typename Iterator, typename... Args>
/* template <ChunkTaskType TaskType, typename Iterator, typename... Args>
inline void PushBulk(Iterator chunk_pos_begin, Iterator chunk_pos_end, Args &&...args) {
for (Iterator it = chunk_pos_begin; it != chunk_pos_end; ++it)
Push<TaskType>(*it, args...);
}
for (Iterator it = chunk_pos_begin; it != chunk_pos_end; ++it)
Push<TaskType>(*it, args...);
} */

[[nodiscard]] inline const auto &GetDataMap() const { return m_data_map; }
inline auto &GetDataMap() { return m_data_map; }
Expand Down
25 changes: 15 additions & 10 deletions client/include/client/ChunkUpdate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
#include <block/Block.hpp>
#include <cinttypes>
#include <common/Position.hpp>
#include <optional>

namespace hc::client {

enum class ChunkUpdateType { kLocal, kRemote };

struct ChunkSetBlock {
InnerIndex3 index{};
block::Block block;
ChunkUpdateType type{};
};

struct ChunkSetSunlight {
InnerIndex2 index{};
InnerPos1 sunlight{};
ChunkUpdateType type{};
template <typename Data> struct ChunkUpdate {
std::optional<Data> local, remote;
template <ChunkUpdateType Type> inline std::optional<Data> &Get() {
return Type == ChunkUpdateType::kLocal ? local : remote;
}
template <ChunkUpdateType Type> inline const std::optional<Data> &Get() const {
return Type == ChunkUpdateType::kLocal ? local : remote;
}
inline std::optional<Data> &Get(ChunkUpdateType type) { return type == ChunkUpdateType::kLocal ? local : remote; }
inline const std::optional<Data> &Get(ChunkUpdateType type) const {
return type == ChunkUpdateType::kLocal ? local : remote;
}
inline Data GetNew() const { return local.has_value() ? local.value() : remote.value(); }
inline const std::optional<Data> &GetOld() const { return remote; }
};

} // namespace hc::client
18 changes: 14 additions & 4 deletions client/include/client/ChunkUpdateBlockTask.inl
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,25 @@ namespace hc::client {
template <>
class ChunkTaskData<ChunkTaskType::kUpdateBlock> final : public ChunkTaskDataBase<ChunkTaskType::kUpdateBlock> {
private:
std::unordered_map<InnerIndex3, uint64_t> m_updates;
struct UpdateInfo {
uint64_t tick{};
bool activate{};
};
std::unordered_map<InnerIndex3, UpdateInfo> m_updates;

public:
inline static constexpr ChunkTaskType kType = ChunkTaskType::kUpdateBlock;

inline void Push(InnerIndex3 update, uint64_t tick) { m_updates[update] = tick; }
inline void Push(std::span<const InnerIndex3> updates, uint64_t tick) {
// inline void Push(InnerIndex3 update, uint64_t tick) { m_updates[update] = tick; }
inline void Push(std::span<const InnerIndex3> updates, uint64_t tick, std::span<const InnerIndex3> activates) {
for (const auto &pos : updates)
m_updates[pos] = tick;
m_updates[pos].tick = tick;

for (const auto &pos : activates) {
auto it = m_updates.find(pos);
if (it != m_updates.end())
it->second.activate = true;
}
}
inline constexpr ChunkTaskPriority GetPriority() const { return ChunkTaskPriority::kTick; }
inline bool IsQueued() const { return !m_updates.empty(); }
Expand Down
Loading

0 comments on commit ba84bfd

Please sign in to comment.