diff --git a/include/Cubed/gameplay/chunk.hpp b/include/Cubed/gameplay/chunk.hpp new file mode 100644 index 0000000..f2ef335 --- /dev/null +++ b/include/Cubed/gameplay/chunk.hpp @@ -0,0 +1,27 @@ +#pragma once +#include "Cubed/gameplay/chunk_pos.hpp" + +#include +#include +namespace Cubed { +class Chunk { +public: + Chunk() = default; + Chunk(const Chunk&) = delete; + Chunk(Chunk&&) = delete; + Chunk& operator=(const Chunk&) = delete; + Chunk& operator=(Chunk&&) = delete; + virtual ~Chunk() = default; + static int index(int x, int y, int z); + static int index(const glm::vec3& pos); + 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); +}; +} // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/client_chunk.hpp b/include/Cubed/gameplay/client_chunk.hpp index a4fe258..52a2952 100644 --- a/include/Cubed/gameplay/client_chunk.hpp +++ b/include/Cubed/gameplay/client_chunk.hpp @@ -2,6 +2,7 @@ #include "Cubed/constants.hpp" #include "Cubed/gameplay/biome.hpp" #include "Cubed/gameplay/block.hpp" +#include "Cubed/gameplay/chunk.hpp" #include "Cubed/gameplay/chunk_pos.hpp" #include "Cubed/gameplay/vertex_data.hpp" #include "world/chunk_data.pb.h" @@ -26,7 +27,7 @@ struct ChunkRenderSnapshot { glm::vec3 center; glm::vec3 half_extents; }; -class ClientChunk { +class ClientChunk : public Chunk { public: ClientChunk(ClientWorld& world); ~ClientChunk(); @@ -35,17 +36,6 @@ public: ClientChunk(ClientChunk&&) noexcept; ClientChunk& operator=(ClientChunk&&) noexcept; - static int index(int x, int y, int z); - static int index(const glm::vec3& pos); - 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; diff --git a/include/Cubed/gameplay/client_world.hpp b/include/Cubed/gameplay/client_world.hpp index 1b6f4f3..525d171 100644 --- a/include/Cubed/gameplay/client_world.hpp +++ b/include/Cubed/gameplay/client_world.hpp @@ -8,6 +8,7 @@ #include "Cubed/gameplay/client_player.hpp" #include "Cubed/gameplay/game_time.hpp" #include "Cubed/gameplay/network_client.hpp" +#include "Cubed/gameplay/world.hpp" #include "Cubed/input/event.hpp" #include "Cubed/tools/cubed_random.hpp" #include "Cubed/tools/priority_thread_pool.hpp" @@ -30,7 +31,7 @@ struct PlayerRenderData { float angle; }; class WorldScene; -class ClientWorld { +class ClientWorld : public World { public: ClientWorld(const ClientWorld&) = delete; ClientWorld(ClientWorld&&) = delete; @@ -46,10 +47,10 @@ public: const std::optional& get_look_block_pos() const; ClientPlayer& get_player(); const ClientPlayer& get_player() const; - 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; + int get_block(const glm::ivec3& block_pos) const override; + bool is_solid(const glm::ivec3& block_pos) const override; + bool can_pass_block(const glm::ivec3& block_pos) const override; + BlockType get_block_tpye(const glm::ivec3& block_pos) const override; void rebuild_world(); diff --git a/include/Cubed/gameplay/server_chunk.hpp b/include/Cubed/gameplay/server_chunk.hpp index 8fa7075..9eb9a9a 100644 --- a/include/Cubed/gameplay/server_chunk.hpp +++ b/include/Cubed/gameplay/server_chunk.hpp @@ -2,6 +2,7 @@ #include "Cubed/constants.hpp" #include "Cubed/gameplay/biome.hpp" #include "Cubed/gameplay/block.hpp" +#include "Cubed/gameplay/chunk.hpp" #include "Cubed/gameplay/chunk_generator.hpp" #include "Cubed/gameplay/chunk_pos.hpp" @@ -11,7 +12,7 @@ #include namespace Cubed { class ServerWorld; -class ServerChunk { +class ServerChunk : public Chunk { public: ServerChunk(ServerWorld& world, ChunkPos chunk_pos, bool temp_chunk = false); diff --git a/include/Cubed/gameplay/server_world.hpp b/include/Cubed/gameplay/server_world.hpp index 8502570..bb1ac41 100644 --- a/include/Cubed/gameplay/server_world.hpp +++ b/include/Cubed/gameplay/server_world.hpp @@ -8,6 +8,7 @@ #include "Cubed/gameplay/river_worm.hpp" #include "Cubed/gameplay/server_chunk.hpp" #include "Cubed/gameplay/server_player.hpp" +#include "Cubed/gameplay/world.hpp" #include "Cubed/tools/priority_thread_pool.hpp" #include "Cubed/tools/recent_queue.hpp" #include "Cubed/tools/sensitive_filter.hpp" @@ -25,7 +26,7 @@ #include namespace Cubed { class Session; -class ServerWorld { +class ServerWorld : public World { public: enum class ThreadPoolKind { NET, GEN }; ServerWorld(Config& config); @@ -85,6 +86,12 @@ public: void handle_chat_message(ChatMsg& msg); void handle_voice_message(VoiceMsg& msg); int chunk_size() const; + + int get_block(const glm::ivec3& block_pos) const override; + bool is_solid(const glm::ivec3& block_pos) const override; + bool can_pass_block(const glm::ivec3& block_pos) const override; + BlockType get_block_tpye(const glm::ivec3& block_pos) const override; + template void register_timer(std::string_view id, TickType threshold, Fn&& f) { m_timers.emplace(std::piecewise_construct, @@ -119,7 +126,7 @@ private: using PlayerUUIDMap = tbb::concurrent_hash_map; using chunk_acc = ChunkHashMap::accessor; - using chunk_caac = ChunkHashMap::const_accessor; + using chunk_cacc = ChunkHashMap::const_accessor; using uuid_acc = PlayerUUIDMap::accessor; using uuid_cacc = PlayerUUIDMap::const_accessor; diff --git a/include/Cubed/gameplay/world.hpp b/include/Cubed/gameplay/world.hpp new file mode 100644 index 0000000..84dc4df --- /dev/null +++ b/include/Cubed/gameplay/world.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "Cubed/gameplay/block.hpp" + +#include +namespace Cubed { +class World { +public: + World() = default; + World(const World&) = delete; + World(World&&) = delete; + World& operator=(const World&) = delete; + World& operator=(World&&) = delete; + virtual ~World() = default; + + virtual int get_block(const glm::ivec3& block_pos) const = 0; + virtual bool is_solid(const glm::ivec3& block_pos) const = 0; + virtual bool can_pass_block(const glm::ivec3& block_pos) const = 0; + virtual BlockType get_block_tpye(const glm::ivec3& block_pos) const = 0; +}; +} // namespace Cubed \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 589c8be..a6ea590 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,4 +95,5 @@ target_sources(${PROJECT_NAME} tools/model_loader.cpp render/model_manager.cpp render/model_renderer.cpp + gameplay/chunk.cpp ) \ No newline at end of file diff --git a/src/gameplay/chunk.cpp b/src/gameplay/chunk.cpp new file mode 100644 index 0000000..723b9e1 --- /dev/null +++ b/src/gameplay/chunk.cpp @@ -0,0 +1,49 @@ +#include "Cubed/gameplay/chunk.hpp" + +#include "Cubed/tools/cubed_assert.hpp" + +namespace Cubed { +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); +} +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); +} +} // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/client_chunk.cpp b/src/gameplay/client_chunk.cpp index 11e1b1c..96de15c 100644 --- a/src/gameplay/client_chunk.cpp +++ b/src/gameplay/client_chunk.cpp @@ -1,7 +1,5 @@ #include "Cubed/gameplay/client_chunk.hpp" -#include "Cubed/tools/cubed_assert.hpp" - namespace Cubed { using OptionalBlockVectorArray = std::array>, 4>; @@ -128,49 +126,6 @@ ClientChunk& ClientChunk::operator=(ClientChunk&& other) noexcept { return *this; } -int ClientChunk::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 ClientChunk::index(const glm::vec3& pos) { - return ClientChunk::index(pos.x, pos.y, pos.z); -} -std::tuple ClientChunk::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 -ClientChunk::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 -ClientChunk::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 -ClientChunk::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 ClientChunk::get_biome() const { return m_biome.load(); } ChunkPos ClientChunk::get_chunk_pos() const { return m_chunk_pos; } diff --git a/src/gameplay/client_world.cpp b/src/gameplay/client_world.cpp index ca2ecd1..4ab4078 100644 --- a/src/gameplay/client_world.cpp +++ b/src/gameplay/client_world.cpp @@ -136,7 +136,6 @@ void ClientWorld::rebuild_world() { BlockType ClientWorld::get_block_tpye(const glm::ivec3& block_pos) const { auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); chunk_cacc cacc; - ; if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) { // Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y, @@ -737,6 +736,7 @@ AABB ClientWorld::get_block_aabb(const glm::ivec3& pos) { static_cast(pos.z) + 0.5f}, glm::vec3{0.5f, 0.5f, 0.5f}}; } + AudioEngine& ClientWorld::get_audio() { return m_audio; } const AudioEngine& ClientWorld::get_audio() const { return m_audio; } Config& ClientWorld::get_config() { return m_config; } diff --git a/src/gameplay/server_world.cpp b/src/gameplay/server_world.cpp index f1ca893..ff9f55c 100644 --- a/src/gameplay/server_world.cpp +++ b/src/gameplay/server_world.cpp @@ -113,7 +113,7 @@ void ServerWorld::send_chunk(int task_id, const std::string& uuid, rsq_pos->set_x(pos.x); rsq_pos->set_z(pos.z); { - chunk_caac cacc; + chunk_cacc cacc; if (!m_chunks.find(cacc, pos)) { // No chunk found and not generating Logger::error("Chunk {} {} neither pending nor ready", pos.x, @@ -990,4 +990,88 @@ void ServerWorld::set_chunk_load_style(int id) { int ServerWorld::chunk_size() const { return m_chunks.size(); } +int ServerWorld::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; + + if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) { + return 0; + } + if (cacc->second.state != ChunkState::READY) { + return 0; + } + const auto& chunk_blocks = cacc->second.chunk->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 ServerWorld::is_solid(const glm::ivec3& block_pos) const { + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); + chunk_cacc cacc; + + if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) { + return false; + } + if (cacc->second.state != ChunkState::READY) { + return 0; + } + const auto& chunk_blocks = cacc->second.chunk->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 ServerWorld::can_pass_block(const glm::ivec3& block_pos) const { + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); + chunk_cacc cacc; + + if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) { + return true; + } + if (cacc->second.state != ChunkState::READY) { + return 0; + } + const auto& chunk_blocks = cacc->second.chunk->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 ServerWorld::get_block_tpye(const glm::ivec3& block_pos) const { + auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z); + chunk_cacc cacc; + + if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) { + // Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y, + // block_pos.z); + return 0; + } + if (cacc->second.state != ChunkState::READY) { + return 0; + } + const auto& chunk_blocks = cacc->second.chunk->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)]; +} + } // namespace Cubed \ No newline at end of file