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:
};

View File

@@ -97,7 +97,7 @@ target_sources(${PROJECT_NAME}
render/model_renderer.cpp
gameplay/chunk.cpp
gameplay/hitbox_manager.cpp
gameplay/entity.cpp
gameplay/systems/physical_system.cpp
gameplay/systems/speed_system.cpp
gameplay/client_player_manager.cpp
)

View File

@@ -0,0 +1,219 @@
#pragma once
#include "Cubed/gameplay/client_player_manager.hpp"
#include "Cubed/gameplay/client_world.hpp"
#include "Cubed/gameplay/hitbox_manager.hpp"
#include "Cubed/tools/math_tools.hpp"
using namespace google::protobuf;
namespace Cubed {
ClientPlayerManager::ClientPlayerManager(ClientWorld& world)
: m_world(world), m_local(world) {}
ClientPlayerManager::~ClientPlayerManager() {
};
void ClientPlayerManager::init(std::string_view local_name) {
m_local.init(local_name);
}
void ClientPlayerManager::update(float dt) {
m_local.update(dt);
update_players_data(dt);
}
bool ClientPlayerManager::has_player(const Hitbox& hitbox) const {
std::shared_lock lock(m_players_mutex);
for (const auto& player : m_players) {
auto box = HitboxManager::hitbox("cubed:player");
box.box.center += player.pos.value;
if (box.box.intersects(hitbox)) {
return true;
}
}
return false;
}
void ClientPlayerManager::receive_remote_player(const PlayerInfoRsp& rsp) {
auto pitch = rsp.pitch();
auto yaw = rsp.yaw();
{
std::lock_guard lock(m_players_mutex);
glm::vec3 pos{rsp.pos().x(), rsp.pos().y(), rsp.pos().z()};
auto it = m_players_handle.find(rsp.uuid());
if (it == m_players_handle.end()) {
ClientPlayer data{};
data.entity.name = rsp.name();
data.entity.uuid = rsp.uuid();
data.angle.pitch = pitch;
data.angle.yaw = yaw;
data.render_angle.pitch = pitch;
data.render_angle.yaw = yaw;
data.pos.value = pos;
data.render_pos.value = pos;
data.walk.gait = get_gait_from_id(rsp.gait());
auto handle = m_players.emplace(std::move(data));
m_players_handle.try_emplace(rsp.uuid(), handle);
} else {
auto it = m_players_handle.find(rsp.uuid());
if (it != m_players_handle.end()) {
auto& data = m_players[it->second];
data.pos.value = pos;
data.walk.gait = get_gait_from_id(rsp.gait());
data.angle.yaw = yaw;
data.angle.pitch = pitch;
}
}
// Logger::info("Player {} pos Update", rsp.name());
}
}
void ClientPlayerManager::receive_player_logout(const LogoutRsp& rsp) {
{
std::lock_guard lock(m_players_mutex);
auto it = m_players_handle.find(rsp.uuid());
if (it == m_players_handle.end()) {
Logger::warn("Player {} not find", rsp.uuid());
} else {
m_players.erase(it->second);
m_players_handle.erase(it);
Logger::info("Player {} erase", rsp.uuid());
}
}
}
void ClientPlayerManager::reload_config() { m_local.reload_config(); }
void ClientPlayerManager::report_player_info(NetworkClient* client) {
if (!client) {
return;
}
Arena arena;
auto* info = Arena::Create<C2S_PlayerInfo>(&arena);
info->set_uuid(m_local.get_uuid());
glm::vec3 player_pos = m_local.get_player_pos();
auto* v3 = info->mutable_pos();
v3->set_x(player_pos.x);
v3->set_y(player_pos.y);
v3->set_z(player_pos.z);
info->set_yaw(m_local.yaw());
info->set_pitch(m_local.pitch());
info->set_gait(get_gait_id(m_local.get_gait()));
client->send(make_packet(*info), 0);
}
void ClientPlayerManager::update_players_data(float dt) {
m_render_data.clear();
auto m_rendering_distance = m_world.rendering_distance();
auto update_renderinfo = [this, dt,
m_rendering_distance](ClientPlayer& player) {
player.render_pos.value =
glm::mix(player.render_pos.value, player.pos.value, 0.15f);
if (Math::distance2(player.render_pos.value, m_local.get_player_pos()) >
m_rendering_distance * CHUNK_SIZE * m_rendering_distance *
CHUNK_SIZE) {
return;
}
player.render_angle.yaw =
glm::mix(player.render_angle.yaw, player.angle.yaw, 0.15);
player.render_angle.pitch =
glm::mix(player.render_angle.pitch, player.angle.pitch, 0.15);
if (player.walk.gait == Gait::WALK || player.walk.gait == Gait::RUN) {
player.walk.walk_time += dt;
float speed = player.walk.gait == Gait::RUN ? 14.0f : 8.0f;
float amp = player.walk.gait == Gait::RUN ? 50.0f : 35.0f;
// float amp = 90.0f;
player.render_angle.roll =
glm::sin(player.walk.walk_time * speed) * glm::radians(amp);
} else if (player.walk.gait == Gait::STOP) {
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
player.render_angle.roll =
glm::mix(player.render_angle.roll, 0.0f, t);
}
// walking sound
if (player.walk.gait == Gait::STOP) {
player.walk.moving_time = 0.0f;
} else {
player.walk.moving_time += dt;
}
auto play_walk_sound = [&]() {
glm::ivec3 block = glm::floor(player.render_pos.value);
block.y -= 1;
BlockType id = m_world.get_block_tpye(block);
if (id == 0) {
return;
}
std::string name = BlockManager::name_form_id(id);
std::string sound = "block/" + name + "/walk.ogg";
m_world.get_audio().play_3d(sound, player.render_pos.value);
};
if (player.walk.gait == Gait::WALK) {
if (player.walk.moving_time >= LocalPlayer::WALK_SOUND_INTERVAL) {
player.walk.moving_time = 0.0f;
play_walk_sound();
}
}
if (player.walk.gait == Gait::RUN) {
if (player.walk.moving_time >= LocalPlayer::RUN_SOUND_INTERVAL) {
player.walk.moving_time = 0.0f;
play_walk_sound();
}
}
PlayerRenderData render_data;
render_data.render_pos = player.render_pos;
render_data.angle = player.render_angle;
render_data.gait = player.walk.gait;
render_data.info = player.entity;
m_render_data.emplace_back(std::move(render_data));
};
{
std::lock_guard lock(m_players_mutex);
for (auto& player : m_players) {
update_renderinfo(player);
}
{
auto gait = m_local.get_gait();
auto& walk_time = m_local.walk_time();
auto& angle = m_local.roll();
if (gait == Gait::WALK || gait == Gait::RUN) {
walk_time += dt;
float speed = gait == Gait::RUN ? 14.0f : 8.0f;
float amp = gait == Gait::RUN ? 50.0f : 35.0f;
// float amp = 90.0f;
angle = glm::sin(walk_time * speed) * glm::radians(amp);
} else if (gait == Gait::STOP) {
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
angle = glm::mix(angle, 0.0f, t);
}
PlayerRenderData render_data{};
render_data.render_pos.value = m_local.get_player_pos();
render_data.angle.yaw = m_local.yaw();
render_data.angle.pitch = m_local.pitch();
render_data.angle.roll = angle;
render_data.gait = m_local.get_gait();
render_data.info.name = m_local.get_name();
render_data.info.uuid = m_local.get_uuid();
m_render_data.emplace_back(std::move(render_data));
}
}
}
LocalPlayer& ClientPlayerManager::get_local() { return m_local; }
const LocalPlayer& ClientPlayerManager::get_local() const { return m_local; }
std::span<PlayerRenderData> ClientPlayerManager::render_player_data() {
return m_render_data;
}
} // namespace Cubed

View File

@@ -2,12 +2,9 @@
#include "Cubed/config.hpp"
#include "Cubed/gameplay/chunk_generator.hpp"
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/game_time.hpp"
#include "Cubed/gameplay/hitbox_manager.hpp"
#include "Cubed/gameplay/packet.hpp"
#include "Cubed/scene/world_scene.hpp"
#include "Cubed/tools/math_tools.hpp"
#include "Cubed/tools/time_tools.hpp"
#include <absl/container/inlined_vector.h>
@@ -26,7 +23,8 @@ struct ChunkRenderData {
} // namespace
ClientWorld::ClientWorld(AudioEngine& auido, Config& config, WorldScene& scene)
: m_player(*this), m_audio(auido), m_config(config), m_world_scene(scene) {}
: m_player_manager(*this), m_audio(auido), m_config(config),
m_world_scene(scene) {}
ClientWorld::~ClientWorld() {
m_client->close();
@@ -58,11 +56,13 @@ ClientWorld::~ClientWorld() {
const std::optional<LookBlock>& ClientWorld::get_look_block_pos() const {
return m_player.get_look_block_pos();
return m_player_manager.get_local().get_look_block_pos();
}
LocalPlayer& ClientWorld::get_player() { return m_player; }
const LocalPlayer& ClientWorld::get_player() const { return m_player; }
LocalPlayer& ClientWorld::get_player() { return m_player_manager.get_local(); }
const LocalPlayer& ClientWorld::get_player() const {
return m_player_manager.get_local();
}
int ClientWorld::get_block(const glm::ivec3& block_pos) const {
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
chunk_cacc cacc;
@@ -129,7 +129,7 @@ void ClientWorld::rebuild_world() {
m_pending_upload_queue.clear();
start_thread_pool();
start_client_thread(m_player.get_uuid());
start_client_thread(m_player_manager.get_local().get_uuid());
request_chunk();
m_is_rebuilding = false;
}
@@ -296,21 +296,14 @@ void ClientWorld::report_block_change(const glm::ivec3& pos,
unsigned id) const {
if (id != 0) {
Hitbox block_box = get_block_aabb(pos);
std::shared_lock lock(m_players_date_mutex);
for (const auto& player : m_players_data) {
auto box = HitboxManager::hitbox("cubed:player");
box.box.center += player.pos.value;
if (box.box.intersects(block_box)) {
if (m_player_manager.has_player(block_box)) {
return;
}
}
}
Arena arena;
auto* req = Arena::Create<BlockChangeReq>(&arena);
req->set_uuid(m_player.get_uuid());
req->set_uuid(m_player_manager.get_local().get_uuid());
req->set_block(id);
auto* p = req->mutable_pos();
p->set_x(pos.x);
@@ -329,64 +322,20 @@ void ClientWorld::receive_time(const UpdateTime& rsp) {
m_day_tick = rsp.day_tick();
}
void ClientWorld::receive_remote_player(const PlayerInfoRsp& rsp) {
auto pitch = rsp.pitch();
auto yaw = rsp.yaw();
{
std::lock_guard lock(m_players_date_mutex);
glm::vec3 pos{rsp.pos().x(), rsp.pos().y(), rsp.pos().z()};
auto it = m_players_handle.find(rsp.uuid());
if (it == m_players_handle.end()) {
PlayerData data{};
data.entity.name = rsp.name();
data.entity.uuid = rsp.uuid();
data.angle.pitch = pitch;
data.angle.yaw = yaw;
data.render_angle.pitch = pitch;
data.render_angle.yaw = yaw;
data.pos.value = pos;
data.render_pos.value = pos;
data.walk.gait = get_gait_from_id(rsp.gait());
auto handle = m_players_data.emplace(std::move(data));
m_players_handle.try_emplace(rsp.uuid(), handle);
} else {
auto it = m_players_handle.find(rsp.uuid());
if (it != m_players_handle.end()) {
auto& data = m_players_data[it->second];
data.pos.value = pos;
data.walk.gait = get_gait_from_id(rsp.gait());
data.angle.yaw = yaw;
data.angle.pitch = pitch;
}
}
// Logger::info("Player {} pos Update", rsp.name());
}
}
void ClientWorld::receive_player_logout(const LogoutRsp& rsp) {
if (rsp.server_stop()) {
m_receive_exit = true;
return;
}
if (rsp.uuid() == m_player.get_uuid()) {
if (rsp.uuid() == m_player_manager.get_local().get_uuid()) {
m_receive_exit = true;
return;
}
{
std::lock_guard lock(m_players_date_mutex);
auto it = m_players_handle.find(rsp.uuid());
if (it == m_players_handle.end()) {
Logger::warn("Player {} not find", rsp.uuid());
} else {
m_players_data.erase(it->second);
m_players_handle.erase(it);
Logger::info("Player {} erase", rsp.uuid());
}
}
m_player_manager.receive_player_logout(rsp);
}
void ClientWorld::receive_player_water_sound(const PlayerWaterSound& rsp) {
if (rsp.uuid() == m_player.get_uuid()) {
if (rsp.uuid() == m_player_manager.get_local().get_uuid()) {
return;
}
glm::vec3 pos = {rsp.pos().x(), rsp.pos().y(), rsp.pos().z()};
@@ -406,7 +355,7 @@ void ClientWorld::send_player_water_sound(bool underwater,
p->set_x(pos.x);
p->set_y(pos.y);
p->set_z(pos.z);
r->set_uuid(m_player.get_uuid());
r->set_uuid(m_player_manager.get_local().get_uuid());
m_client->send(make_packet(*r));
Logger::info("Client: Send Player Water Sound");
@@ -414,7 +363,7 @@ void ClientWorld::send_player_water_sound(bool underwater,
void ClientWorld::init(std::string_view player_name,
std::shared_ptr<NetworkClient> client) {
m_player.init(player_name);
m_player_manager.init(player_name);
m_client = client;
reload_config(false);
@@ -422,9 +371,11 @@ void ClientWorld::init(std::string_view player_name,
m_random.init(ChunkGenerator::seed());
// timer
register_ticktimer("player_pos", 1, [this]() { report_player_info(); });
register_ticktimer("player_pos", 1, [this]() {
m_player_manager.report_player_info(m_client.get());
});
m_timers.try_emplace("Birds Sound", 60.0f, [this]() {
auto player_pos = m_player.get_player_pos();
auto player_pos = m_player_manager.get_local().get_player_pos();
if (player_pos.y < SEA_LEVEL) {
return;
}
@@ -440,7 +391,7 @@ void ClientWorld::init(std::string_view player_name,
});
m_timers.try_emplace("Ocean Wave", 3.0f, [this]() {
auto player_pos = m_player.get_player_pos();
auto player_pos = m_player_manager.get_local().get_player_pos();
if (player_pos.y < SEA_LEVEL - 10 || player_pos.y > SEA_LEVEL + 10) {
return;
}
@@ -460,11 +411,12 @@ void ClientWorld::init(std::string_view player_name,
});
m_timers.try_emplace("under water bubble", 1.5f, [this]() {
if (m_player.is_underwater()) {
if (m_player_manager.get_local().is_underwater()) {
auto ans = m_random.random_int(1, 2);
std::string sound =
"ambient/water/bubble00" + std::to_string(ans) + ".ogg";
m_audio.play_3d(sound, m_player.get_player_pos(), true);
m_audio.play_3d(
sound, m_player_manager.get_local().get_player_pos(), true);
}
});
@@ -477,7 +429,7 @@ void ClientWorld::init(std::string_view player_name,
});
LoginReq req;
req.set_name(m_player.get_name());
req.set_name(m_player_manager.get_local().get_name());
while (!client->is_connected()) {
if (client->is_connect_error()) {
throw std::runtime_error(client->get_error_string());
@@ -502,7 +454,7 @@ void ClientWorld::start_client_thread(std::string_view uuid) {
return;
}
// response
m_player.set_uuid(uuid);
m_player_manager.get_local().set_uuid(uuid);
m_client_thread = std::jthread([this](std::stop_token token) {
m_game_running = true;
@@ -557,7 +509,7 @@ void ClientWorld::reload_config(bool chunk_build) {
request_chunk();
}
m_player.reload_config();
m_player_manager.reload_config();
}
void ClientWorld::client_run(std::stop_token stoken) {
@@ -576,25 +528,6 @@ void ClientWorld::client_run(std::stop_token stoken) {
}
}
void ClientWorld::report_player_info() {
if (!m_client) {
return;
}
Arena arena;
auto* info = Arena::Create<C2S_PlayerInfo>(&arena);
info->set_uuid(m_player.get_uuid());
glm::vec3 player_pos = m_player.get_player_pos();
auto* v3 = info->mutable_pos();
v3->set_x(player_pos.x);
v3->set_y(player_pos.y);
v3->set_z(player_pos.z);
info->set_yaw(m_player.yaw());
info->set_pitch(m_player.pitch());
info->set_gait(get_gait_id(m_player.get_gait()));
m_client->send(make_packet(*info), 0);
}
void ClientWorld::update_chunk(const ChunkPosSet& old, const ChunkPosSet& now) {
// Elements in the old set that are not contained in now are not needed by
@@ -622,7 +555,7 @@ void ClientWorld::request_chunk() {
}
ChunkPosSet required_chunks;
glm::vec3 player_pos = m_player.get_player_pos();
glm::vec3 player_pos = m_player_manager.get_local().get_player_pos();
int x = std::floor(player_pos.x);
int z = std::floor(player_pos.z);
@@ -640,8 +573,8 @@ void ClientWorld::request_chunk() {
}
}
ChunkPosSet old = m_player.get_chunk_pos_set();
m_player.update_chunk_set(required_chunks);
ChunkPosSet old = m_player_manager.get_local().get_chunk_pos_set();
m_player_manager.get_local().update_chunk_set(required_chunks);
ChunkPosVector need_send_pos;
@@ -665,7 +598,7 @@ void ClientWorld::request_chunk() {
break;
case CENTER: {
glm::vec3 player_pos = m_player.get_player_pos();
glm::vec3 player_pos = m_player_manager.get_local().get_player_pos();
ChunkPos player_chunk_pos = get_chunk_pos(player_pos.x, player_pos.z);
auto dist2 = [player_chunk_pos](ChunkPos chunk_pos) {
float dx = player_chunk_pos.x - chunk_pos.x;
@@ -679,7 +612,7 @@ void ClientWorld::request_chunk() {
});
}
}
auto uuid = m_player.get_uuid();
auto uuid = m_player_manager.get_local().get_uuid();
Arena arena;
++m_chunk_task_id;
auto* req = Arena::Create<ChunkDataReq>(&arena);
@@ -694,7 +627,9 @@ void ClientWorld::request_chunk() {
Logger::info("Send Chunk Request Success");
m_requesting_chunk = false;
}
void ClientWorld::reset_key_status() { m_player.reset_input_status(); }
void ClientWorld::reset_key_status() {
m_player_manager.get_local().reset_input_status();
}
void ClientWorld::receive_chunk(std::vector<uint8_t> raw_data,
PacketHeader header) {
@@ -741,6 +676,7 @@ AudioEngine& ClientWorld::get_audio() { return m_audio; }
const AudioEngine& ClientWorld::get_audio() const { return m_audio; }
Config& ClientWorld::get_config() { return m_config; }
WorldScene& ClientWorld::world_scene() { return m_world_scene; }
ClientPlayerManager& ClientWorld::player_manager() { return m_player_manager; }
void ClientWorld::set_direct_exit() { m_exit_direct = true; }
void ClientWorld::request_exit() {
if (m_receive_exit) {
@@ -748,7 +684,7 @@ void ClientWorld::request_exit() {
}
Arena arena;
auto* req = Arena::Create<LogoutReq>(&arena);
req->set_uuid(m_player.get_uuid());
req->set_uuid(m_player_manager.get_local().get_uuid());
m_client->send(make_packet(*req));
int cnt = 0;
while (!m_receive_exit) {
@@ -789,8 +725,7 @@ void ClientWorld::send_chat_message(ChatMessage& message) {
}
void ClientWorld::update(float delta_time) {
m_player.update(delta_time);
m_player_manager.update(delta_time);
{
std::lock_guard lk(m_delete_vbo_mutex);
m_pending_delete_vbo.clear();
@@ -841,7 +776,7 @@ void ClientWorld::update(float delta_time) {
chunk->upload_to_gpu();
}
auto chunk_pos_set = m_player.get_chunk_pos_set();
auto chunk_pos_set = m_player_manager.get_local().get_chunk_pos_set();
for (auto& pos : chunk_pos_set) {
std::shared_ptr<ClientChunk> chunk;
@@ -858,9 +793,6 @@ void ClientWorld::update(float delta_time) {
m_render_snapshots.push_back(chunk->get_render_snapshot());
}
m_render_player_data.clear();
update_players(delta_time);
// sound
PendingSound pending_sound;
while (m_pending_sound.try_pop(pending_sound)) {
@@ -881,126 +813,24 @@ void ClientWorld::update(float delta_time) {
}
}
void ClientWorld::update_players(float dt) {
auto update_renderinfo = [this, dt](PlayerData& player) {
player.render_pos.value =
glm::mix(player.render_pos.value, player.pos.value, 0.15f);
if (Math::distance2(player.render_pos.value,
m_player.get_player_pos()) >
m_rendering_distance * CHUNK_SIZE * m_rendering_distance *
CHUNK_SIZE) {
return;
}
player.render_angle.yaw =
glm::mix(player.render_angle.yaw, player.angle.yaw, 0.15);
player.render_angle.pitch =
glm::mix(player.render_angle.pitch, player.angle.pitch, 0.15);
if (player.walk.gait == Gait::WALK || player.walk.gait == Gait::RUN) {
player.walk.walk_time += dt;
float speed = player.walk.gait == Gait::RUN ? 14.0f : 8.0f;
float amp = player.walk.gait == Gait::RUN ? 50.0f : 35.0f;
// float amp = 90.0f;
player.render_angle.roll =
glm::sin(player.walk.walk_time * speed) * glm::radians(amp);
} else if (player.walk.gait == Gait::STOP) {
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
player.render_angle.roll =
glm::mix(player.render_angle.roll, 0.0f, t);
}
// walking sound
if (player.walk.gait == Gait::STOP) {
player.walk.moving_time = 0.0f;
} else {
player.walk.moving_time += dt;
}
auto play_walk_sound = [&]() {
glm::ivec3 block = glm::floor(player.render_pos.value);
block.y -= 1;
BlockType id = get_block_tpye(block);
if (id == 0) {
return;
}
std::string name = BlockManager::name_form_id(id);
std::string sound = "block/" + name + "/walk.ogg";
m_audio.play_3d(sound, player.render_pos.value);
};
if (player.walk.gait == Gait::WALK) {
if (player.walk.moving_time >= LocalPlayer::WALK_SOUND_INTERVAL) {
player.walk.moving_time = 0.0f;
play_walk_sound();
}
}
if (player.walk.gait == Gait::RUN) {
if (player.walk.moving_time >= LocalPlayer::RUN_SOUND_INTERVAL) {
player.walk.moving_time = 0.0f;
play_walk_sound();
}
}
PlayerRenderData render_data;
render_data.render_pos = player.render_pos;
render_data.angle = player.render_angle;
render_data.gait = player.walk.gait;
render_data.info = player.entity;
m_render_player_data.emplace_back(std::move(render_data));
};
{
std::lock_guard lock(m_players_date_mutex);
for (auto& player : m_players_data) {
update_renderinfo(player);
}
{
auto gait = m_player.get_gait();
auto& walk_time = m_player.walk_time();
auto& angle = m_player.roll();
if (gait == Gait::WALK || gait == Gait::RUN) {
walk_time += dt;
float speed = gait == Gait::RUN ? 14.0f : 8.0f;
float amp = gait == Gait::RUN ? 50.0f : 35.0f;
// float amp = 90.0f;
angle = glm::sin(walk_time * speed) * glm::radians(amp);
} else if (gait == Gait::STOP) {
float t = glm::clamp(dt * 10.0f, 0.0f, 1.0f);
angle = glm::mix(angle, 0.0f, t);
}
PlayerRenderData render_data{};
render_data.render_pos.value = m_player.get_player_pos();
render_data.angle.yaw = m_player.yaw();
render_data.angle.pitch = m_player.pitch();
render_data.angle.roll = angle;
render_data.gait = m_player.get_gait();
render_data.info.name = m_player.get_name();
render_data.info.uuid = m_player.get_uuid();
m_render_player_data.emplace_back(std::move(render_data));
}
}
}
bool ClientWorld::handle_event(const Event& e) {
return std::visit(
Overloaded{[this](const MouseButtonEvent& e) {
if (m_player.handle_mouse_button_event(e)) {
Overloaded{
[this](const MouseButtonEvent& e) {
if (m_player_manager.get_local().handle_mouse_button_event(e)) {
return true;
}
return false;
},
[](const MouseMoveEvent&) { return false; },
[this](const MouseWheelEvent& e) {
if (m_player.handle_mouse_wheel_event(e)) {
if (m_player_manager.get_local().handle_mouse_wheel_event(e)) {
return true;
}
return false;
},
[this](const KeyEvent& e) {
if (m_player.handle_key_event(e)) {
if (m_player_manager.get_local().handle_key_event(e)) {
return true;
}
@@ -1075,11 +905,6 @@ const std::vector<const ChunkRenderSnapshot*>&
ClientWorld::render_snapshots() const {
return m_render_snapshots;
};
const std::vector<PlayerRenderData>& ClientWorld::render_player_data() const {
return m_render_player_data;
}
std::vector<PlayerRenderData>& ClientWorld::render_player_data() {
return m_render_player_data;
}
std::vector<glm::vec4>& ClientWorld::planes() { return m_planes; }
} // namespace Cubed

View File

@@ -1,47 +0,0 @@
#include "Cubed/gameplay/entity.hpp"
#include "Cubed/gameplay/hitbox_manager.hpp"
#include "Cubed/render/model_manager.hpp"
namespace Cubed {
Entity::Entity(EntityID id, const std::string& name) {
m_info.id = id;
m_info.name = name;
auto h = ModelManager::model(name);
m_info.model = h.id;
auto b = HitboxManager::hitbox(name);
m_info.hitbox = b.id;
}
glm::vec3& Entity::max_speed() { return m_velocity.max; }
float& Entity::acceleration() { return m_movement.acceleration; }
float& Entity::deceleration() { return m_movement.deceleration; }
float& Entity::g() { return m_gravity.value; }
void Entity::set_gait(Gait gait) { m_walk_pose.gait = gait; }
float Entity::yaw() const { return m_angle.yaw; }
float Entity::pitch() const { return m_angle.pitch; }
float& Entity::roll() { return m_angle.roll; }
float& Entity::walk_time() { return m_walk_pose.walk_time; }
Gait Entity::get_gait() const { return m_walk_pose.gait; }
Velocity& Entity::velocity() { return m_velocity; }
Position& Entity::pos() { return m_pos; }
WalkPose& Entity::walk_pose() { return m_walk_pose; }
Orientation& Entity::angle() { return m_angle; }
Movement& Entity::movement() { return m_movement; }
Gravity& Entity::gravity() { return m_gravity; }
MoveState& Entity::move_state() { return m_move_state; }
Direction& Entity::direction() { return m_direction; }
EntityInfo& Entity::info() { return m_info; }
const Velocity& Entity::velocity() const { return m_velocity; }
const Position& Entity::pos() const { return m_pos; }
const WalkPose& Entity::walk_pose() const { return m_walk_pose; }
const Orientation& Entity::angle() const { return m_angle; }
const Movement& Entity::movement() const { return m_movement; }
const Gravity& Entity::gravity() const { return m_gravity; }
const MoveState& Entity::move_state() const { return m_move_state; }
const Direction& Entity::direction() const { return m_direction; }
const EntityInfo& Entity::info() const { return m_info; }
} // namespace Cubed

View File

@@ -10,8 +10,7 @@
namespace {} // namespace
namespace Cubed {
LocalPlayer::LocalPlayer(ClientWorld& world)
: Entity(0, "cubed:player"), m_world(world) {}
LocalPlayer::LocalPlayer(ClientWorld& world) : m_world(world) {}
LocalPlayer::~LocalPlayer() {}
const glm::vec3& LocalPlayer::get_front() const { return m_front; }
@@ -361,7 +360,8 @@ void LocalPlayer::update_move(float delta_time) {
glm::vec3{m_max_run_speed, m_max_y_speed, m_max_run_speed};
}
SpeedSystem::update(delta_time, *this);
SpeedSystem::update(delta_time, m_velocity, m_move_state, m_movement,
m_direction, m_gravity);
update_direction();
@@ -374,10 +374,12 @@ void LocalPlayer::update_move(float delta_time) {
}
if (m_game_mode == SPECTATOR) {
player_pos += PhysicalSystem::get_move_distance(delta_time, *this);
player_pos += PhysicalSystem::get_move_distance(delta_time, m_direction,
m_velocity);
} else {
auto [x, y, z] =
PhysicalSystem::update(delta_time, *this, m_world, player_pos);
PhysicalSystem::update(delta_time, m_world, player_pos, m_velocity,
m_direction, m_move_state, m_hitbox);
if (!x || !z) {
m_sprinting = false;
}
@@ -552,6 +554,9 @@ void LocalPlayer::reset_input_status() {
}
void LocalPlayer::init(std::string_view name) {
m_hitbox = HitboxManager::hitbox("cubed:player").id;
{
std::lock_guard lock(m_player_pos_mutex);
m_pos.value = {0.0f, 255.0f, 0.0f};
@@ -590,4 +595,16 @@ void LocalPlayer::init(std::string_view name) {
bool LocalPlayer::is_underwater() const { return m_underwater; }
void LocalPlayer::set_underwater(bool u) { m_underwater = u; }
glm::vec3& LocalPlayer::max_speed() { return m_velocity.max; }
float& LocalPlayer::acceleration() { return m_movement.acceleration; }
float& LocalPlayer::deceleration() { return m_movement.deceleration; }
float& LocalPlayer::g() { return m_gravity.value; }
void LocalPlayer::set_gait(Gait gait) { m_walk_pose.gait = gait; }
float LocalPlayer::yaw() const { return m_angle.yaw; }
float LocalPlayer::pitch() const { return m_angle.pitch; }
float& LocalPlayer::roll() { return m_angle.roll; }
float& LocalPlayer::walk_time() { return m_walk_pose.walk_time; }
Gait LocalPlayer::get_gait() const { return m_walk_pose.gait; }
} // namespace Cubed

View File

@@ -107,7 +107,7 @@ asio::awaitable<void> NetworkClient::read_loop() {
case std::to_underlying(PacketEnum::PLAYER_INFO_RSP): {
auto* rsp = Arena::Create<PlayerInfoRsp>(&arena);
if (decode_packet(*rsp, body_data, header)) {
m_world.receive_remote_player(*rsp);
m_world.player_manager().receive_remote_player(*rsp);
}
} break;
case std::to_underlying(PacketEnum::LOGOUT_RSP): {

View File

@@ -99,21 +99,28 @@ bool update_z(const glm::vec3& pos, const glm::vec3& distance, World& world,
}
} // namespace
std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, Entity& e,
std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, ServerEntity& e,
World& world) {
glm::vec3 pos = e.pos().value;
glm::vec3 pos = e.transform.position.value;
auto ans = update(dt, e, world, pos);
e.pos().value = pos;
e.transform.position.value = pos;
return ans;
}
std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, Entity& e,
std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, ServerEntity& e,
World& world,
glm::vec3& moved_pos) {
auto distance = get_move_distance(dt, e);
auto& m_velocity = e.velocity();
auto& m_move_state = e.move_state();
auto box = HitboxManager::hitbox(e.info().hitbox);
return update(dt, world, moved_pos, e.velocity, e.direction, e.move_state,
e.hitbox);
}
std::tuple<bool, bool, bool>
PhysicalSystem::update(float dt, World& world, glm::vec3& moved_pos,
Velocity& v, Direction& direction, MoveState& move_state,
HitboxID hitbox) {
auto distance = get_move_distance(dt, direction, v);
auto box = HitboxManager::hitbox(hitbox);
bool x = false;
bool y = false;
bool z = false;
@@ -121,17 +128,17 @@ std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, Entity& e,
moved_pos.x += distance.x;
x = true;
} else {
m_velocity.value.x = 0.0f;
v.value.x = 0.0f;
}
if (update_y(moved_pos, distance, world, box.box)) {
moved_pos.y += distance.y;
y = true;
} else {
m_velocity.value.y = 0.0f;
v.value.y = 0.0f;
if (distance.y < 0) {
m_move_state.can_up = true;
m_move_state.is_fly = false;
move_state.can_up = true;
move_state.is_fly = false;
}
}
@@ -139,16 +146,14 @@ std::tuple<bool, bool, bool> PhysicalSystem::update(float dt, Entity& e,
moved_pos.z += distance.z;
z = true;
} else {
m_velocity.value.z = 0.0f;
v.value.z = 0.0f;
}
return {x, y, z};
}
glm::vec3 PhysicalSystem::get_move_distance(float dt, const Entity& e) {
auto& m_direction = e.direction();
auto& m_velocity = e.velocity();
return glm::vec3{m_direction.value.x * m_velocity.value.x * dt,
m_velocity.value.y * dt,
m_direction.value.z * m_velocity.value.z * dt};
glm::vec3 PhysicalSystem::get_move_distance(float dt, const Direction& d,
const Velocity& v) {
return glm::vec3{d.value.x * v.value.x * dt, v.value.y * dt,
d.value.z * v.value.z * dt};
}
} // namespace Cubed

View File

@@ -1,56 +1,58 @@
#include "Cubed/gameplay/systems/speed_system.hpp"
namespace Cubed {
void SpeedSystem::update(float dt, Entity& e) {
auto& m_velocity = e.velocity();
auto& m_move_state = e.move_state();
auto& m_movement = e.movement();
auto& direction = e.direction();
auto& m_gravity = e.gravity();
void SpeedSystem::update(float dt, ServerEntity& e) {
update(dt, e.velocity, e.move_state, e.movement, e.direction, e.gravity);
}
void SpeedSystem::update(float dt, Velocity& v, MoveState& move_state,
Movement& movement, Direction& direction,
const Gravity& g) {
// calculate speed
if (m_move_state.forward || m_move_state.back || m_move_state.left ||
m_move_state.right) {
if (move_state.forward || move_state.back || move_state.left ||
move_state.right) {
direction.value = glm::vec3(0.0f, 0.0f, 0.0f);
m_velocity.value.x += m_movement.acceleration * dt;
m_velocity.value.z += m_movement.acceleration * dt;
if (m_velocity.value.x > m_velocity.max.x) {
m_velocity.value.x = m_velocity.max.x;
v.value.x += movement.acceleration * dt;
v.value.z += movement.acceleration * dt;
if (v.value.x > v.max.x) {
v.value.x = v.max.x;
}
if (m_velocity.value.z > m_velocity.max.z) {
m_velocity.value.z = m_velocity.max.z;
if (v.value.z > v.max.z) {
v.value.z = v.max.z;
}
} else {
m_velocity.value.x += -m_movement.deceleration * dt;
m_velocity.value.z += -m_movement.deceleration * dt;
if (m_velocity.value.z < 0.0f) {
m_velocity.value.z = 0.0f;
v.value.x += -movement.deceleration * dt;
v.value.z += -movement.deceleration * dt;
if (v.value.z < 0.0f) {
v.value.z = 0.0f;
}
if (m_velocity.value.x < 0.0f) {
m_velocity.value.x = 0.0f;
if (v.value.x < 0.0f) {
v.value.x = 0.0f;
}
if (m_velocity.value.z < 0.0f && m_velocity.value.x < 0.0f) {
if (v.value.z < 0.0f && v.value.x < 0.0f) {
direction.value = glm::vec3(0.0f, 0.0f, 0.0f);
}
}
if (m_move_state.is_fly) {
if (m_move_state.up) {
m_velocity.value.y = m_velocity.max.y;
if (move_state.is_fly) {
if (move_state.up) {
v.value.y = v.max.y;
}
if (m_move_state.down) {
m_velocity.value.y = -m_velocity.max.y;
if (move_state.down) {
v.value.y = -v.max.y;
}
if (!m_move_state.down && !m_move_state.up) {
m_velocity.value.y = 0.0f;
if (!move_state.down && !move_state.up) {
v.value.y = 0.0f;
}
} else {
if (m_move_state.up && m_move_state.can_up) {
m_velocity.value.y = m_movement.jump_power;
m_move_state.can_up = false;
if (move_state.up && move_state.can_up) {
v.value.y = movement.jump_power;
move_state.can_up = false;
}
m_velocity.value.y += -m_gravity.value * dt;
v.value.y += -g.value * dt;
}
}
} // namespace Cubed

View File

@@ -201,8 +201,10 @@ void PlayerRenderer::render(const Shader& shader, ClientWorld& world,
glm::mat4 m_v_mat = camera.get_camera_lookat();
glm::mat4 m_p_mat = m_renderer.world_proj_matrix();
auto& players = world.render_player_data();
auto players = world.player_manager().render_player_data();
if (!shadow_render) {
shader.set_loc("proj_matrix", m_p_mat);
}
for (auto& player : players) {