refactor(gameplay): separate player logic into manager and ECS components

This commit is contained in:
2026-07-28 21:00:04 +08:00
parent 0ff5820e6e
commit d15037e7a3
26 changed files with 640 additions and 493 deletions

View File

@@ -1,7 +1,12 @@
#pragma once
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/ecs/animation.hpp"
#include "Cubed/gameplay/ecs/identity.hpp"
#include "Cubed/gameplay/ecs/transform.hpp"
#include "Cubed/gameplay/player.hpp"
namespace Cubed {
struct PlayerData {
struct ClientPlayer {
Position pos{};
Position render_pos{};
EntityInfo entity{};

View File

@@ -0,0 +1,45 @@
#pragma once
#include "Cubed/gameplay/client_player.hpp"
#include "Cubed/gameplay/local_player.hpp"
#include "Cubed/gameplay/network_client.hpp"
#include "Cubed/tools/sparse_vector.hpp"
namespace Cubed {
class ClientWorld;
class ClientPlayerManager {
public:
ClientPlayerManager(const ClientPlayerManager&) = delete;
ClientPlayerManager(ClientPlayerManager&&) = delete;
ClientPlayerManager& operator=(const ClientPlayerManager&) = delete;
ClientPlayerManager& operator=(ClientPlayerManager&&) = delete;
ClientPlayerManager(ClientWorld& world);
~ClientPlayerManager();
void init(std::string_view local_name);
void update(float dt);
std::span<PlayerRenderData> render_player_data();
bool has_player(const Hitbox& hitbox) const;
LocalPlayer& get_local();
const LocalPlayer& get_local() const;
void receive_remote_player(const PlayerInfoRsp& rsp);
void receive_player_logout(const LogoutRsp& rsp);
void reload_config();
void report_player_info(NetworkClient* client);
private:
ClientWorld& m_world;
mutable std::shared_mutex m_players_mutex;
using PlayerHandle = SparseVector<ClientPlayer>::Handle;
SparseVector<ClientPlayer> m_players;
std::vector<PlayerRenderData> m_render_data;
std::unordered_map<std::string, PlayerHandle> m_players_handle;
LocalPlayer m_local;
void update_players_data(float dt);
};
} // namespace Cubed

View File

@@ -5,15 +5,14 @@
#include "Cubed/gameplay/chat_message.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/client_chunk.hpp"
#include "Cubed/gameplay/client_player_manager.hpp"
#include "Cubed/gameplay/game_time.hpp"
#include "Cubed/gameplay/local_player.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>
@@ -34,7 +33,6 @@ public:
void init(std::string_view player_name,
std::shared_ptr<NetworkClient> client);
void update(float dt);
void update_players(float dt);
bool handle_event(const Event& e);
const std::optional<LookBlock>& get_look_block_pos() const;
LocalPlayer& get_player();
@@ -55,7 +53,6 @@ public:
void receive_block_change(const BlockChangeRsp& rsp);
void receive_time(const UpdateTime& rsp);
void receive_remote_player(const PlayerInfoRsp& rsp);
void receive_player_logout(const LogoutRsp& rsp);
void receive_player_water_sound(const PlayerWaterSound& rsp);
void send_player_water_sound(bool underwater, const glm::vec3& pos);
@@ -74,8 +71,6 @@ public:
void reset_key_status();
std::vector<glm::vec4>& planes();
const std::vector<const ChunkRenderSnapshot*>& render_snapshots() const;
const std::vector<PlayerRenderData>& render_player_data() const;
std::vector<PlayerRenderData>& render_player_data();
glm::vec3 sunlight_dir() const;
bool sphere_collide_world(glm::vec3 center, float radius) const;
@@ -88,6 +83,7 @@ public:
const AudioEngine& get_audio() const;
Config& get_config();
WorldScene& world_scene();
ClientPlayerManager& player_manager();
void set_direct_exit();
void receive_chat_message(ChatMsg& msg);
@@ -131,7 +127,7 @@ private:
static constexpr int WORLD_EXIT_TIMEOUT = 200;
static constexpr int MAX_UPLOAD_CHUNK_SUM = 16;
LocalPlayer m_player;
ClientPlayerManager m_player_manager;
ChunkHashMap m_chunks;
AudioEngine& m_audio;
Config& m_config;
@@ -139,11 +135,6 @@ private:
std::vector<glm::vec4> m_planes;
std::jthread m_client_thread;
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;
tbb::concurrent_queue<PendingSound> m_pending_sound;
@@ -152,7 +143,6 @@ private:
std::deque<ChunkPos> m_dirty_queue;
std::vector<const ChunkRenderSnapshot*> m_render_snapshots;
std::vector<PlayerRenderData> m_render_player_data;
tbb::concurrent_unordered_map<std::string, TickTimer> m_ticktimers;
std::unordered_map<std::string, Timer> m_timers;
@@ -176,8 +166,6 @@ private:
void client_run(std::stop_token token);
void report_player_info();
void set_block(const glm::ivec3& pos, unsigned id);
void update_chunk(const ChunkPosSet& old, const ChunkPosSet& now);

View File

@@ -0,0 +1,6 @@
#pragma once
namespace Cubed {
struct PigTag {};
} // namespace Cubed

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Cubed/gameplay/player.hpp"
namespace Cubed {
struct WalkPose {
Gait gait = Gait::STOP;
// for arm roll caculate
float walk_time = 0.0f;
// for sound play
float moving_time = 0.0f;
};
} // namespace Cubed

View File

@@ -0,0 +1,20 @@
#pragma once
#include "Cubed/gameplay/ecs/animation.hpp"
#include "Cubed/gameplay/ecs/entity.hpp"
#include "Cubed/gameplay/ecs/identity.hpp"
#include "Cubed/gameplay/ecs/transform.hpp"
#include "Cubed/gameplay/model.hpp"
namespace Cubed {
struct ClientEntity {
Entity entity;
EntityInfo info;
Transform transform;
WalkPose pose;
ModelID model;
};
} // namespace Cubed

View File

@@ -0,0 +1,11 @@
#pragma once
#include <cstdint>
namespace Cubed {
using EntityID = uint64_t;
struct Entity {
EntityID id;
explicit Entity(EntityID id) : id(id) {}
};
} // namespace Cubed

View File

@@ -0,0 +1,10 @@
#pragma once
namespace Cubed {
struct Health {
float hp = 20;
float max_hp = 20;
};
} // namespace Cubed

View File

@@ -0,0 +1,10 @@
#pragma once
#include <string>
namespace Cubed {
struct EntityInfo {
std::string name;
std::string uuid;
};
} // namespace Cubed

View File

@@ -0,0 +1,26 @@
#pragma once
#include "Cubed/constants.hpp"
#include <glm/glm.hpp>
namespace Cubed {
struct Velocity {
glm::vec3 value{0.0f};
glm::vec3 max{4.5f, 7.5f, 7.5f};
};
struct Movement {
float acceleration = DEFAULT_ACCELERATION;
float deceleration = DEFAULT_DECELERATION;
float jump_power = 7.5f;
};
struct Gravity {
float value = DEFAULT_G;
};
} // namespace Cubed

View File

@@ -0,0 +1,32 @@
#pragma once
#include "Cubed/gameplay/ecs/entity.hpp"
#include "Cubed/gameplay/ecs/health.hpp"
#include "Cubed/gameplay/ecs/identity.hpp"
#include "Cubed/gameplay/ecs/movement.hpp"
#include "Cubed/gameplay/ecs/state.hpp"
#include "Cubed/gameplay/ecs/transform.hpp"
#include "Cubed/gameplay/hitbox.hpp"
namespace Cubed {
struct ServerEntity {
Entity entity;
EntityInfo info;
Transform transform;
Velocity velocity;
Movement movement;
MoveState move_state;
Direction direction;
Gravity gravity;
Health health;
HitboxID hitbox;
};
} // namespace Cubed

View File

@@ -0,0 +1,18 @@
#pragma once
namespace Cubed {
struct MoveState {
bool forward = false;
bool back = false;
bool left = false;
bool right = false;
bool down = false;
bool up = false;
bool is_fly = false;
bool can_up = true;
};
} // namespace Cubed

View File

@@ -0,0 +1,24 @@
#pragma once
#include <glm/glm.hpp>
namespace Cubed {
struct Position {
glm::vec3 value{0.0f};
};
struct Orientation {
float yaw = 0.0f;
float pitch = 0.0f;
float roll = 0.0f;
};
struct Direction {
glm::vec3 value{0.0f};
};
struct Transform {
Position position;
Orientation orientation;
Direction direction;
};
} // namespace Cubed

View File

@@ -1,120 +0,0 @@
#pragma once
#include "Cubed/constants.hpp"
#include "Cubed/gameplay/hitbox.hpp"
#include "Cubed/gameplay/model.hpp"
#include "Cubed/gameplay/player.hpp"
#include <glm/glm.hpp>
#include <string>
namespace Cubed {
using EntityID = uint64_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;
};
struct EntityInfo {
std::string name;
std::string uuid;
EntityID id;
HitboxID hitbox;
ModelID model;
};
struct Health {
float hp = 20;
float max_hp = 20;
};
struct Orientation {
float yaw = 0.0f;
float pitch = 0.0f;
float roll = 0.0f;
};
struct Velocity {
glm::vec3 value{0.0f};
glm::vec3 max{4.5f, 7.5f, 7.5f};
};
struct Movement {
float acceleration = DEFAULT_ACCELERATION;
float deceleration = DEFAULT_DECELERATION;
float jump_power = 7.5f;
};
struct Gravity {
float value = DEFAULT_G;
};
struct MoveState {
bool forward = false;
bool back = false;
bool left = false;
bool right = false;
bool down = false;
bool up = false;
bool is_fly = false;
bool can_up = true;
};
struct Direction {
glm::vec3 value{0.0f};
};
class Entity {
public:
Entity(EntityID id, const std::string& name);
glm::vec3& max_speed();
float& acceleration();
float& deceleration();
float& g();
void set_gait(Gait gait);
float yaw() const;
float pitch() const;
float& roll();
float& walk_time();
Gait get_gait() const;
Velocity& velocity();
Position& pos();
WalkPose& walk_pose();
Orientation& angle();
Movement& movement();
Gravity& gravity();
MoveState& move_state();
Direction& direction();
EntityInfo& info();
const Velocity& velocity() const;
const Position& pos() const;
const WalkPose& walk_pose() const;
const Orientation& angle() const;
const Movement& movement() const;
const Gravity& gravity() const;
const MoveState& move_state() const;
const Direction& direction() const;
const EntityInfo& info() const;
protected:
EntityInfo m_info;
Position m_pos;
WalkPose m_walk_pose;
Velocity m_velocity;
Orientation m_angle;
Movement m_movement;
Gravity m_gravity;
MoveState m_move_state;
Direction m_direction;
};
} // namespace Cubed

View File

@@ -2,9 +2,14 @@
#include "Cubed/constants.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/chunk_pos.hpp"
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/ecs/animation.hpp"
#include "Cubed/gameplay/ecs/identity.hpp"
#include "Cubed/gameplay/ecs/movement.hpp"
#include "Cubed/gameplay/ecs/state.hpp"
#include "Cubed/gameplay/ecs/transform.hpp"
#include "Cubed/gameplay/game_mode.hpp"
#include "Cubed/gameplay/game_time.hpp"
#include "Cubed/gameplay/hitbox.hpp"
#include "Cubed/gameplay/item_stack.hpp"
#include "Cubed/gameplay/player.hpp"
#include "Cubed/input/event.hpp"
@@ -17,7 +22,7 @@
namespace Cubed {
class ClientWorld;
class LocalPlayer : public Entity {
class LocalPlayer {
public:
static constexpr size_t HOTBAR_SUM = 10;
static constexpr float WALK_SOUND_INTERVAL = 0.45f;
@@ -35,6 +40,7 @@ public:
bool update_scroll(float yoffset);
void update_chunk_set(const ChunkPosSet& set);
const ChunkPosSet& get_chunk_pos_set() const;
ChunkPosSet get_chunk_pos_set();
@@ -77,6 +83,17 @@ public:
void set_hotbar(int pos, const ItemStack& item);
std::span<const ItemStack, HOTBAR_SUM> get_hotbar() const;
glm::vec3& max_speed();
float& acceleration();
float& deceleration();
float& g();
void set_gait(Gait gait);
float yaw() const;
float pitch() const;
float& roll();
float& walk_time();
Gait get_gait() const;
private:
using enum GameMode;
float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED;
@@ -84,8 +101,18 @@ private:
float m_max_y_speed = 7.5f;
static constexpr float MAX_SPACE_ON_TIME = 0.3f;
static constexpr float PLACE_BLOCK_INTERVAL = 0.2f;
Movement m_movement{};
Gravity m_gravity{};
EntityInfo m_info;
Position m_pos;
WalkPose m_walk_pose;
Velocity m_velocity;
Orientation m_angle;
Movement m_movement;
Gravity m_gravity;
MoveState m_move_state;
Direction m_direction;
HitboxID m_hitbox = 0;
float m_place_time = PLACE_BLOCK_INTERVAL;
std::array<ItemStack, HOTBAR_SUM> m_hotbar;

View File

@@ -1,15 +1,20 @@
#pragma once
#include "Cubed/gameplay/entity.hpp"
#include "Cubed//gameplay/ecs/server_entity.hpp"
#include "Cubed/gameplay/world.hpp"
namespace Cubed {
class PhysicalSystem {
public:
static glm::vec3 get_move_distance(float dt, const Entity& e);
static std::tuple<bool, bool, bool> update(float dt, Entity& e,
static glm::vec3 get_move_distance(float dt, const Direction& d,
const Velocity& v);
static std::tuple<bool, bool, bool> update(float dt, ServerEntity& e,
World& world);
static std::tuple<bool, bool, bool>
update(float dt, Entity& e, World& world, glm::vec3& moved_pos);
update(float dt, ServerEntity& e, World& world, glm::vec3& moved_pos);
static std::tuple<bool, bool, bool>
update(float dt, World& world, glm::vec3& moved_pos, Velocity& v,
Direction& direction, MoveState& move_state, HitboxID hitbox);
private:
};

View File

@@ -1,11 +1,15 @@
#pragma once
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/ecs/server_entity.hpp"
#include "Cubed/gameplay/ecs/state.hpp"
namespace Cubed {
class SpeedSystem {
public:
static void update(float dt, Entity& e);
static void update(float dt, ServerEntity& e);
static void update(float dt, Velocity& v, MoveState& move_state,
Movement& movement, Direction& direction,
const Gravity& g);
private:
};