From cbe3548dcd7a63220ce2984753f0995f84d467e8 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Sun, 28 Jun 2026 19:29:52 +0800 Subject: [PATCH] refactor(gameplay): remove old pre_remove chunk, player, and world files --- include/Cubed/gameplay/pre_remove_chunk.hpp | 171 ---- include/Cubed/gameplay/pre_remove_player.hpp | 112 --- include/Cubed/gameplay/pre_remove_world.hpp | 173 ---- src/gameplay/pre_remove_chunk.cpp | 804 ------------------- src/gameplay/pre_remove_player.cpp | 544 ------------- src/gameplay/pre_remove_world.cpp | 702 ---------------- 6 files changed, 2506 deletions(-) delete mode 100644 include/Cubed/gameplay/pre_remove_chunk.hpp delete mode 100644 include/Cubed/gameplay/pre_remove_player.hpp delete mode 100644 include/Cubed/gameplay/pre_remove_world.hpp delete mode 100644 src/gameplay/pre_remove_chunk.cpp delete mode 100644 src/gameplay/pre_remove_player.cpp delete mode 100644 src/gameplay/pre_remove_world.cpp diff --git a/include/Cubed/gameplay/pre_remove_chunk.hpp b/include/Cubed/gameplay/pre_remove_chunk.hpp deleted file mode 100644 index c686210..0000000 --- a/include/Cubed/gameplay/pre_remove_chunk.hpp +++ /dev/null @@ -1,171 +0,0 @@ -#pragma once - -#include "Cubed/gameplay/biome.hpp" -#include "Cubed/gameplay/block.hpp" -#include "Cubed/gameplay/chunk_generator.hpp" -#include "Cubed/gameplay/chunk_pos.hpp" -#include "Cubed/gameplay/vertex_data.hpp" - -#include -#include -namespace Cubed { - -struct ChunkInfo { - ChunkPos pos{0, 0}; - unsigned seed{0}; - BiomeType biome{BiomeType::NONE}; - unsigned first_random{0}; - bool has_cave_start{false}; - bool has_cave{false}; -}; - -class World; -// if want to use, do init_chunk(), gen_vertex_data() and -class Chunk { -private: - using OptionalBlockVectorArray = - std::array>, 4>; - - struct FaceKey { - BlockType block_id = 0; - int face = -1; // 0-5, used to index NORMALS/TANGENTS/TEX_COORDS - - bool valid() const { return block_id != 0; } - bool operator==(const FaceKey& o) const { - return block_id == o.block_id && face == o.face; - } - bool operator!=(const FaceKey& o) const { return !(*this == o); } - }; - - static constexpr int SIZE_X = CHUNK_SIZE; - static constexpr int SIZE_Y = WORLD_SIZE_Y; - static constexpr int SIZE_Z = CHUNK_SIZE; - static constexpr int VERTEX_DATA_SUM = 5; - std::atomic m_dirty{false}; - std::atomic m_need_upload{true}; - std::atomic m_is_on_gen_vertex_data{false}; - std::atomic m_gening{false}; - std::atomic m_temp_chunk{false}; - - bool m_has_cave{false}; - - std::atomic m_biome = BiomeType::PLAIN; - std::mutex m_vertexs_data_mutex; - - std::unique_ptr m_generator; - - ChunkPos m_chunk_pos; - World& m_world; - HeightMapArray m_heightmap; - // the index is a array of block id - std::vector m_blocks; - - /* - 0 - normal - 1 - cross_plane - 2 - normal_discard - 3 - transparent and blend - 4 - water - */ - std::vector m_vertex_data; - float frequency = 0.01f; - float height = 80; - unsigned m_seed = 0; - - BiomeConditions m_conditions; - ChunkInfo m_info; - void clear_dirty(); - void gen_vertices(const OptionalBlockVectorArray& neighbor_block); - void gen_cross_plane_vertices(int world_x, int world_y, int world_z, - BlockType id); - void emit_quad(int axis, int face_dir, int layer, int i, int j, int w, - int h, int u_axis, int v_axis, FaceKey key); - -public: - Chunk(World& world, ChunkPos chunk_pos, bool temp_chunk = false); - ~Chunk(); - Chunk(const Chunk&) = delete; - Chunk& operator=(const Chunk&) = delete; - Chunk(Chunk&&) noexcept; - Chunk& operator=(Chunk&&) noexcept; - - static std::tuple world_to_block(int world_x, int world_y, - int world_z, int chunk_x, - int chunk_z); - static std::tuple world_to_block(const glm::ivec3& block_pos, - ChunkPos chunk_pos); - static std::tuple block_to_world(int x, int y, int z, - int chunk_x, int chunk_z); - static std::tuple block_to_world(const glm::ivec3& block_pos, - ChunkPos chunk_pos); - BiomeType get_biome() const; - ChunkPos get_chunk_pos() const; - const std::vector& get_chunk_blocks() const; - HeightMapArray get_heightmap() const; - static int index(int x, int y, int z); - static int index(const glm::vec3& pos); - // Init Chunk - // Determine biome from temperature and humidity noise - void gen_phase_one(); - // Resolve biome adjacency conflicts with neighbor chunks - void gen_phase_two(const std::array& adj_chunks); - // Generate heightmap using biome-specific noise - void gen_phase_three(); - // Blend heightmap with neighbors for smooth transitions - void gen_phase_four( - const std::array, 8>& neighbor_heightmap, - const std::array& neighbor_biome); - // Generate terrain blocks from heightmap and biome - void gen_phase_five(); - // Blend surface blocks at chunk borders with neighbors - void gen_phase_six(const std::array>, - 4>& neighbor_block); - // Generate biome-specific vegetation/structures - void gen_phase_seven(); - // void gen_vertex_data(); - // 0 : (1, 0) - // 1 : (-1, 0) - // 2 : (0, 1) - // 3 : (0, -1) - void gen_vertex_data(const OptionalBlockVectorArray& neighbor_block); - void upload_to_gpu(); - - GLuint get_normal_vao() const; - size_t get_normal_vertices_sum() const; - - GLuint get_cross_vao() const; - size_t get_cross_vertices_sum() const; - - GLuint get_normal_discard_vao() const; - size_t get_normal_discard_vertices_sum() const; - - GLuint get_normal_blend_vao() const; - size_t get_normal_blend_vertices_sum() const; - - GLuint get_water_vao() const; - size_t get_water_vertices_sum() const; - - bool is_dirty() const; - void mark_dirty(); - - bool is_need_upload() const; - void need_upload(); - - void set_chunk_block(int index, unsigned id); - // ensure thread safe! - void gen_chunk(); - - bool is_temp_chunk() const; - ChunkPos chunk_pos() const; - BiomeType biome() const; - void biome(BiomeType b); - HeightMapArray& heightmap(); - std::vector& blocks(); - World& world(); - unsigned seed() const; - BiomeConditions& conditions(); - ChunkInfo get_info() const; - bool& has_cave(); -}; - -} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/pre_remove_player.hpp b/include/Cubed/gameplay/pre_remove_player.hpp deleted file mode 100644 index 2dba631..0000000 --- a/include/Cubed/gameplay/pre_remove_player.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once -#include "Cubed/AABB.hpp" -#include "Cubed/constants.hpp" -#include "Cubed/gameplay/block.hpp" -#include "Cubed/gameplay/chunk_pos.hpp" -#include "Cubed/gameplay/game_mode.hpp" -#include "Cubed/input.hpp" - -#include -#include -#include - -namespace Cubed { - -enum class Gait { WALK = 0, RUN }; - -class World; - -class Player { -private: - using enum GameMode; - float m_max_walk_speed = DEFAULT_MAX_WALK_SPEED; - float m_max_run_speed = DEFAULT_MAX_RUN_SPEED; - float m_acceleration = DEFAULT_ACCELERATION; - float m_deceleration = DEFAULT_DECELERATION; - float m_g = DEFAULT_G; - - constexpr static float MAX_SPACE_ON_TIME = 0.3f; - - float m_yaw = 0.0f; - float m_pitch = 0.0f; - - float m_sensitivity = 0.15f; - - float m_max_speed = m_max_walk_speed; - float m_y_speed = 0.0f; - float m_fly_y_speed = 7.5f; - bool can_up = true; - - float space_on_time = 0.0f; - bool space_on = false; - bool is_fly = false; - - float m_xz_speed = 0.0f; - - unsigned m_place_block = 1; - - glm::vec3 direction = glm::vec3(0.0f, 0.0f, 0.0f); - glm::vec3 move_distance{0.0f, 0.0f, 0.0f}; - // player is tow block tall, the pos is the lower pos - - glm::vec3 m_player_pos{0.0f, 255.0f, 0.0f}; - ChunkPos m_player_chunk_pos{0, 0}; - - glm::vec3 m_front{0, 0, -1}; - glm::vec3 m_right{0, 0, 0}; - glm::vec3 m_size{0.6f, 1.8f, 0.6f}; - - Gait m_gait = Gait::WALK; - MoveState m_move_state{}; - GameMode m_game_mode = CREATIVE; - std::optional m_look_block = std::nullopt; - std::string m_name{}; - World& m_world; - - bool ray_cast(const glm::vec3& start, const glm::vec3& dir, - glm::ivec3& block_pos, glm::vec3& normal, - float distance = 4.0f); - - void check_player_chunk_transition(); - void update_direction(); - void update_lookup_block(); - void update_move(float delta_time); - void update_x_move(); - void update_y_move(); - void update_z_move(); - -public: - Player(World& world, const std::string& name); - ~Player(); - AABB get_aabb() const; - const glm::vec3& get_front() const; - const Gait& get_gait() const; - const std::optional& get_look_block_pos() const; - const glm::vec3& get_player_pos() const; - const MoveState& get_move_state() const; - - void change_mode(GameMode mode); - void hot_reload(); - void set_player_pos(const glm::vec3& pos); - void set_place_block(unsigned id); - void update(float delta_time); - void update_front_vec(float offset_x, float offset_y); - void update_player_move_state(int key, int action); - void update_scroll(double yoffset); - - float& max_walk_speed(); - float& max_run_speed(); - float& max_speed(); - float& acceleration(); - float& deceleration(); - float& g(); - float& fly_y_speed(); - - unsigned place_block() const; - - Gait& gait(); - GameMode& game_mode(); - const World& get_world() const; -}; - -} // namespace Cubed diff --git a/include/Cubed/gameplay/pre_remove_world.hpp b/include/Cubed/gameplay/pre_remove_world.hpp deleted file mode 100644 index a789752..0000000 --- a/include/Cubed/gameplay/pre_remove_world.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#pragma once -#include "Cubed/AABB.hpp" -#include "Cubed/gameplay/cave_carver.hpp" -#include "Cubed/gameplay/chunk.hpp" -#include "Cubed/gameplay/game_time.hpp" -#include "Cubed/gameplay/river_worm.hpp" -#include "Cubed/tools/thread_pool.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Cubed { - -struct ChunkRenderSnapshot { - GLuint normal_vao; - size_t normal_vertices_count; - GLuint cross_vao; - size_t cross_vertices_count; - GLuint normal_discard_vao; - size_t normal_discard_vertices_count; - GLuint normal_blend_vao; - size_t normal_blend_vertices_count; - GLuint water_vao; - size_t water_vertices_count; - glm::vec3 center; - glm::vec3 half_extents; -}; - -class Player; -class TextureManager; -class World { -private: - enum class ChunkLoadStyle { RANDOM, CENTER }; - - struct PendingChunk { - Chunk chunk; - std::future future; - }; - - using OptionalBlockVectorArray = - std::array>, 4>; - using ChunkPtrUpdateList = std::vector>; - using ChunkPairVector = std::vector>; - using ChunkPairQueue = std::queue>; - using ConstChunkMap = - std::unordered_map; - using ChunkPosSet = std::unordered_set; - using ChunkHashMap = std::unordered_map; - using PendingChunkHashMap = - std::unordered_map; - glm::vec3 m_gen_player_pos{0.0f, 0.0f, 0.0f}; - ChunkHashMap m_chunks; - std::unordered_map m_players; - std::vector m_planes; - - std::thread m_gen_thread; - std::thread m_server_thread; - std::atomic> m_gen_thread_pool; - std::stop_source m_server_stop_source; - - std::atomic m_per_tick_time = DEFAULT_PER_TICK_TIME; // ms - - std::atomic m_day_tick = 6000; - - mutable std::shared_mutex m_chunks_mutex; - std::mutex m_gen_signal_mutex; - std::mutex m_new_chunk_mutex; - std::mutex m_delete_vbo_mutex; - std::mutex m_delete_vao_mutex; - std::mutex m_gen_player_pos_mutex; - std::vector m_pending_delete_vbo; - std::vector m_pending_delete_vao; - std::condition_variable m_gen_cv; - std::atomic m_gen_running{false}; - std::atomic m_need_gen_chunk{false}; - std::atomic m_is_rebuilding{false}; - std::atomic m_chunk_gen_finished{false}; - std::atomic m_could_gen{true}; - std::atomic m_tick_running{true}; - std::atomic m_rendering_distance{24}; - std::atomic m_pool_threads{0}; - std::atomic m_max_threads{1}; - std::atomic m_game_ticks{0}; - std::atomic m_chunk_load_style{ChunkLoadStyle::RANDOM}; - std::vector m_dirty_queue; - std::vector m_render_snapshots; - std::vector> m_new_finished_chunk; - // Can only be used in the gen thread - PendingChunkHashMap new_chunks; - - CaveCarver m_cave_carcer; - RiverWorm m_river_worm; - void init_chunks(); - - void gen_chunks_internal(); - void sync_player_pos(glm::vec3& player_pos); - void compute_required_chunks(ChunkPosSet& required_chunks); - void sync_and_collect_missing_chunks(std::vector&, - const ChunkPosSet&); - - void submit_new_chunks(); - void poll_finished_chunks(); - void wait_all_chunk_tasks(); - -public: - World(); - ~World(); - - bool can_move(const AABB& player_box) const; - // const BlockRenderData& get_block_render_data(int x, int y ,int z); - - const std::optional& - get_look_block_pos(const std::string& name) const; - // const Chunk* get_chunk(const ChunkPos& pos) const; - - Player& get_player(const std::string& name); - void init_world(); - int get_block(const glm::ivec3& block_pos) const; - bool is_solid(const glm::ivec3& block_pos) const; - bool can_pass_block(const glm::ivec3& block_pos) const; - BlockType get_block_tpye(const glm::ivec3& block_pos) const; - static ChunkPos get_chunk_pos(int world_x, int world_z); - - void need_gen(); - - void set_block(const glm::ivec3& pos, unsigned id); - void update(float delta_time); - - void push_delete_vbo(GLuint vbo); - void push_delete_vao(GLuint vao); - void hot_reload(); - - void rebuild_world(); - - 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(); - std::vector& planes(); - std::vector& render_snapshots(); - - glm::vec3 sunlight_dir() const; - 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 pool_threads() const; - int max_threads() const; - void change_pool_threads(int threads); - int chunk_load_style() const; - void set_chunk_load_style(int id); - ChunkInfo get_chunk_info(const glm::vec3& world_pos) const; -}; - -} // namespace Cubed diff --git a/src/gameplay/pre_remove_chunk.cpp b/src/gameplay/pre_remove_chunk.cpp deleted file mode 100644 index 69f33e4..0000000 --- a/src/gameplay/pre_remove_chunk.cpp +++ /dev/null @@ -1,804 +0,0 @@ -#include "Cubed/gameplay/chunk.hpp" -#include "Cubed/gameplay/world.hpp" -#include "Cubed/tools/cubed_assert.hpp" -#include "Cubed/tools/log.hpp" - -#include - -namespace Cubed { -using OptionalBlockVectorArray = - std::array>, 4>; -namespace { -// ──────────────────────────────────────────────────────────────────────────── -// Face direction mapping -// Original DIR[6]: {+Z,+X,-Z,-X,+Y,-Y} => face index 0-5 -// Axis × direction => face: -// axis=2(Z) dir=+1 => face 0 (+Z) -// axis=0(X) dir=+1 => face 1 (+X) -// axis=2(Z) dir=-1 => face 2 (-Z) -// axis=0(X) dir=-1 => face 3 (-X) -// axis=1(Y) dir=+1 => face 4 (+Y) -// axis=1(Y) dir=-1 => face 5 (-Y) -// ──────────────────────────────────────────────────────────────────────────── - -inline int axis_dir_to_face(int axis, int dir) { - // axis: 0=X 1=Y 2=Z - // dir: +1 or -1 - static const int TABLE[3][2] = { - {3, 1}, // X: dir=-1->face3(-X), dir=+1->face1(+X) - {5, 4}, // Y: dir=-1->face5(-Y), dir=+1->face4(+Y) - {2, 0}, // Z: dir=-1->face2(-Z), dir=+1->face0(+Z) - }; - return TABLE[axis][dir > 0 ? 1 : 0]; -} - -inline BlockType -get_block_safe(int lx, int ly, int lz, ChunkPos& chunk_pos, - const std::vector& blocks, - const OptionalBlockVectorArray& neighbor_block) { - if (lx >= 0 && lx < CHUNK_SIZE && ly >= 0 && ly < WORLD_SIZE_Y && lz >= 0 && - lz < CHUNK_SIZE) { - return blocks[Chunk::index(lx, ly, lz)]; - } - - // Out of bounds: check neighbors - int world_x = lx + chunk_pos.x * CHUNK_SIZE; - int world_z = lz + chunk_pos.z * CHUNK_SIZE; - - auto [nb_cx, nb_cz] = World::get_chunk_pos(world_x, world_z); - - const std::optional>* nb = nullptr; - if (nb_cx == chunk_pos.x + 1) - nb = &neighbor_block[0]; - else if (nb_cx == chunk_pos.x - 1) - nb = &neighbor_block[1]; - else if (nb_cz == chunk_pos.z + 1) - nb = &neighbor_block[2]; - else if (nb_cz == chunk_pos.z - 1) - nb = &neighbor_block[3]; - - if (!nb || !nb->has_value()) - return 0; // Neighbor does not exist, treat as opaque - - int nbx = world_x - nb_cx * CHUNK_SIZE; - int nby = ly; - int nbz = world_z - nb_cz * CHUNK_SIZE; - - if (nbx < 0 || nby < 0 || nbz < 0 || nbx >= CHUNK_SIZE || - nby >= WORLD_SIZE_Y || nbz >= CHUNK_SIZE) - return 0; - - int idx = Chunk::index(nbx, nby, nbz); - if (static_cast(idx) >= (*nb)->size()) { - return 0; - } - - return (**nb)[idx]; -} -// Determine whether the face from cur_id looking towards neighbor_id should be -// culled (does not need to be rendered) -inline bool is_face_culled(BlockType cur_id, BlockType neighbor_id) { - if (!BlockManager::is_transparent(neighbor_id)) - return true; // Neighbor is opaque, blocking - // Neighbor transparency: same block type culls each other (e.g., water - // adjacent to water does not render internal faces) - if (neighbor_id == cur_id) - return true; - return false; -} - -inline int choose_buf(BlockType id) { - if (!BlockManager::is_transparent(id)) - return 0; - if (BlockManager::is_discard(id)) - return 2; - if (BlockManager::is_blend(id)) { - return (id == 7) ? 4 : 3; // water=4, other blend=3 - } - return 3; // fallback -} - -} // namespace - -Chunk::Chunk(World& world, ChunkPos chunk_pos, bool temp_chunk) - : m_temp_chunk(temp_chunk), m_chunk_pos(chunk_pos), m_world(world) { - for (int i = 0; i < VERTEX_DATA_SUM; i++) { - m_vertex_data.emplace_back(m_world); - } -} - -Chunk::~Chunk() {} - -Chunk::Chunk(Chunk&& other) noexcept - : m_dirty(other.is_dirty()), m_need_upload(other.m_need_upload.load()), - m_is_on_gen_vertex_data(other.m_is_on_gen_vertex_data.load()), - m_biome(other.m_biome.load()), m_chunk_pos(std::move(other.m_chunk_pos)), - m_world(other.m_world), m_heightmap(std::move(other.m_heightmap)), - m_blocks(std::move(other.m_blocks)), - m_vertex_data(std::move(other.m_vertex_data)), m_seed(other.m_seed), - m_conditions(other.m_conditions), m_info(std::move(other.m_info)) {} - -Chunk& Chunk::operator=(Chunk&& other) noexcept { - // Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&& - // other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z, - // static_cast(&other)); - - m_chunk_pos = std::move(other.m_chunk_pos); - m_heightmap = std::move(other.m_heightmap); - m_blocks = std::move(other.m_blocks); - m_dirty = other.is_dirty(); - m_vertex_data = std::move(other.m_vertex_data); - m_biome = other.m_biome.load(); - m_is_on_gen_vertex_data = other.m_is_on_gen_vertex_data.load(); - m_need_upload = other.m_need_upload.load(); - m_seed = other.m_seed; - m_conditions = other.m_conditions; - m_info = std::move(other.m_info); - return *this; -} - -std::tuple Chunk::world_to_block(int world_x, int world_y, - int world_z, int chunk_x, - int chunk_z) { - int x, y, z; - y = world_y; - x = world_x - chunk_x * CHUNK_SIZE; - z = world_z - chunk_z * CHUNK_SIZE; - return {x, y, z}; -} - -std::tuple Chunk::world_to_block(const glm::ivec3& block_pos, - ChunkPos chunk_pos) { - return world_to_block(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x, - chunk_pos.z); -} - -std::tuple Chunk::block_to_world(int x, int y, int z, - int chunk_x, int chunk_z) { - int world_x = x + chunk_x * CHUNK_SIZE; - int world_z = z + chunk_z * CHUNK_SIZE; - int world_y = y; - return {world_x, world_y, world_z}; -} -std::tuple Chunk::block_to_world(const glm::ivec3& block_pos, - ChunkPos chunk_pos) { - return block_to_world(block_pos.x, block_pos.y, block_pos.z, chunk_pos.x, - chunk_pos.z); -} - -BiomeType Chunk::get_biome() const { return m_biome.load(); } - -ChunkPos Chunk::get_chunk_pos() const { return m_chunk_pos; } - -const std::vector& Chunk::get_chunk_blocks() const { - return m_blocks; -} - -HeightMapArray Chunk::get_heightmap() const { - // Logger::info("Chunk pos {} {} in get_heightmap this {}", m_chunk_pos.x, - // m_chunk_pos.z, static_cast(this)); - return m_heightmap; -} - -int Chunk::index(int x, int y, int z) { - ASSERT(!(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE)); - if ((x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z < 0 || - (x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z >= - CHUNK_SIZE * CHUNK_SIZE * WORLD_SIZE_Y) { - Logger::error("block pos x {} y {} z {} range error", x, y, z); - ASSERT(0); - } - return (x * WORLD_SIZE_Y + y) * CHUNK_SIZE + z; -} - -int Chunk::index(const glm::vec3& pos) { - return Chunk::index(pos.x, pos.y, pos.z); -} - -void Chunk::gen_vertex_data(const OptionalBlockVectorArray& neighbor_block) { - if (m_is_on_gen_vertex_data) { - return; - } - m_is_on_gen_vertex_data = true; - std::lock_guard lk(m_vertexs_data_mutex); - - for (auto& data : m_vertex_data) { - data.m_vertices.clear(); - } - - gen_vertices(neighbor_block); - for (auto& data : m_vertex_data) { - data.update_sum(); - } - m_need_upload = true; - m_is_on_gen_vertex_data = false; -} - -GLuint Chunk::get_normal_vao() const { return m_vertex_data[0].m_vao; } - -size_t Chunk::get_normal_vertices_sum() const { - if (m_vertex_data[0].m_sum == 0) { - Logger::warn("m_normal_vertices_sum is 0"); - } - return m_vertex_data[0].m_sum.load(); -} - -GLuint Chunk::get_cross_vao() const { return m_vertex_data[1].m_vao; } -size_t Chunk::get_cross_vertices_sum() const { - return m_vertex_data[1].m_sum.load(); -} - -GLuint Chunk::get_normal_discard_vao() const { return m_vertex_data[2].m_vao; } -size_t Chunk::get_normal_discard_vertices_sum() const { - return m_vertex_data[2].m_sum.load(); -} - -GLuint Chunk::get_normal_blend_vao() const { return m_vertex_data[3].m_vao; } -size_t Chunk::get_normal_blend_vertices_sum() const { - return m_vertex_data[3].m_sum.load(); -} - -GLuint Chunk::get_water_vao() const { return m_vertex_data[4].m_vao; } -size_t Chunk::get_water_vertices_sum() const { - return m_vertex_data[4].m_sum.load(); -} - -void Chunk::gen_phase_one() { - // m_generator = std::make_unique(*this); - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - m_generator->assign_chunk_biome(); - m_seed = m_generator->chunk_seed(); -} - -void Chunk::gen_phase_two(const std::array& adj_chunks) { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - // m_generator->resolve_biome_adjacency_conflict(adj_chunks); -} - -void Chunk::gen_phase_three() { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - m_generator->generate_heightmap(); -} - -void Chunk::gen_phase_four( - const std::array, 8>& neighbor_heightmap, - const std::array& neighbor_biome) { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - // m_generator->blend_heightmap_boundaries(neighbor_heightmap, - // neighbor_biome); -} - -void Chunk::gen_phase_five() { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - m_generator->generate_terrain_blocks(); -} - -void Chunk::gen_phase_six( - const std::array>, 4>& - neighbor_block) { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - // This must be fully completed before any other operations can proceed! - m_generator->blend_surface_blocks_borders(neighbor_block); -} - -void Chunk::gen_phase_seven() { - if (!m_generator) { - Logger::error("ChunkGenerator is Nullptr"); - return; - } - m_generator->ocean_build(); - m_generator->generate_river(); - m_generator->generate_cave(); - - m_generator->generate_vegetation(); - mark_dirty(); - m_generator = nullptr; -} - -void Chunk::upload_to_gpu() { - - ASSERT(is_need_upload()); - - std::lock_guard lk(m_vertexs_data_mutex); - - for (auto& data : m_vertex_data) { - data.upload(); - } - - // after fininshed it, can use - clear_dirty(); - m_need_upload = false; -} - -bool Chunk::is_dirty() const { return m_dirty.load(); } - -void Chunk::mark_dirty() { m_dirty = true; } - -void Chunk::clear_dirty() { m_dirty = false; } - -bool Chunk::is_need_upload() const { return m_need_upload.load(); } - -void Chunk::need_upload() { m_need_upload = true; } - -void Chunk::set_chunk_block(int index, unsigned id) { - m_blocks[index] = id; - mark_dirty(); -} - -ChunkPos Chunk::chunk_pos() const { return m_chunk_pos; } - -BiomeType Chunk::biome() const { return m_biome; } - -void Chunk::biome(BiomeType b) { m_biome = b; } - -HeightMapArray& Chunk::heightmap() { return m_heightmap; } -std::vector& Chunk::blocks() { return m_blocks; } -World& Chunk::world() { return m_world; } -unsigned Chunk::seed() const { - if (m_seed == 0) { - Logger::warn("Seed Not Generator"); - } - return m_seed; -} - -BiomeConditions& Chunk::conditions() { return m_conditions; } - -ChunkInfo Chunk::get_info() const { - if (m_gening) { - return ChunkInfo{}; - } - return m_info; -} -/* -void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) { - static const glm::ivec3 DIR[6] = {{0, 0, 1}, {1, 0, 0}, {0, 0, -1}, - {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}}; - - for (int x = 0; x < SIZE_X; x++) { - for (int y = 0; y < SIZE_Y; y++) { - for (int z = 0; z < SIZE_Z; z++) { - int world_x = x + m_chunk_pos.x * CHUNK_SIZE; - int world_z = z + m_chunk_pos.z * CHUNK_SIZE; - int world_y = y; - int cur_id = m_blocks[index(x, y, z)]; - // air - if (cur_id == 0) { - continue; - } - - for (int face = 0; face < 6; face++) { - int nx = x + DIR[face].x; - int ny = y + DIR[face].y; - int nz = z + DIR[face].z; - bool neighbor_culled = false; - - if (nx < 0 || nx >= SIZE_X || ny < 0 || ny >= SIZE_Y || - nz < 0 || nz >= SIZE_Z) { - - int world_nx = world_x + DIR[face].x; - int world_ny = world_y + DIR[face].y; - int world_nz = world_z + DIR[face].z; - - auto [neighbor_x, neighbor_z] = - World::get_chunk_pos(world_nx, world_nz); - - auto is_culled = - [&](const std::optional>& - chunk_blocks) { - if (chunk_blocks == std::nullopt) { - return true; - } - int x, y, z; - y = world_ny; - x = world_nx - neighbor_x * CHUNK_SIZE; - z = world_nz - neighbor_z * CHUNK_SIZE; - if (x < 0 || y < 0 || z < 0 || - x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - return false; - } - - int idx = Chunk::index(x, y, z); - // not init - if (static_cast(idx) >= - chunk_blocks->size()) { - // Logger::warn("not init"); - return true; - } - auto id = (*chunk_blocks)[idx]; - // transparent - if (BlockManager::is_transparent(id)) { - if (id == cur_id) { - return true; - } else { - return false; - } - - } else { - return true; - } - }; - - if (m_chunk_pos.x + 1 == neighbor_x) { - neighbor_culled = is_culled(neighbor_block[0]); - } else if (m_chunk_pos.x - 1 == neighbor_x) { - neighbor_culled = is_culled(neighbor_block[1]); - } else if (m_chunk_pos.z + 1 == neighbor_z) { - neighbor_culled = is_culled(neighbor_block[2]); - } else if (m_chunk_pos.z - 1 == neighbor_z) { - neighbor_culled = is_culled(neighbor_block[3]); - } - // neighbor_cull = m_world.is_block(glm::ivec3(world_x, - // world_y, world_z) + DIR[face]); - } else { - auto neighbor_id = m_blocks[index(nx, ny, nz)]; - // transparent block - if (!BlockManager::is_transparent(neighbor_id)) { - neighbor_culled = true; - } else { - if (neighbor_id == cur_id) { - neighbor_culled = true; - } else { - neighbor_culled = false; - } - } - } - - if (neighbor_culled) { - continue; - } - if (BlockManager::is_cross_plane(cur_id)) { - gen_cross_plane_vertices(world_x, world_y, world_z, - cur_id); - } - for (int i = 0; i < 6; i++) { - Vertex3D vex = { - VERTICES_POS[face][i][0] + (float)world_x * 1.0f, - VERTICES_POS[face][i][1] + (float)world_y * 1.0f, - VERTICES_POS[face][i][2] + (float)world_z * 1.0f, - TEX_COORDS[face][i][0], - TEX_COORDS[face][i][1], - - static_cast(cur_id * 6 + face), - - NORMALS[face][i][0], - NORMALS[face][i][1], - NORMALS[face][i][2], - BlockManager::roughness(cur_id), - TANGENTS[face][i][0], - TANGENTS[face][i][1], - TANGENTS[face][i][2] - - }; - if (BlockManager::is_transparent(cur_id)) { - if (BlockManager::is_discard(cur_id) && - BlockManager::is_blend(cur_id)) { - Logger::warn( - "Block id {} is both discard and blend is " - "must only one can true !!!", - cur_id); - } - if (BlockManager::is_discard(cur_id)) { - m_vertex_data[2].m_vertices.emplace_back(vex); - } else if (BlockManager::is_blend(cur_id)) { - if (cur_id == 7) { - m_vertex_data[4].m_vertices.emplace_back( - vex); - } else { - m_vertex_data[3].m_vertices.emplace_back( - vex); - } - - } else { - Logger::warn("Id {} is transparent but not " - "discard or blend", - cur_id); - m_vertex_data[3].m_vertices.emplace_back(vex); - } - - } else { - m_vertex_data[0].m_vertices.emplace_back(vex); - } - } - } - } - } - } -} -*/ -void Chunk::gen_vertices(const OptionalBlockVectorArray& neighbor_block) { - - // SIZE_X=SIZE_Z=CHUNK_SIZE=16, SIZE_Y=WORLD_SIZE_Y=256 - // Axis order: axis 0=X, 1=Y, 2=Z - // Two slice dimensions of each axis - const int DIMS[3] = {CHUNK_SIZE, WORLD_SIZE_Y, CHUNK_SIZE}; - - // Maximum mask size: max(16*256, 16*16) = 4096 - static thread_local FaceKey mask[CHUNK_SIZE * WORLD_SIZE_Y]; - static thread_local bool visited[CHUNK_SIZE * WORLD_SIZE_Y]; - - for (int axis = 0; axis < 3; axis++) { - int u_axis = (axis + 1) % 3; // horizontal - int v_axis = (axis + 2) % 3; // vertical - - int u = DIMS[u_axis]; - int v = DIMS[v_axis]; - int d = DIMS[axis]; // Depth along the normal axis - - for (int face_dir : {1, -1}) { - int face_idx = axis_dir_to_face(axis, face_dir); - - for (int layer = 0; layer < d; layer++) { - - // ── 1. Build mask ────────────────────────────────────────── - for (int vi = 0; vi < v; vi++) { - for (int ui = 0; ui < u; ui++) { - // Current cell local coordinates - int lpos[3]; - lpos[axis] = layer; - lpos[u_axis] = ui; - lpos[v_axis] = vi; - - // Neighbor (offset one cell along the normal direction) - int npos[3]; - npos[axis] = layer + face_dir; - npos[u_axis] = ui; - npos[v_axis] = vi; - - BlockType cur_id = get_block_safe( - lpos[0], lpos[1], lpos[2], m_chunk_pos, m_blocks, - neighbor_block); - - // Air / cross plane are not involved in greedy meshing - if (cur_id == 0 || - BlockManager::is_cross_plane(cur_id)) { - mask[vi * u + ui] = {}; - continue; - } - - BlockType nb_id = get_block_safe( - npos[0], npos[1], npos[2], m_chunk_pos, m_blocks, - neighbor_block); - - if (is_face_culled(cur_id, nb_id)) { - mask[vi * u + ui] = {}; - } else { - mask[vi * u + ui] = {cur_id, face_idx}; - } - } - } - - // ── 2. Greedy Merge ────────────────────────────────────── - std::fill(visited, visited + u * v, false); - - for (int vi = 0; vi < v; vi++) { - for (int ui = 0; ui < u; ui++) { - if (visited[vi * u + ui]) - continue; - FaceKey cur = mask[vi * u + ui]; - if (!cur.valid()) - continue; - - // Extend width in the u direction - int w = 1; - while (ui + w < u && !visited[vi * u + (ui + w)] && - mask[vi * u + (ui + w)] == cur) { - w++; - } - - // Extend height in the v direction - int h = 1; - bool can_expand = true; - while (vi + h < v && can_expand) { - for (int k = 0; k < w; k++) { - int idx = (vi + h) * u + (ui + k); - if (visited[idx] || mask[idx] != cur) { - can_expand = false; - break; - } - } - if (can_expand) - h++; - } - - // mark visited - for (int dv = 0; dv < h; dv++) - for (int du = 0; du < w; du++) - visited[(vi + dv) * u + (ui + du)] = true; - - // output quad - emit_quad(axis, face_dir, layer, ui, vi, w, h, u_axis, - v_axis, cur); - } - } - } - } - } - - for (int x = 0; x < CHUNK_SIZE; x++) { - for (int y = 0; y < WORLD_SIZE_Y; y++) { - for (int z = 0; z < CHUNK_SIZE; z++) { - BlockType id = m_blocks[index(x, y, z)]; - if (id != 0 && BlockManager::is_cross_plane(id)) { - int world_x = x + m_chunk_pos.x * CHUNK_SIZE; - int world_z = z + m_chunk_pos.z * CHUNK_SIZE; - gen_cross_plane_vertices(world_x, y, world_z, id); - } - } - } - } -} -void Chunk::emit_quad(int axis, int face_dir, int layer, int i, int j, int w, - int h, int u_axis, int v_axis, FaceKey key) { - float axis_val = (float)(layer + (face_dir > 0 ? 1 : 0)); - float wx_base = (float)(m_chunk_pos.x * CHUNK_SIZE); - float wz_base = (float)(m_chunk_pos.z * CHUNK_SIZE); - - // Offsets of the four corners along the u_axis/v_axis - int su[4] = {0, w, w, 0}; - int sv[4] = {0, 0, h, h}; - - // Each face's UV: directly read from the four corners of TEX_COORDS, then - // scaled by w/h TEX_COORDS vertex order: 0=BL, 1=TL, 2=TR, 3=TR, 4=BR, 5=BL - // (two triangles) Four unique corners correspond to indices: BL=0, TL=1, - // TR=2, BR=4 Extract the UVs of the four corners from TEX_COORDS (unique - // corners after removing duplicate vertices) Vertices 0,1,2,4 correspond to - // BL, TL, TR, BR - float u0 = TEX_COORDS[key.face][0][0]; // BL.u - float v0 = TEX_COORDS[key.face][0][1]; // BL.v - float u1 = TEX_COORDS[key.face][4][0]; // BR.u - float v1 = TEX_COORDS[key.face][4][1]; // BR.v - float u3 = TEX_COORDS[key.face][1][0]; // TL.u - float v3 = TEX_COORDS[key.face][1][1]; // TL.v - - float du_u = u1 - u0; // Change in u when su increases (per block) - float dv_u = v1 - v0; - float du_v = u3 - u0; // Change in u when sv increases - float dv_v = v3 - v0; - - float uvs[4][2] = { - {u0, v0}, // (0, 0 ) - {u0 + du_u * (float)w, v0 + dv_u * (float)w}, // (w, 0 ) - {u0 + du_u * (float)w + du_v * (float)h, - v0 + dv_u * (float)w + dv_v * (float)h}, // (w, h ) - {u0 + du_v * (float)h, v0 + dv_v * (float)h}, // (0, h ) - }; - - int tri[6] = {0, 1, 2, 0, 2, 3}; - - float pos[4][3]; - for (int c = 0; c < 4; c++) { - pos[c][axis] = axis_val; - pos[c][u_axis] = (float)(i + su[c]); - pos[c][v_axis] = (float)(j + sv[c]); - pos[c][0] += wx_base; - pos[c][2] += wz_base; - } - - float layer_id = (float)(key.block_id * 6 + key.face); - float roughness = BlockManager::roughness(key.block_id); - int buf = choose_buf(key.block_id); - - for (int vi = 0; vi < 6; vi++) { - int c = tri[vi]; - Vertex3D vex = { - pos[c][0], - pos[c][1], - pos[c][2], - uvs[c][0], - uvs[c][1], - layer_id, - NORMALS[key.face][0][0], - NORMALS[key.face][0][1], - NORMALS[key.face][0][2], - roughness, - TANGENTS[key.face][0][0], - TANGENTS[key.face][0][1], - TANGENTS[key.face][0][2], - }; - m_vertex_data[buf].m_vertices.emplace_back(vex); - } -} - -void Chunk::gen_cross_plane_vertices(int world_x, int world_y, int world_z, - BlockType id) { - - if (!BlockManager::is_cross_plane(id)) { - Logger::warn("Block {} {} {} id {} is not cross plane", world_x, - world_y, world_z, id); - return; - } - for (int face = 0; face < 2; face++) { - for (int i = 0; i < 6; i++) { - Vertex3D vex = { - CROSS_VERTICES_POS[face][i][0] + (float)world_x * 1.0f, - CROSS_VERTICES_POS[face][i][1] + (float)world_y * 1.0f, - CROSS_VERTICES_POS[face][i][2] + (float)world_z * 1.0f, - CROSS_TEX_COORDS[face][i][0], - CROSS_TEX_COORDS[face][i][1], - static_cast(BlockManager::cross_plane_index(id)), - CROSS_NORMALS[face][i][0], - CROSS_NORMALS[face][i][1], - CROSS_NORMALS[face][i][2], - BlockManager::roughness(id), - CROSS_TANGENTS[face][i][0], - CROSS_TANGENTS[face][i][1], - CROSS_TANGENTS[face][i][2] - - }; - m_vertex_data[1].m_vertices.emplace_back(vex); - } - } -} - -void Chunk::gen_chunk() { - if (m_gening.exchange(true)) - return; - m_gening = true; - if (m_blocks.size() != 0) { - Logger::warn( - "Request Generator Chunk {} {} ,but the Blocks size is Not 0", - m_chunk_pos.x, m_chunk_pos.z); - } - std::vector neighbor; - for (int i = 0; i < 4; i++) { - neighbor.emplace_back(m_world, m_chunk_pos + CHUNK_DIR[i], true); - } - for (auto& chunk : neighbor) { - chunk.gen_phase_one(); - chunk.gen_phase_three(); - chunk.gen_phase_five(); - chunk.gen_phase_seven(); - } - gen_phase_one(); - gen_phase_three(); - gen_phase_five(); - - OptionalBlockVectorArray neightbor_blocks; - for (int i = 0; i < 4; i++) { - neightbor_blocks[i] = neighbor[i].get_chunk_blocks(); - } - gen_phase_six(neightbor_blocks); - gen_phase_seven(); - for (int i = 0; i < 4; i++) { - neightbor_blocks[i] = neighbor[i].get_chunk_blocks(); - } - gen_vertex_data(neightbor_blocks); - - // collect chunk info for debugging - m_info.biome = m_biome; - m_info.pos = m_chunk_pos; - m_info.seed = m_seed; - Random r(m_seed); - unsigned first = r.engine()(); - m_info.first_random = first; - r.init(m_seed); - m_info.has_cave_start = r.random_bool(DEFAULT_CAVE_PROBABILITY); - m_info.has_cave = m_has_cave; -} -// Logger::info("Cross Sum {}", m_cross_vertices_sum.load()); - -bool Chunk::is_temp_chunk() const { return m_temp_chunk.load(); } - -bool& Chunk::has_cave() { return m_has_cave; } - -} // namespace Cubed diff --git a/src/gameplay/pre_remove_player.cpp b/src/gameplay/pre_remove_player.cpp deleted file mode 100644 index 62587ef..0000000 --- a/src/gameplay/pre_remove_player.cpp +++ /dev/null @@ -1,544 +0,0 @@ -#include "Cubed/config.hpp" -#include "Cubed/debug_collector.hpp" -#include "Cubed/gameplay/player.hpp" -#include "Cubed/gameplay/world.hpp" -#include "Cubed/tools/log.hpp" - -#include - -namespace Cubed { - -Player::Player(World& world, const std::string& name) - : m_name(name), m_world(world) { - hot_reload(); -} -Player::~Player() {} - -AABB Player::get_aabb() const { - float half_width = m_size.x / 2.0f; - float half_depth = m_size.z / 2.0f; - - glm::vec3 min{m_player_pos.x - half_width, m_player_pos.y, - m_player_pos.z - half_depth}; - - glm::vec3 max{m_player_pos.x + half_width, m_player_pos.y + m_size.y, - m_player_pos.z + half_depth}; - - return AABB{min, max}; -} - -const glm::vec3& Player::get_front() const { return m_front; } - -const Gait& Player::get_gait() const { return m_gait; } - -const std::optional& Player::get_look_block_pos() const { - return m_look_block; -} - -const glm::vec3& Player::get_player_pos() const { return m_player_pos; } - -const MoveState& Player::get_move_state() const { return m_move_state; } - -bool Player::ray_cast(const glm::vec3& start, const glm::vec3& front, - glm::ivec3& block_pos, glm::vec3& normal, - float distance) { - glm::vec3 dir = glm::normalize(front); - // float step = 0.1f; - glm::ivec3 cur = glm::floor(start); - int ix = cur.x; - int iy = cur.y; - int iz = cur.z; - // step direction - int step_x = (dir.x > 0) ? 1 : ((dir.x < 0) ? -1 : 0); - int step_y = (dir.y > 0) ? 1 : ((dir.y < 0) ? -1 : 0); - int step_z = (dir.z > 0) ? 1 : ((dir.z < 0) ? -1 : 0); - - static const float INF = std::numeric_limits::infinity(); - - float t_delta_x = (dir.x != 0) ? std::fabs(1.0f / dir.x) : INF; - float t_delta_y = (dir.y != 0) ? std::fabs(1.0f / dir.y) : INF; - float t_delta_z = (dir.z != 0) ? std::fabs(1.0f / dir.z) : INF; - - float t_max_x, t_max_y, t_max_z; - - if (dir.x > 0) { - t_max_x = (static_cast(ix) + 1.0f - start.x) / dir.x; - } else if (dir.x < 0) { - t_max_x = (start.x - static_cast(ix)) / (-dir.x); - } else { - t_max_x = INF; - } - - if (dir.y > 0) { - t_max_y = (static_cast(iy) + 1.0f - start.y) / dir.y; - } else if (dir.y < 0) { - t_max_y = (start.y - static_cast(iy)) / (-dir.y); - } else { - t_max_y = INF; - } - - if (dir.z > 0) { - t_max_z = (static_cast(iz) + 1.0f - start.z) / dir.z; - } else if (dir.z < 0) { - t_max_z = (start.z - static_cast(iz)) / (-dir.z); - } else { - t_max_z = INF; - } - float t = 0.0f; - normal = glm::vec3(0.0f, 0.0f, 0.0f); - while (t <= distance) { - if (m_world.is_solid(glm::ivec3(ix, iy, iz))) { - block_pos = glm::ivec3(ix, iy, iz); - return true; - } - - if (t_max_x < t_max_y && t_max_x < t_max_z) { - t = t_max_x; - t_max_x += t_delta_x; - normal = glm::vec3(-step_x, 0.0f, 0.0f); - ix += step_x; - } else if (t_max_y < t_max_z) { - t = t_max_y; - t_max_y += t_delta_y; - normal = glm::vec3(0.0f, -step_y, 0.0f); - iy += step_y; - } else { - t = t_max_z; - t_max_z += t_delta_z; - normal = glm::vec3(0.0f, 0.0f, -step_z); - iz += step_z; - } - } - return false; -} - -void Player::change_mode(GameMode mode) { - m_game_mode = mode; - Logger::info("Change GameMode to {}", to_str(mode)); - if (mode == CREATIVE) { - is_fly = false; - m_gait = Gait::WALK; - } else if (mode == SPECTATOR) { - is_fly = true; - m_gait = Gait::RUN; - m_max_speed = m_max_run_speed; - } -} - -void Player::hot_reload() { - auto& config = Config::get(); - m_sensitivity = - static_cast(config.get("player.mouse_sensitivity")); -} - -void Player::set_player_pos(const glm::vec3& pos) { m_player_pos = pos; } - -void Player::set_place_block(unsigned id) { m_place_block = id; } - -void Player::update(float delta_time) { - - update_move(delta_time); - update_lookup_block(); - check_player_chunk_transition(); - - DebugCollector::get().report("player_pos", - std::format("x: {:.2f} y: {:.2f} z: {:.2f}", - m_player_pos.x, m_player_pos.y, - m_player_pos.z)); - - DebugCollector::get().report("speed", - std::format("Speed: {:.2} m/s", m_xz_speed)); -} - -void Player::update_player_move_state(int key, int action) { - switch (key) { - case GLFW_KEY_W: - if (action == GLFW_PRESS) { - m_move_state.forward = true; - } - if (action == GLFW_RELEASE) { - m_move_state.forward = false; - if (m_game_mode != SPECTATOR) { - m_gait = Gait::WALK; - } - } - break; - case GLFW_KEY_S: - if (action == GLFW_PRESS) { - m_move_state.back = true; - } - if (action == GLFW_RELEASE) { - m_move_state.back = false; - } - break; - case GLFW_KEY_A: - if (action == GLFW_PRESS) { - m_move_state.left = true; - } - if (action == GLFW_RELEASE) { - m_move_state.left = false; - } - break; - case GLFW_KEY_D: - if (action == GLFW_PRESS) { - m_move_state.right = true; - } - if (action == GLFW_RELEASE) { - m_move_state.right = false; - } - break; - case GLFW_KEY_SPACE: - if (action == GLFW_PRESS) { - m_move_state.up = true; - if (space_on) { - if (m_game_mode == CREATIVE) { - is_fly = !is_fly ? true : false; - m_y_speed = 0.0f; - } - space_on = false; - space_on_time = 0.0f; - } else { - space_on = true; - } - } - if (action == GLFW_RELEASE) { - m_move_state.up = false; - } - break; - case GLFW_KEY_LEFT_SHIFT: - if (action == GLFW_PRESS) { - m_move_state.down = true; - } - if (action == GLFW_RELEASE) { - m_move_state.down = false; - } - break; - case GLFW_KEY_LEFT_CONTROL: - if (action == GLFW_PRESS) { - m_gait = Gait::RUN; - } - break; - case GLFW_KEY_F4: - if (action == GLFW_PRESS) { - if (m_game_mode == CREATIVE) { - change_mode(SPECTATOR); - } else { - change_mode(CREATIVE); - } - } - break; - } -} - -void Player::update_front_vec(float offset_x, float offset_y) { - m_yaw += offset_x * m_sensitivity; - m_pitch += offset_y * m_sensitivity; - - m_yaw = std::fmod(m_yaw, 360.0); - - m_pitch = std::clamp(m_pitch, -89.0f, 89.0f); - - m_front.x = sin(glm::radians(m_yaw)) * cos(glm::radians(m_pitch)); - m_front.y = sin(glm::radians(m_pitch)); - m_front.z = -cos(glm::radians(m_yaw)) * cos(glm::radians(m_pitch)); - - m_front = glm::normalize(m_front); -} - -void Player::check_player_chunk_transition() { - ChunkPos cur_pos = m_world.get_chunk_pos(m_player_pos.x, m_player_pos.z); - if (cur_pos != m_player_chunk_pos) { - m_world.need_gen(); - m_player_chunk_pos = cur_pos; - } -} - -void Player::update_direction() { - m_right = glm::normalize(glm::cross(m_front, glm::vec3(0.0f, 1.0f, 0.0f))); - - glm::vec3 move_dir_front = glm::vec3(0.0f); - glm::vec3 move_dir_right = glm::vec3(0.0f); - glm::vec3 move_dir = glm::vec3(0.0f); - if (m_move_state.forward) { - move_dir_front += glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)); - } - if (m_move_state.back) { - move_dir_front -= glm::normalize(glm::vec3(m_front.x, 0.0f, m_front.z)); - } - if (m_move_state.left) { - move_dir_right -= glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)); - } - if (m_move_state.right) { - move_dir_right += glm::normalize(glm::vec3(m_right.x, 0.0f, m_right.z)); - } - move_dir = move_dir_front + move_dir_right; - - if (glm::length(move_dir) > 0.001f) { - direction = glm::normalize(move_dir); - } -} - -void Player::update_lookup_block() { - // calculate the block that is looked - glm::ivec3 block_pos; - glm::vec3 block_normal; - if (ray_cast( - glm::vec3(m_player_pos.x, (m_player_pos.y + 1.6f), m_player_pos.z), - m_front, block_pos, block_normal)) { - m_look_block = LookBlock{block_pos, glm::floor(block_normal)}; - } else { - m_look_block = std::nullopt; - } - - if (m_look_block != std::nullopt) { - if (Input::get_input_state().mouse_state.left) { - if (m_world.is_solid(m_look_block->pos)) { - m_world.set_block(m_look_block->pos, 0); - } - Input::get_input_state().mouse_state.left = false; - } - if (Input::get_input_state().mouse_state.right) { - glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal; - if (!m_world.is_solid(near_pos)) { - auto x = near_pos.x; - auto y = near_pos.y; - auto z = near_pos.z; - AABB block_box = {glm::vec3{static_cast(x), - static_cast(y), - static_cast(z)}, - glm::vec3{static_cast(x + 1), - static_cast(y + 1), - static_cast(z + 1)}}; - AABB player_box = get_aabb(); - if (!player_box.intersects(block_box)) { - m_world.set_block(near_pos, m_place_block); - } - } - Input::get_input_state().mouse_state.right = false; - } - } -} - -void Player::update_move(float delta_time) { - // if frame rate less than 1 frame per second, don't update - if (delta_time > 1.0f) { - return; - } - if (m_game_mode != SPECTATOR) { - if (m_gait == Gait::RUN) { - m_max_speed = m_max_run_speed; - } - if (m_gait == Gait::WALK) { - m_max_speed = m_max_walk_speed; - } - } - - if (space_on) { - space_on_time += delta_time; - if (space_on_time >= MAX_SPACE_ON_TIME) { - space_on = false; - space_on_time = 0.0f; - } - } - - // calculate speed - if (m_move_state.forward || m_move_state.back || m_move_state.left || - m_move_state.right || m_move_state.up) { - direction = glm::vec3(0.0f, 0.0f, 0.0f); - m_xz_speed += m_acceleration * delta_time; - if (m_xz_speed > m_max_speed) { - m_xz_speed = m_max_speed; - } - } else { - m_xz_speed += -m_deceleration * delta_time; - if (m_xz_speed < 0) { - m_xz_speed = 0; - direction = glm::vec3(0.0f, 0.0f, 0.0f); - } - } - - update_direction(); - - move_distance = {direction.x * m_xz_speed * delta_time, 0.0f, - direction.z * m_xz_speed * delta_time}; - - if (is_fly) { - if (m_move_state.up) { - m_y_speed = m_fly_y_speed; - } - - if (m_move_state.down) { - m_y_speed = -m_fly_y_speed; - } - - if (!m_move_state.down && !m_move_state.up) { - m_y_speed = 0.0f; - } - } else { - if (m_move_state.up && can_up) { - m_y_speed = 7.5; - can_up = false; - } - - m_y_speed += -m_g * delta_time; - } - - move_distance.y = m_y_speed * delta_time; - // y - update_y_move(); - // x - update_x_move(); - - update_z_move(); - - if (m_player_pos.y < -15.0f) { - Logger::warn("y is tow low"); - m_player_pos += glm::vec3(1.0f, 100.0f, 1.0f); - } -} - -void Player::update_x_move() { - m_player_pos.x += move_distance.x; - if (m_game_mode == SPECTATOR) { - return; - } - AABB player_box = get_aabb(); - int minx = std::floor(player_box.min.x); - int maxx = std::floor(player_box.max.x); - int miny = std::floor(player_box.min.y); - int maxy = std::floor(player_box.max.y); - int minz = std::floor(player_box.min.z); - int maxz = std::floor(player_box.max.z); - - for (int x = minx; x <= maxx; ++x) { - for (int y = miny; y <= maxy; ++y) { - for (int z = minz; z <= maxz; ++z) { - if (!m_world.can_pass_block(glm::ivec3{x, y, z})) { - AABB block_box = {glm::vec3{static_cast(x), - static_cast(y), - static_cast(z)}, - glm::vec3{static_cast(x + 1), - static_cast(y + 1), - static_cast(z + 1)}}; - if (player_box.intersects(block_box)) { - m_gait = Gait::WALK; - m_player_pos.x -= move_distance.x; - return; - } - } - } - } - } -} - -void Player::update_y_move() { - m_player_pos.y += move_distance.y; - if (m_game_mode == SPECTATOR) { - return; - } - AABB player_box = get_aabb(); - int minx = std::floor(player_box.min.x); - int maxx = std::floor(player_box.max.x); - int miny = std::floor(player_box.min.y); - int maxy = std::floor(player_box.max.y); - int minz = std::floor(player_box.min.z); - int maxz = std::floor(player_box.max.z); - - for (int x = minx; x <= maxx; ++x) { - for (int y = miny; y <= maxy; ++y) { - for (int z = minz; z <= maxz; ++z) { - if (!m_world.can_pass_block(glm::ivec3{x, y, z})) { - AABB block_box = {glm::vec3{static_cast(x), - static_cast(y), - static_cast(z)}, - glm::vec3{static_cast(x + 1), - static_cast(y + 1), - static_cast(z + 1)}}; - if (player_box.intersects(block_box)) { - m_player_pos.y -= move_distance.y; - m_y_speed = 0.0f; - if (move_distance.y < 0) { - can_up = true; - is_fly = false; - } - return; - } - } - } - } - } -} - -void Player::update_z_move() { - m_player_pos.z += move_distance.z; - if (m_game_mode == SPECTATOR) { - return; - } - AABB player_box = get_aabb(); - int minx = std::floor(player_box.min.x); - int maxx = std::floor(player_box.max.x); - int miny = std::floor(player_box.min.y); - int maxy = std::floor(player_box.max.y); - int minz = std::floor(player_box.min.z); - int maxz = std::floor(player_box.max.z); - - for (int x = minx; x <= maxx; ++x) { - for (int y = miny; y <= maxy; ++y) { - for (int z = minz; z <= maxz; ++z) { - if (!m_world.can_pass_block(glm::ivec3{x, y, z})) { - AABB block_box = {glm::vec3{static_cast(x), - static_cast(y), - static_cast(z)}, - glm::vec3{static_cast(x + 1), - static_cast(y + 1), - static_cast(z + 1)}}; - if (player_box.intersects(block_box)) { - m_gait = Gait::WALK; - m_player_pos.z -= move_distance.z; - return; - } - } - } - } - } -} - -void Player::update_scroll(double yoffset) { - if (m_game_mode == SPECTATOR) { - if (yoffset > 0) { - if (m_max_speed < 500.0f) { - m_max_speed += 1.0f; - } - } else { - if (m_max_speed > 1.0f) { - m_max_speed -= 1.0f; - } - } - } - if (m_game_mode == CREATIVE) { - if (yoffset < 0) { - m_place_block += 1; - if (m_place_block >= BlockManager::sums()) { - m_place_block = 1; - } - } else { - m_place_block -= 1; - if (m_place_block <= 0) { - m_place_block = BlockManager::sums() - 1; - } - } - } -} - -float& Player::max_walk_speed() { return m_max_walk_speed; } -float& Player::max_run_speed() { return m_max_run_speed; } -float& Player::max_speed() { return m_max_speed; } -float& Player::acceleration() { return m_acceleration; } -float& Player::deceleration() { return m_deceleration; } -float& Player::g() { return m_g; } -float& Player::fly_y_speed() { return m_fly_y_speed; } -unsigned Player::place_block() const { return m_place_block; }; -Gait& Player::gait() { return m_gait; } -GameMode& Player::game_mode() { return m_game_mode; } -const World& Player::get_world() const { return m_world; } -} // namespace Cubed diff --git a/src/gameplay/pre_remove_world.cpp b/src/gameplay/pre_remove_world.cpp deleted file mode 100644 index 499b32e..0000000 --- a/src/gameplay/pre_remove_world.cpp +++ /dev/null @@ -1,702 +0,0 @@ -#include "Cubed/config.hpp" -#include "Cubed/gameplay/player.hpp" -#include "Cubed/gameplay/world.hpp" -#include "Cubed/tools/cubed_assert.hpp" -#include "Cubed/tools/cubed_hash.hpp" - -#include -#include -#include -using namespace std::chrono; -using namespace std::chrono_literals; - -namespace Cubed { - -struct ChunkRenderData { - std::array*, 4> neighbor_block; - Chunk* chunk; -}; - -World::World() {} - -World::~World() { - stop_gen_thread(); - stop_server_thread(); - wait_all_chunk_tasks(); - stop_thread_pool(); - - m_chunks.clear(); - { - std::lock_guard lk(m_delete_vbo_mutex); - for (auto x : m_pending_delete_vbo) { - glDeleteBuffers(1, &x); - } - m_pending_delete_vbo.clear(); - } - { - std::lock_guard lk(m_delete_vao_mutex); - for (auto x : m_pending_delete_vao) { - glDeleteVertexArrays(1, &x); - } - m_pending_delete_vao.clear(); - } -} - -void World::wait_all_chunk_tasks() { - for (auto& [pos, task] : new_chunks) { - task.future.get(); - } -} - -bool World::can_move(const AABB& player_box) const { return true; } - -const std::optional& -World::get_look_block_pos(const std::string& name) const { - static std::optional null_look_block = std::nullopt; - auto it = m_players.find(HASH::str(name)); - if (it == m_players.end()) { - Logger::error("Can't find player {}", name); - ASSERT(0); - return null_look_block; - } - - return it->second.get_look_block_pos(); -} -/* -const Chunk* World::get_chunk(const ChunkPos& pos) const { - std::lock_guard lk(m_chunks_mutex); - auto it = m_chunks.find(pos); - if (it == m_chunks.end()) { - return nullptr; - } - return &it->second; -}*/ - -Player& World::get_player(const std::string& name) { - auto it = m_players.find(HASH::str(name)); - if (it == m_players.end()) { - Logger::error("Can't find player {}", name); - ASSERT(0); - } - - return it->second; -} - -void World::init_world() { - m_cave_carcer.init(ChunkGenerator::seed()); - m_river_worm.init(ChunkGenerator::seed()); - m_chunks.reserve(MAX_DISTANCE * MAX_DISTANCE * 4); - start_thread_pool(); - - auto t1 = std::chrono::system_clock::now(); - - // init players - m_players.emplace(HASH::str("TestPlayer"), Player(*this, "TestPlayer")); - - start_gen_thread(); - init_chunks(); - auto t2 = std::chrono::system_clock::now(); - auto d = std::chrono::duration_cast(t2 - t1); - Logger::info("Chunk Block Init Finish, Time Consuming: {}", d); - - start_server_thread(); - - Logger::info("TestPlayer Create Finish"); -} -void World::init_chunks() { - hot_reload(); - while (!m_chunk_gen_finished) { - // Logger::info("World Spawn: {:.2f}%", m_chunk_gen_fraction.load()); - std::this_thread::sleep_for(std::chrono::microseconds(200)); - } -} - -ChunkPos World::get_chunk_pos(int world_x, int world_z) { - int chunk_x, chunk_z; - if (world_x < 0) { - chunk_x = (world_x + 1) / CHUNK_SIZE - 1; - } - if (world_x >= 0) { - chunk_x = world_x / CHUNK_SIZE; - } - if (world_z < 0) { - chunk_z = (world_z + 1) / CHUNK_SIZE - 1; - } - if (world_z >= 0) { - chunk_z = world_z / CHUNK_SIZE; - } - return {chunk_x, chunk_z}; -} - -#pragma region ChunkGenerate - -void World::gen_chunks_internal() { - // Logger::info("gen_chunks_internal"); - m_chunk_gen_finished = false; - - ChunkPosSet required_chunks; - compute_required_chunks(required_chunks); - - ASSERT_MSG(!required_chunks.empty(), "required chunks is empty!!"); - - std::vector need_gen_chunks_pos; - - sync_and_collect_missing_chunks(need_gen_chunks_pos, required_chunks); - - Logger::info("New Gen Chunks Sum: {}", need_gen_chunks_pos.size()); - - if (need_gen_chunks_pos.empty()) { - m_could_gen = true; - - return; - } - - for (auto& pos : need_gen_chunks_pos) { - new_chunks.emplace(pos, Chunk(*this, pos)); - } - - submit_new_chunks(); - m_chunk_gen_finished = true; -} - -void World::sync_player_pos(glm::vec3& player_pos) { - std::lock_guard lk(m_gen_player_pos_mutex); - player_pos = m_gen_player_pos; -} - -void World::compute_required_chunks(ChunkPosSet& required_chunks) { - glm::vec3 player_pos; - sync_player_pos(player_pos); - - int x = std::floor(player_pos.x); - int z = std::floor(player_pos.z); - auto [chunk_x, chunk_z] = get_chunk_pos(x, z); - int radius = m_rendering_distance; - int r2 = radius * radius; - required_chunks.reserve(radius * radius); - - for (int dx = -radius; dx <= radius; ++dx) { - for (int dz = -radius; dz <= radius; ++dz) { - if (dx * dx + dz * dz <= r2) { - required_chunks.emplace(chunk_x + dx, chunk_z + dz); - } - } - } -} - -void World::sync_and_collect_missing_chunks( - std::vector& need_gen_chunks_pos, - const ChunkPosSet& required_chunks) { - std::lock_guard lk(m_chunks_mutex); - for (auto it = m_chunks.begin(); it != m_chunks.end();) { - if (required_chunks.find(it->first) == required_chunks.end()) { - it = m_chunks.erase(it); - } else { - ++it; - } - } - - for (auto pos : required_chunks) { - auto it = m_chunks.find(pos); - if (it == m_chunks.end()) { - need_gen_chunks_pos.push_back(pos); - } - } -} - -void World::submit_new_chunks() { - using enum ChunkLoadStyle; - std::lock_guard lock(m_new_chunk_mutex); - auto pool_ptr = m_gen_thread_pool.load(); - if (!pool_ptr) { - return; - } - switch (m_chunk_load_style) { - case RANDOM: - for (auto& [pos, task] : new_chunks) { - if (!task.future.valid()) { - task.future = - pool_ptr->enqueue([&task]() { task.chunk.gen_chunk(); }); - } - } - break; - case CENTER: { - std::vector> tasks; - for (auto& [pos, task] : new_chunks) { - if (!task.future.valid()) { - tasks.emplace_back(pos, &task); - } - } - glm::vec3 player_pos; - sync_player_pos(player_pos); - auto dist2 = [player_pos](ChunkPos chunk_pos) { - ChunkPos player_chunk_pos = - get_chunk_pos(player_pos.x, player_pos.z); - float dx = player_chunk_pos.x - chunk_pos.x; - float dz = player_chunk_pos.z - chunk_pos.z; - return dx * dx + dz * dz; - }; - - std::sort(tasks.begin(), tasks.end(), - [&dist2](const auto& a, const auto& b) { - return dist2(a.first) < dist2(b.first); - }); - for (auto& [pos, task] : tasks) { - if (!task->future.valid()) { - task->future = - pool_ptr->enqueue([task]() { task->chunk.gen_chunk(); }); - } - } - } - } -} - -void World::poll_finished_chunks() { - m_new_finished_chunk.clear(); - std::lock_guard lock(m_new_chunk_mutex); - std::erase_if( - new_chunks, [&](std::pair& pair) { - auto& pending = pair.second; - if (!pending.future.valid()) { - return false; - } - if (pending.future.wait_for(0ms) != std::future_status::ready) { - return false; - } - pending.future.get(); - - m_new_finished_chunk.emplace_back(pair.first, - std::move(pending.chunk)); - return true; - }); -} - -#pragma endregion - -void World::start_gen_thread() { - m_gen_running = true; - Logger::info("Gen Thread Started"); - m_gen_thread = std::thread([this]() { - while (m_gen_running) { - std::unique_lock lk(m_gen_signal_mutex); - - m_gen_cv.wait(lk, [this]() { - return m_need_gen_chunk.load() || !m_gen_running; - }); - if (!m_gen_running) { - break; - } - m_need_gen_chunk = false; - lk.unlock(); - - gen_chunks_internal(); - } - }); -} - -void World::start_server_thread() { - m_server_thread = std::thread( - [this]() { serever_run(m_server_stop_source.get_token()); }); -} - -void World::stop_gen_thread() { - m_gen_running = false; - m_gen_cv.notify_all(); - if (m_gen_thread.joinable()) { - m_gen_thread.join(); - } - Logger::info("Gen Thread Stopped"); -} - -void World::stop_server_thread() { - m_server_stop_source.request_stop(); - if (m_server_thread.joinable()) { - m_server_thread.join(); - } -} - -void World::stop_thread_pool() { - auto pool_ptr = m_gen_thread_pool.load(); - if (pool_ptr) { - pool_ptr->stop(); - } - m_gen_thread_pool.store(nullptr); - Logger::info("Thread Pool Stopped"); -} - -void World::start_thread_pool() { - int max_thread = std::thread::hardware_concurrency(); - if (m_pool_threads == 0) { - change_pool_threads(max_thread - RESERVED_THREADS); - } else { - change_pool_threads(m_pool_threads); - } -} - -void World::serever_run(std::stop_token stoken) { - Logger::info("Server Thread Started!"); - while (!stoken.stop_requested()) { - std::this_thread::sleep_for(milliseconds(m_per_tick_time)); - if (m_tick_running) { - ++m_game_ticks; - m_day_tick = (m_day_tick + 1) % DAY_TIME; - } - } - Logger::info("Server Thread Stopped!"); -} - -void World::need_gen() { - - if (!m_could_gen) { - Logger::warn("It is generating or consuming new chunks"); - return; - } - - m_could_gen = false; - { - std::lock_guard lk(m_gen_player_pos_mutex); - m_gen_player_pos = get_player("TestPlayer").get_player_pos(); - } - - m_need_gen_chunk = true; - - m_gen_cv.notify_one(); -} - -int World::get_block(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); - std::shared_lock lk(m_chunks_mutex); - auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); - - if (it == m_chunks.end()) { - return 0; - } - - const auto& chunk_blocks = it->second.get_chunk_blocks(); - auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z}); - if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - return 0; - } - return chunk_blocks[Chunk::index(x, y, z)]; -} - -bool World::is_solid(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); - std::shared_lock lk(m_chunks_mutex); - auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); - - if (it == m_chunks.end()) { - return false; - } - const auto& chunk_blocks = it->second.get_chunk_blocks(); - auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z}); - if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - return false; - } - auto id = chunk_blocks[Chunk::index(x, y, z)]; - if (BlockManager::is_gas(id) || BlockManager::is_liquid(id)) { - return false; - } else { - return true; - } -} - -bool World::can_pass_block(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); - std::shared_lock lk(m_chunks_mutex); - auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); - - if (it == m_chunks.end()) { - return true; - } - const auto& chunk_blocks = it->second.get_chunk_blocks(); - auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z}); - if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - return true; - } - auto id = chunk_blocks[Chunk::index(x, y, z)]; - return BlockManager::is_passable(id); -} - -BlockType World::get_block_tpye(const glm::ivec3& block_pos) const { - auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); - std::shared_lock lk(m_chunks_mutex); - auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); - - if (it == m_chunks.end()) { - // Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y, - // block_pos.z); - return 0; - } - const auto& chunk_blocks = it->second.get_chunk_blocks(); - auto [x, y, z] = Chunk::world_to_block(block_pos, {chunk_x, chunk_z}); - if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - // Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y, - // block_pos.z); - return 0; - } - return chunk_blocks[Chunk::index(x, y, z)]; -} - -void World::set_block(const glm::ivec3& block_pos, unsigned id) { - - int world_x, world_y, world_z; - world_x = block_pos.x; - world_y = block_pos.y; - world_z = block_pos.z; - - auto [chunk_x, chunk_z] = get_chunk_pos(world_x, world_z); - std::lock_guard lk(m_chunks_mutex); - auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z}); - - if (it == m_chunks.end()) { - return; - } - - auto [x, y, z] = - Chunk::world_to_block(world_x, world_y, world_z, chunk_x, chunk_z); - if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y || - z >= CHUNK_SIZE) { - return; - } - - it->second.set_chunk_block(Chunk::index(x, y, z), id); - - static const glm::ivec3 NEIGHBOR_DIRS[] = { - {1, 0, 0}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 1}}; - - for (const auto& dir : NEIGHBOR_DIRS) { - glm::ivec3 neighbor = block_pos + dir; - - auto [cx, cz] = get_chunk_pos(neighbor.x, neighbor.z); - auto it = m_chunks.find({cx, cz}); - if (it != m_chunks.end()) { - it->second.mark_dirty(); - } - } -} - -void World::update(float delta_time) { - for (auto& player : m_players) { - player.second.update(delta_time); - } - { - std::lock_guard lk(m_delete_vbo_mutex); - for (auto x : m_pending_delete_vbo) { - glDeleteBuffers(1, &x); - } - m_pending_delete_vbo.clear(); - } - - { - std::lock_guard lk(m_delete_vao_mutex); - for (auto x : m_pending_delete_vao) { - glDeleteVertexArrays(1, &x); - } - m_pending_delete_vao.clear(); - } - - poll_finished_chunks(); - - for (auto& x : m_new_finished_chunk) { - x.second.upload_to_gpu(); - } - - // unified compute vertex data before rendering - { - std::lock_guard lk(m_chunks_mutex); - bool consumed = false; - - for (auto& x : m_new_finished_chunk) { - m_chunks.insert_or_assign(x.first, std::move(x.second)); - consumed = true; - } - if (consumed) { - m_could_gen = true; - } - - m_render_snapshots.clear(); - for (auto& [pos, chunk] : m_chunks) { - if (chunk.is_dirty()) { - // the curial fator influence - OptionalBlockVectorArray neighbor_block; - for (int i = 0; i < 4; i++) { - auto it = m_chunks.find(pos + CHUNK_DIR[i]); - if (it != m_chunks.end()) { - neighbor_block[i] = (it->second.get_chunk_blocks()); - } else { - neighbor_block[i] = std::nullopt; - } - } - chunk.gen_vertex_data(neighbor_block); - chunk.upload_to_gpu(); - } - if (!chunk.is_dirty()) { - if (chunk.is_need_upload()) { - chunk.upload_to_gpu(); - } - m_render_snapshots.push_back( - {chunk.get_normal_vao(), chunk.get_normal_vertices_sum(), - chunk.get_cross_vao(), chunk.get_cross_vertices_sum(), - chunk.get_normal_discard_vao(), - chunk.get_normal_discard_vertices_sum(), - chunk.get_normal_blend_vao(), - chunk.get_normal_blend_vertices_sum(), - chunk.get_water_vao(), chunk.get_water_vertices_sum(), - glm::vec3(static_cast(pos.x * CHUNK_SIZE) + - static_cast(CHUNK_SIZE / 2), - static_cast(WORLD_SIZE_Y / 2), - static_cast(pos.z * CHUNK_SIZE) + - static_cast(CHUNK_SIZE / 2)), - glm::vec3(static_cast(CHUNK_SIZE / 2), - static_cast(WORLD_SIZE_Y / 2), - static_cast(CHUNK_SIZE / 2))}); - } - } - } -} - -void World::push_delete_vbo(GLuint vbo) { - std::lock_guard lk(m_delete_vbo_mutex); - m_pending_delete_vbo.push_back(vbo); -} - -void World::push_delete_vao(GLuint vao) { - std::lock_guard lk(m_delete_vao_mutex); - m_pending_delete_vao.push_back(vao); -} - -void World::hot_reload() { - auto& config = Config::get(); - int dist = config.get("world.rendering_distance"); - m_rendering_distance = dist <= MAX_DISTANCE ? dist : MAX_DISTANCE; - need_gen(); -} - -void World::rebuild_world() { - if (m_is_rebuilding) { - return; - } - m_is_rebuilding = true; - stop_gen_thread(); - stop_thread_pool(); - m_cave_carcer.reload(ChunkGenerator::seed()); - m_river_worm.reload(ChunkGenerator::seed()); - { - std::lock_guard lk(m_chunks_mutex); - m_chunks.clear(); - m_new_finished_chunk.clear(); - } - m_could_gen = true; - ChunkGenerator::reload(); - start_thread_pool(); - start_gen_thread(); - need_gen(); - - m_is_rebuilding = false; -} - -/* -glm::vec3 World::sunlight_dir() const { - float t = static_cast(m_day_tick) / DAY_TIME; - - float azimuth = glm::radians(90.0f - t * 360.0f); - - float altitude = - glm::half_pi() * sin((t - 0.25f) * glm::two_pi()); - - glm::vec3 dir{cos(altitude) * cos(azimuth), sin(altitude), - cos(altitude) * sin(azimuth)}; - - return glm::normalize(-dir); -} -*/ - -glm::vec3 World::sunlight_dir() const { - float altitude = sin((m_day_tick - 6 * PER_HOUR) / - static_cast(DAY_TIME / 2) * std::numbers::pi) * - 90.0f; - - float t = static_cast(m_day_tick) / DAY_TIME; - float azimuth = 90.0f - 360.0f * (t - 0.25f); - - float alt = glm::radians(altitude); - float az = glm::radians(azimuth); - glm::vec3 dir; - dir.x = cos(alt) * sin(az); - dir.y = sin(alt); - dir.z = cos(alt) * cos(az); - - return glm::normalize(-dir); -} - -int World::rendering_distance() const { return m_rendering_distance.load(); } - -void World::rendering_distance(int rendering_distance) { - m_rendering_distance = rendering_distance; -} - -CaveCarver& World::cave_carcer() { return m_cave_carcer; } -RiverWorm& World::river_worm() { return m_river_worm; } -std::vector& World::planes() { return m_planes; } -std::vector& World::render_snapshots() { - return m_render_snapshots; -}; - -TickType World::game_tick() const { return m_game_ticks.load(); } -TickType World::day_tick() const { return m_day_tick.load(); } -void World::day_tick(TickType tick) { - tick %= DAY_TIME; - m_day_tick = tick; -} -int World::per_tick_time() const { return m_per_tick_time.load(); } -void World::per_tick_time(int ms) { m_per_tick_time = ms; } - -bool World::is_tick_running() const { return m_tick_running.load(); } -void World::tick_running(bool run) { m_tick_running = run; } -int World::pool_threads() const { return m_pool_threads.load(); } -int World::max_threads() const { return m_max_threads.load(); } -void World::change_pool_threads(int threads) { - m_max_threads = std::thread::hardware_concurrency(); - if (m_max_threads < 1) { - Logger::warn("Can't Get Max Support Threads, Set Max Threads to 4"); - m_max_threads = 4; - } - int used_thread = std::clamp(threads, 1, m_max_threads.load()); - Logger::info("Create New Thread Pool Use {} Threads", used_thread); - m_gen_thread_pool.store(std::make_shared(used_thread)); - m_pool_threads = used_thread; -} -int World::chunk_load_style() const { - return std::to_underlying(m_chunk_load_style.load()); -} -void World::set_chunk_load_style(int id) { - using enum ChunkLoadStyle; - - switch (id) { - case std::to_underlying(RANDOM): - m_chunk_load_style = RANDOM; - return; - case std::to_underlying(CENTER): - m_chunk_load_style = CENTER; - return; - } - Logger::error("Can,t Find Chunk Load Style Id {}, Nothing Will Do", id); -} - -ChunkInfo World::get_chunk_info(const glm::vec3& world_pos) const { - ChunkPos pos = get_chunk_pos(world_pos.x, world_pos.z); - - std::shared_lock lock(m_chunks_mutex); - auto it = m_chunks.find(pos); - if (it == m_chunks.end()) { - return ChunkInfo{}; - } - return it->second.get_info(); -} - -} // namespace Cubed \ No newline at end of file