mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
refactor(gameplay): replace entt components with SparseVector for player data
Refactor client world to use a custom SparseVector for player data instead of entt registry. Consolidate Transform, ViewAngles, and related structs into Position, Orientation, WalkPose. Introduce PlayerData and PlayerRenderData. Remove the unused move_system.cpp. Unify player render and shadow render into a single function.
This commit is contained in:
@@ -8,10 +8,12 @@
|
||||
#include "Cubed/gameplay/client_player.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/network_client.hpp"
|
||||
#include "Cubed/gameplay/player_data.hpp"
|
||||
#include "Cubed/gameplay/world.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/tools/cubed_random.hpp"
|
||||
#include "Cubed/tools/priority_thread_pool.hpp"
|
||||
#include "Cubed/tools/sparse_vector.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <deque>
|
||||
@@ -20,15 +22,6 @@
|
||||
#include <tbb/concurrent_unordered_map.h>
|
||||
namespace Cubed {
|
||||
|
||||
struct PlayerRenderData {
|
||||
std::string name;
|
||||
std::string uuid;
|
||||
glm::vec3 render_pos;
|
||||
float yaw;
|
||||
float pitch;
|
||||
Gait gait;
|
||||
float angle;
|
||||
};
|
||||
class WorldScene;
|
||||
class ClientWorld : public World {
|
||||
public:
|
||||
@@ -146,7 +139,10 @@ private:
|
||||
std::vector<glm::vec4> m_planes;
|
||||
std::jthread m_client_thread;
|
||||
|
||||
mutable std::shared_mutex m_registry_mutex;
|
||||
mutable std::shared_mutex m_players_date_mutex;
|
||||
using PlayerHandle = SparseVector<PlayerData>::Handle;
|
||||
SparseVector<PlayerData> m_players_data;
|
||||
std::unordered_map<std::string, PlayerHandle> m_players_handle;
|
||||
|
||||
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||
tbb::concurrent_queue<ChunkPos> m_dirty_chunk_queue;
|
||||
|
||||
@@ -5,11 +5,18 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
namespace Cubed {
|
||||
struct Transform {
|
||||
glm::vec3 pos{0, 0, 0};
|
||||
glm::vec3 render_pos{0, 0, 0};
|
||||
|
||||
using ModelID = uint32_t;
|
||||
|
||||
struct Position {
|
||||
glm::vec3 value{0.0f};
|
||||
};
|
||||
|
||||
struct WalkPose {
|
||||
Gait gait = Gait::STOP;
|
||||
// for arm roll caculate
|
||||
float walk_time = 0.0f;
|
||||
// for sound play
|
||||
float moving_time = 0.0f;
|
||||
};
|
||||
|
||||
@@ -19,26 +26,22 @@ struct EntityInfo {
|
||||
};
|
||||
|
||||
struct Model {
|
||||
std::string name;
|
||||
ModelID id;
|
||||
};
|
||||
|
||||
struct Health {
|
||||
float hp = 0;
|
||||
float hp = 20;
|
||||
float max_hp = 20;
|
||||
};
|
||||
|
||||
struct ViewAngles {
|
||||
float render_yaw = 0.0f;
|
||||
struct Orientation {
|
||||
float yaw = 0.0f;
|
||||
float render_pitch = 0.0f;
|
||||
float pitch = 0.0f;
|
||||
float angle = 0.0f;
|
||||
float roll = 0.0f;
|
||||
};
|
||||
|
||||
struct Velocity {
|
||||
float dx = 0.0f;
|
||||
float dy = 0.0f;
|
||||
float dz = 0.0f;
|
||||
glm::vec3 value{0.0f};
|
||||
};
|
||||
|
||||
struct HitBoxes {
|
||||
|
||||
20
include/Cubed/gameplay/player_data.hpp
Normal file
20
include/Cubed/gameplay/player_data.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/entity.hpp"
|
||||
namespace Cubed {
|
||||
struct PlayerData {
|
||||
Position pos{};
|
||||
Position render_pos{};
|
||||
EntityInfo entity{};
|
||||
WalkPose walk{};
|
||||
Orientation angle{};
|
||||
Orientation render_angle{};
|
||||
};
|
||||
|
||||
struct PlayerRenderData {
|
||||
EntityInfo info{};
|
||||
Position render_pos{};
|
||||
Orientation angle{};
|
||||
Gait gait{};
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -13,8 +13,7 @@ public:
|
||||
PlayerRenderer(Renderer& renderer);
|
||||
~PlayerRenderer();
|
||||
void init();
|
||||
void render(const Shader& shader, ClientWorld& world);
|
||||
void shadow_render(const Shader& shader, ClientWorld& world);
|
||||
void render(const Shader& shader, ClientWorld& world, bool shadow_render);
|
||||
|
||||
private:
|
||||
struct PlayerVertex {
|
||||
|
||||
318
include/Cubed/tools/sparse_vector.hpp
Normal file
318
include/Cubed/tools/sparse_vector.hpp
Normal file
@@ -0,0 +1,318 @@
|
||||
#pragma once
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace Cubed {
|
||||
template <typename T> class SparseVector {
|
||||
private:
|
||||
std::vector<std::optional<T>> m_data;
|
||||
std::vector<uint32_t> m_free_list;
|
||||
std::vector<uint32_t> m_generation;
|
||||
|
||||
std::vector<uint32_t> m_dense;
|
||||
std::vector<uint32_t> m_dense_index;
|
||||
|
||||
public:
|
||||
struct Handle {
|
||||
uint32_t index;
|
||||
uint32_t generation;
|
||||
|
||||
uint64_t value() const noexcept {
|
||||
return (uint64_t(index) << 32) | generation;
|
||||
}
|
||||
|
||||
bool operator==(const Handle&) const = default;
|
||||
|
||||
struct Hash {
|
||||
size_t operator()(const Handle& h) const noexcept {
|
||||
return h.value();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
using value_type = T;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
using pointer = T*;
|
||||
|
||||
using size_type = size_t;
|
||||
|
||||
class iterator { // NOLINT
|
||||
private:
|
||||
SparseVector* m_owner;
|
||||
size_t m_index;
|
||||
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using iterator_concept = std::random_access_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
iterator(SparseVector* owner, size_t index)
|
||||
: m_owner(owner), m_index(index) {}
|
||||
|
||||
reference operator*() {
|
||||
return m_owner->m_data[m_owner->m_dense[m_index]].value();
|
||||
}
|
||||
|
||||
pointer operator->() { return &(**this); }
|
||||
|
||||
iterator& operator++() {
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator& operator--() {
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator--(int) {
|
||||
iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& other) const {
|
||||
return m_owner == other.m_owner && m_index == other.m_index;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
iterator operator+(difference_type n) const {
|
||||
return iterator(m_owner, m_index + n);
|
||||
}
|
||||
|
||||
iterator operator-(difference_type n) const {
|
||||
return iterator(m_owner, m_index - n);
|
||||
}
|
||||
|
||||
difference_type operator-(const iterator& other) const {
|
||||
return static_cast<difference_type>(m_index) -
|
||||
static_cast<difference_type>(other.m_index);
|
||||
}
|
||||
|
||||
iterator& operator+=(difference_type n) {
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator& operator-=(difference_type n) {
|
||||
m_index -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator[](difference_type n) const { return *(*this + n); }
|
||||
|
||||
bool operator<(const iterator& other) const {
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
bool operator>(const iterator& other) const {
|
||||
return m_index > other.m_index;
|
||||
}
|
||||
|
||||
bool operator<=(const iterator& other) const {
|
||||
return m_index <= other.m_index;
|
||||
}
|
||||
|
||||
bool operator>=(const iterator& other) const {
|
||||
return m_index >= other.m_index;
|
||||
}
|
||||
friend iterator operator+(difference_type n, const iterator& it) {
|
||||
return it + n;
|
||||
}
|
||||
};
|
||||
|
||||
class const_iterator { // NOLINT
|
||||
private:
|
||||
const SparseVector* m_owner;
|
||||
size_t m_index;
|
||||
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using iterator_concept = std::random_access_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const T*;
|
||||
using reference = const T&;
|
||||
|
||||
const_iterator(const SparseVector* owner, size_t index)
|
||||
: m_owner(owner), m_index(index) {}
|
||||
|
||||
reference operator*() const {
|
||||
return m_owner->m_data[m_owner->m_dense[m_index]].value();
|
||||
}
|
||||
|
||||
pointer operator->() const { return &(**this); }
|
||||
|
||||
const_iterator& operator++() {
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator operator++(int) {
|
||||
const_iterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const_iterator& operator--() {
|
||||
--m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator operator--(int) {
|
||||
const_iterator tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const const_iterator& other) const {
|
||||
return m_owner == other.m_owner && m_index == other.m_index;
|
||||
}
|
||||
|
||||
bool operator!=(const const_iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const_iterator operator+(difference_type n) const {
|
||||
return const_iterator(m_owner, m_index + n);
|
||||
}
|
||||
|
||||
const_iterator operator-(difference_type n) const {
|
||||
return const_iterator(m_owner, m_index - n);
|
||||
}
|
||||
|
||||
difference_type operator-(const const_iterator& other) const {
|
||||
return static_cast<difference_type>(m_index) -
|
||||
static_cast<difference_type>(other.m_index);
|
||||
}
|
||||
|
||||
const_iterator& operator+=(difference_type n) {
|
||||
m_index += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator& operator-=(difference_type n) {
|
||||
m_index -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
reference operator[](difference_type n) const { return *(*this + n); }
|
||||
|
||||
bool operator<(const const_iterator& other) const {
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
bool operator>(const const_iterator& other) const {
|
||||
return m_index > other.m_index;
|
||||
}
|
||||
|
||||
bool operator<=(const const_iterator& other) const {
|
||||
return m_index <= other.m_index;
|
||||
}
|
||||
|
||||
bool operator>=(const const_iterator& other) const {
|
||||
return m_index >= other.m_index;
|
||||
}
|
||||
friend const_iterator operator+(difference_type n,
|
||||
const const_iterator& it) {
|
||||
return it + n;
|
||||
}
|
||||
};
|
||||
|
||||
template <class U> Handle insert(U&& value) {
|
||||
uint32_t id;
|
||||
if (!m_free_list.empty()) {
|
||||
id = m_free_list.back();
|
||||
m_free_list.pop_back();
|
||||
m_data[id].emplace(std::forward<U>(value));
|
||||
|
||||
m_dense_index[id] = m_dense.size();
|
||||
} else {
|
||||
id = m_data.size();
|
||||
m_data.push_back(std::forward<U>(value));
|
||||
m_generation.push_back(1);
|
||||
m_dense_index.emplace_back(m_dense.size());
|
||||
}
|
||||
|
||||
m_dense.push_back(id);
|
||||
return {id, m_generation[id]};
|
||||
}
|
||||
|
||||
template <typename... Args> Handle emplace(Args&&... args) {
|
||||
return insert(T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
void erase(Handle h) {
|
||||
|
||||
if (!exists(h)) {
|
||||
return;
|
||||
}
|
||||
uint32_t id = h.index;
|
||||
m_free_list.push_back(id);
|
||||
uint32_t index = m_dense_index[id];
|
||||
uint32_t last_id = m_dense.back();
|
||||
m_dense[index] = last_id;
|
||||
m_dense_index[last_id] = index;
|
||||
|
||||
m_dense.pop_back();
|
||||
m_data[id].reset();
|
||||
++m_generation[id];
|
||||
}
|
||||
|
||||
T& operator[](Handle h) {
|
||||
assert(exists(h));
|
||||
return m_data[h.index].value();
|
||||
}
|
||||
|
||||
const T& operator[](Handle h) const {
|
||||
assert(exists(h));
|
||||
return m_data[h.index].value();
|
||||
}
|
||||
|
||||
bool exists(Handle h) const {
|
||||
return h.index < m_generation.size() &&
|
||||
m_generation[h.index] == h.generation;
|
||||
}
|
||||
|
||||
void reserve(size_t n) {
|
||||
m_data.reserve(n);
|
||||
m_generation.reserve(n);
|
||||
m_dense.reserve(n);
|
||||
m_dense_index.reserve(n);
|
||||
}
|
||||
|
||||
size_t size() const { return m_dense.size(); }
|
||||
|
||||
bool empty() const { return m_dense.empty(); }
|
||||
|
||||
iterator begin() { return iterator(this, 0); }
|
||||
|
||||
iterator end() { return iterator(this, m_dense.size()); }
|
||||
|
||||
const_iterator begin() const { return const_iterator(this, 0); }
|
||||
|
||||
const_iterator end() const { return const_iterator(this, m_dense.size()); }
|
||||
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
|
||||
const_iterator cend() const { return end(); }
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user