mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
* refactor(player): extract player rendering into PlayerRenderer class Move player rendering code from Renderer to new PlayerRenderer class. Add normal and tangent vertex attributes for improved per-pixel lighting. * feat(player-renderer): add shadow rendering and include local player data * feat(gameplay): add player yaw/pitch synchronization and rendering * refactor(player_renderer): split rendering into per-body-part VAOs and VBOs Move `PlayerVertex` struct to header and replace single VAO/VBO with arrays of 6 parts. Implement head pitch rotation in `render()` and `shadow_render()` by applying a separate model matrix for the head (index 0). Remove old `vao()` and `sum()` accessors. Adjust model translation for consistency. * feat(player): add texture mapping to player model using skin * fix(player-renderer): correct player rendering rotation and texture coordinates * feat(gameplay): add player gait system with limb animation * fix(player): update leg UVs and remove yaw wrap Update left and right leg UV coordinates to align with updated player texture. Remove yaw modulo operation to allow unrestricted yaw rotation beyond 360 degrees. * feat(camera): add third-person perspective and walk animation - Introduce Perspective enum (FIRST_PERSON, THIRD_PERSON_BACK, THIRD_PERSON_FRONT) and m_front member for camera direction. - Handle F5 key to cycle perspectives. - Add angle and walk_time to ClientPlayer for walking animation. - Update player rendering to skip local player only in first person and fix rotation sign. - Remove redundant player info reporting; update player data with animation angle. * fix(camera): replace magic number with constant and fix missing break * fix(client-player): stop sprinting on forward key release * feat: add camera collision and sphere collision for world * fix(skin): update player001 texture * refactor(gameplay): improve thread safety and remove debug logging * refactor(shaders): extract shadow and normal logic into include files and add lighting to player shaders * chore(shader): remove unused uniforms cameraPos and specularStrength * fix: inlcude <array> header
189 lines
6.0 KiB
C++
189 lines
6.0 KiB
C++
#pragma once
|
|
|
|
#include "Cubed/gameplay/cave_carver.hpp"
|
|
#include "Cubed/gameplay/chunk_pos.hpp"
|
|
#include "Cubed/gameplay/game_time.hpp"
|
|
#include "Cubed/gameplay/packet.hpp" // IWYU pragma: keep
|
|
#include "Cubed/gameplay/river_worm.hpp"
|
|
#include "Cubed/gameplay/server_chunk.hpp"
|
|
#include "Cubed/gameplay/server_player.hpp"
|
|
#include "Cubed/tools/priority_thread_pool.hpp"
|
|
#include "Cubed/tools/recent_queue.hpp"
|
|
#include "Cubed/tools/thread_pool.hpp"
|
|
#include "world/block_change.pb.h"
|
|
|
|
#include <absl/container/flat_hash_set.h>
|
|
#include <shared_mutex>
|
|
#include <tbb/concurrent_hash_map.h>
|
|
#include <tbb/concurrent_queue.h>
|
|
#include <tbb/concurrent_unordered_map.h>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
namespace Cubed {
|
|
class Session;
|
|
class ServerWorld {
|
|
public:
|
|
enum class ThreadPoolKind { NET, GEN };
|
|
ServerWorld();
|
|
~ServerWorld();
|
|
void stop();
|
|
void handle_player_exit(const std::string& uuid);
|
|
void init_world();
|
|
void need_gen(std::string uuid);
|
|
void update();
|
|
void hot_reload();
|
|
|
|
int rendering_distance() const;
|
|
void rendering_distance(int rendering_distance);
|
|
void start_gen_thread();
|
|
void start_server_thread();
|
|
|
|
void stop_gen_thread();
|
|
void stop_server_thread();
|
|
|
|
void stop_thread_pool();
|
|
void start_thread_pool();
|
|
|
|
void serever_run(std::stop_token stoken);
|
|
|
|
CaveCarver& cave_carcer();
|
|
RiverWorm& river_worm();
|
|
|
|
TickType game_tick() const;
|
|
TickType day_tick() const;
|
|
|
|
void day_tick(TickType tick);
|
|
|
|
int per_tick_time() const;
|
|
void per_tick_time(int ms);
|
|
bool is_tick_running() const;
|
|
void tick_running(bool run);
|
|
|
|
int gen_pool_threads() const;
|
|
int max_threads() const;
|
|
|
|
void change_pool_threads(ThreadPoolKind kind, int threads);
|
|
|
|
int chunk_load_style() const;
|
|
void set_chunk_load_style(int id);
|
|
|
|
bool set_block(const glm::ivec3& block_pos, unsigned id);
|
|
|
|
void sync_player_pos(const C2S_PlayerInfo& rsp);
|
|
void handle_player_login(const std::string& player_name,
|
|
std::shared_ptr<Session> session);
|
|
glm::vec3 get_player_pos(const std::string& uuid) const;
|
|
|
|
void handle_chunk_req(int task_id, const std::string& uuid, ChunkPos pos);
|
|
void handle_block_change(const BlockChangeReq& req);
|
|
|
|
int chunk_size() const;
|
|
template <typename Fn>
|
|
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
|
m_timers.emplace(std::piecewise_construct,
|
|
std::forward_as_tuple(std::string(id)),
|
|
std::forward_as_tuple(threshold, std::forward<Fn>(f)));
|
|
}
|
|
|
|
private:
|
|
enum class ChunkState { NONE, GENERATING, READY, PENDING_DELETE };
|
|
struct ChunkEntity {
|
|
ChunkState state;
|
|
std::shared_ptr<ServerChunk> chunk;
|
|
uint32_t ref_count = 0;
|
|
};
|
|
|
|
enum class ChunkLoadStyle { RANDOM, CENTER };
|
|
struct PendingRequest {
|
|
std::string uuid;
|
|
int task_id;
|
|
ChunkPos pos;
|
|
};
|
|
struct PendingChunk {
|
|
ChunkPos pos;
|
|
std::unique_ptr<ServerChunk> chunk;
|
|
};
|
|
|
|
using ChunkHashMap =
|
|
tbb::concurrent_hash_map<ChunkPos, ChunkEntity, ChunkPos::TBBHash>;
|
|
using PlayerHashMap = std::unordered_map<std::string, ServerPlayer>;
|
|
using NewChunkVector = std::vector<PendingChunk>;
|
|
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
|
using PlayerUUIDMap = tbb::concurrent_hash_map<std::string, std::string>;
|
|
|
|
using chunk_acc = ChunkHashMap::accessor;
|
|
using chunk_caac = ChunkHashMap::const_accessor;
|
|
|
|
using uuid_acc = PlayerUUIDMap::accessor;
|
|
using uuid_cacc = PlayerUUIDMap::const_accessor;
|
|
// key = uuid
|
|
PlayerHashMap m_players;
|
|
ChunkHashMap m_chunks;
|
|
|
|
CaveCarver m_cave_carcer;
|
|
RiverWorm m_river_worm;
|
|
|
|
std::jthread m_gen_thread;
|
|
std::jthread m_server_thread;
|
|
|
|
std::atomic<bool> m_chunk_gen_finished{false};
|
|
std::atomic<bool> m_could_gen{true};
|
|
std::atomic<bool> m_gen_running{false};
|
|
std::atomic<bool> m_need_gen_chunk{false};
|
|
std::atomic<bool> m_init{false};
|
|
std::atomic<bool> m_stopped{false};
|
|
std::atomic<int> m_rendering_distance{24};
|
|
std::atomic<int> m_gen_pool_threads{0};
|
|
std::atomic<int> m_net_pool_threads{0};
|
|
std::atomic<int> m_max_threads{1};
|
|
std::atomic<size_t> m_player_sum{0};
|
|
std::atomic<TickType> m_game_ticks{0};
|
|
std::atomic<TickType> m_day_tick{6000};
|
|
std::atomic<bool> m_tick_running{true};
|
|
std::atomic<int> m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms
|
|
|
|
mutable std::shared_mutex m_player_mutex;
|
|
std::mutex m_need_gen_queue_mutex;
|
|
std::condition_variable_any m_gen_cv;
|
|
|
|
RecentQueue<std::string> m_need_gen_queue;
|
|
|
|
std::atomic<std::shared_ptr<PriorityThreadPool>> m_gen_thread_pool;
|
|
std::atomic<std::shared_ptr<ThreadPool>> m_net_thread_pool;
|
|
|
|
std::atomic<ChunkLoadStyle> m_chunk_load_style{ChunkLoadStyle::CENTER};
|
|
|
|
PlayerUUIDMap m_uuid_to_name;
|
|
|
|
tbb::concurrent_unordered_map<std::string, Timer> m_timers;
|
|
tbb::concurrent_queue<PendingRequest> m_waiting_chunk_requests;
|
|
tbb::concurrent_queue<std::unique_ptr<ServerChunk>> m_finished_queue;
|
|
|
|
void init_chunks();
|
|
|
|
void gen_chunks_internal(const std::string& uuid);
|
|
|
|
void compute_required_chunks(ChunkPosSet& required_chunks,
|
|
const std::optional<std::string>& uuid);
|
|
void sync_and_collect_missing_chunks(std::vector<ChunkPos>&,
|
|
const ChunkPosSet&);
|
|
void submit_new_chunks(const std::string& uuid, NewChunkVector& new_chunks);
|
|
// void wait_all_chunk_tasks();
|
|
|
|
void update_ref_count(const ChunkPosSet& old, const ChunkPosSet& now);
|
|
|
|
void send_time();
|
|
|
|
void send_chunk(int task_id, const std::string& uuid, ChunkPos pos);
|
|
|
|
int
|
|
change_pool_threads(std::atomic<std::shared_ptr<ThreadPool>>& thread_pool,
|
|
int threads);
|
|
int change_pool_threads(
|
|
std::atomic<std::shared_ptr<PriorityThreadPool>>& thread_pool,
|
|
int threads);
|
|
void send_server_stop();
|
|
};
|
|
} // namespace Cubed
|