fix: correct neighbor block indexing and add time update support

This commit is contained in:
2026-06-25 21:37:19 +08:00
parent 47552a1887
commit db10d30dc2
9 changed files with 80 additions and 60 deletions

View File

@@ -80,7 +80,7 @@ DesertParams& desert_params();
MountainParams& mountain_params(); MountainParams& mountain_params();
RiverParams& river_params(); RiverParams& river_params();
inline BiomeType get_biome(int id) { inline BiomeType get_biome_from_id(int id) {
using enum BiomeType; using enum BiomeType;
auto to = std::to_underlying<BiomeType>; auto to = std::to_underlying<BiomeType>;
if (id == to(PLAIN)) { if (id == to(PLAIN)) {

View File

@@ -16,7 +16,7 @@ class ClientPlayer {
public: public:
ClientPlayer(ClientWorld& world); ClientPlayer(ClientWorld& world);
~ClientPlayer(); ~ClientPlayer();
AABB get_aabb() const; AABB get_aabb(const glm::vec3& pos) const;
const glm::vec3& get_front() const; const glm::vec3& get_front() const;
const Gait& get_gait() const; const Gait& get_gait() const;
const std::optional<LookBlock>& get_look_block_pos() const; const std::optional<LookBlock>& get_look_block_pos() const;

View File

@@ -96,7 +96,11 @@ inline int choose_buf(BlockType id) {
} }
} // namespace } // namespace
ClientChunk::ClientChunk(ClientWorld& world) : m_world(world) {} ClientChunk::ClientChunk(ClientWorld& world) : m_world(world) {
for (int i = 0; i < VERTEX_DATA_SUM; i++) {
m_vertex_data.emplace_back(m_world);
}
}
ClientChunk::~ClientChunk() {} ClientChunk::~ClientChunk() {}
ClientChunk::ClientChunk(ClientChunk&& other) noexcept ClientChunk::ClientChunk(ClientChunk&& other) noexcept
@@ -110,7 +114,9 @@ ClientChunk& ClientChunk::operator=(ClientChunk&& other) noexcept {
// Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&& // Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&&
// other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z, // other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z,
// static_cast<const void*>(&other)); // static_cast<const void*>(&other));
if (this == &other) {
return *this;
}
m_chunk_pos = std::move(other.m_chunk_pos); m_chunk_pos = std::move(other.m_chunk_pos);
m_blocks = std::move(other.m_blocks); m_blocks = std::move(other.m_blocks);
m_dirty = other.is_dirty(); m_dirty = other.is_dirty();
@@ -498,6 +504,11 @@ void ClientChunk::gen_cross_plane_vertices(int world_x, int world_y,
void ClientChunk::receive_chunk(const ChunkDataRsp& data) { void ClientChunk::receive_chunk(const ChunkDataRsp& data) {
OptionalBlockVectorArray neighbor; OptionalBlockVectorArray neighbor;
m_chunk_pos.x = data.pos().x();
m_chunk_pos.z = data.pos().z();
m_seed = data.chunk_seed();
m_biome = get_biome_from_id(data.biome_type());
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
neighbor[i] = std::nullopt; neighbor[i] = std::nullopt;
} }
@@ -506,41 +517,28 @@ void ClientChunk::receive_chunk(const ChunkDataRsp& data) {
Logger::error("Bad Chunk, size {}", data.chunk_blocks_size()); Logger::error("Bad Chunk, size {}", data.chunk_blocks_size());
return; return;
} }
m_blocks.reserve(BLOCK_SIZE); m_blocks.reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) { for (const auto& b : data.chunk_blocks()) {
m_blocks.push_back(static_cast<BlockType>(b)); m_blocks.push_back(static_cast<BlockType>(b));
} }
// temp neighbor block data // temp neighbor block data
if (data.neighbor_blocks_1_size() == BLOCK_SIZE) { auto load_neighbor = [&](int idx, const auto& blocks) {
neighbor[0] = std::vector<BlockType>(); if (blocks.size() != BLOCK_SIZE)
neighbor[0]->reserve(BLOCK_SIZE); return;
for (const auto& b : data.chunk_blocks()) {
neighbor[0]->push_back(static_cast<BlockType>(b)); neighbor[idx].emplace();
} neighbor[idx]->reserve(BLOCK_SIZE);
}
if (data.neighbor_blocks_2_size() == BLOCK_SIZE) { for (auto b : blocks) {
neighbor[1] = std::vector<BlockType>(); neighbor[idx]->push_back(static_cast<BlockType>(b));
neighbor[1]->reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) {
neighbor[1]->push_back(static_cast<BlockType>(b));
}
}
if (data.neighbor_blocks_3_size() == BLOCK_SIZE) {
neighbor[2] = std::vector<BlockType>();
neighbor[2]->reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) {
neighbor[2]->push_back(static_cast<BlockType>(b));
}
}
if (data.neighbor_blocks_3_size() == BLOCK_SIZE) {
neighbor[3] = std::vector<BlockType>();
neighbor[3]->reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) {
neighbor[3]->push_back(static_cast<BlockType>(b));
}
} }
};
load_neighbor(0, data.neighbor_blocks_1());
load_neighbor(1, data.neighbor_blocks_2());
load_neighbor(2, data.neighbor_blocks_3());
load_neighbor(3, data.neighbor_blocks_4());
gen_vertex_data(neighbor); gen_vertex_data(neighbor);
mark_dirty(); mark_dirty();

View File

@@ -8,15 +8,13 @@ namespace Cubed {
ClientPlayer::ClientPlayer(ClientWorld& world) : m_world(world) {} ClientPlayer::ClientPlayer(ClientWorld& world) : m_world(world) {}
ClientPlayer::~ClientPlayer() {} ClientPlayer::~ClientPlayer() {}
AABB ClientPlayer::get_aabb() const { AABB ClientPlayer::get_aabb(const glm::vec3& pos) const {
float half_width = m_size.x / 2.0f; float half_width = m_size.x / 2.0f;
float half_depth = m_size.z / 2.0f; float half_depth = m_size.z / 2.0f;
glm::vec3 min{m_player_pos.x - half_width, m_player_pos.y, glm::vec3 min{pos.x - half_width, pos.y, pos.z - half_depth};
m_player_pos.z - half_depth};
glm::vec3 max{m_player_pos.x + half_width, m_player_pos.y + m_size.y, glm::vec3 max{pos.x + half_width, pos.y + m_size.y, pos.z + half_depth};
m_player_pos.z + half_depth};
return AABB{min, max}; return AABB{min, max};
} }
@@ -293,7 +291,7 @@ void ClientPlayer::update_lookup_block() {
glm::vec3{static_cast<float>(x + 1), glm::vec3{static_cast<float>(x + 1),
static_cast<float>(y + 1), static_cast<float>(y + 1),
static_cast<float>(z + 1)}}; static_cast<float>(z + 1)}};
AABB player_box = get_aabb(); AABB player_box = get_aabb(get_player_pos());
if (!player_box.intersects(block_box)) { if (!player_box.intersects(block_box)) {
m_world.report_block_change(near_pos, m_place_block); m_world.report_block_change(near_pos, m_place_block);
} }
@@ -394,12 +392,12 @@ void ClientPlayer::update_move(float delta_time) {
} }
} }
void ClientPlayer::update_x_move(glm::vec3& m_player_pos) { void ClientPlayer::update_x_move(glm::vec3& player_pos) {
m_player_pos.x += move_distance.x; player_pos.x += move_distance.x;
if (m_game_mode == SPECTATOR) { if (m_game_mode == SPECTATOR) {
return; return;
} }
AABB player_box = get_aabb(); AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
int miny = std::floor(player_box.min.y); int miny = std::floor(player_box.min.y);
@@ -419,7 +417,7 @@ void ClientPlayer::update_x_move(glm::vec3& m_player_pos) {
static_cast<float>(z + 1)}}; static_cast<float>(z + 1)}};
if (player_box.intersects(block_box)) { if (player_box.intersects(block_box)) {
m_gait = Gait::WALK; m_gait = Gait::WALK;
m_player_pos.x -= move_distance.x; player_pos.x -= move_distance.x;
return; return;
} }
} }
@@ -428,12 +426,12 @@ void ClientPlayer::update_x_move(glm::vec3& m_player_pos) {
} }
} }
void ClientPlayer::update_y_move(glm::vec3& m_player_pos) { void ClientPlayer::update_y_move(glm::vec3& player_pos) {
m_player_pos.y += move_distance.y; player_pos.y += move_distance.y;
if (m_game_mode == SPECTATOR) { if (m_game_mode == SPECTATOR) {
return; return;
} }
AABB player_box = get_aabb(); AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
int miny = std::floor(player_box.min.y); int miny = std::floor(player_box.min.y);
@@ -452,7 +450,7 @@ void ClientPlayer::update_y_move(glm::vec3& m_player_pos) {
static_cast<float>(y + 1), static_cast<float>(y + 1),
static_cast<float>(z + 1)}}; static_cast<float>(z + 1)}};
if (player_box.intersects(block_box)) { if (player_box.intersects(block_box)) {
m_player_pos.y -= move_distance.y; player_pos.y -= move_distance.y;
m_y_speed = 0.0f; m_y_speed = 0.0f;
if (move_distance.y < 0) { if (move_distance.y < 0) {
can_up = true; can_up = true;
@@ -466,12 +464,12 @@ void ClientPlayer::update_y_move(glm::vec3& m_player_pos) {
} }
} }
void ClientPlayer::update_z_move(glm::vec3& m_player_pos) { void ClientPlayer::update_z_move(glm::vec3& player_pos) {
m_player_pos.z += move_distance.z; player_pos.z += move_distance.z;
if (m_game_mode == SPECTATOR) { if (m_game_mode == SPECTATOR) {
return; return;
} }
AABB player_box = get_aabb(); AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x); int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x); int maxx = std::floor(player_box.max.x);
int miny = std::floor(player_box.min.y); int miny = std::floor(player_box.min.y);
@@ -491,7 +489,7 @@ void ClientPlayer::update_z_move(glm::vec3& m_player_pos) {
static_cast<float>(z + 1)}}; static_cast<float>(z + 1)}};
if (player_box.intersects(block_box)) { if (player_box.intersects(block_box)) {
m_gait = Gait::WALK; m_gait = Gait::WALK;
m_player_pos.z -= move_distance.z; player_pos.z -= move_distance.z;
return; return;
} }
} }

View File

@@ -197,7 +197,7 @@ void ClientWorld::init(std::string_view player_name,
m_client = client; m_client = client;
// timer // timer
register_timer("player_pos", 2, [this]() { report_player_pos(); }); register_timer("player_pos", 2, [this]() { report_player_pos(); });
// register_timer("chunk_request", 20, [this]() { request_chunk(); });
LoginReq req; LoginReq req;
req.set_name(m_player.get_name()); req.set_name(m_player.get_name());
while (!client->is_connected()) { while (!client->is_connected()) {
@@ -219,6 +219,7 @@ void ClientWorld::start_client_thread(std::string_view uuid) {
m_game_running = true; m_game_running = true;
client_run(token); client_run(token);
}); });
request_chunk();
} }
void ClientWorld::stop_client_thread() { void ClientWorld::stop_client_thread() {
@@ -317,6 +318,7 @@ void ClientWorld::receive_chunk(const ChunkDataRsp& data) {
{ {
std::lock_guard lock(m_pending_queue_mutex); std::lock_guard lock(m_pending_queue_mutex);
m_pending_queue.emplace_back(std::move(chunk)); m_pending_queue.emplace_back(std::move(chunk));
Logger::info("ClientWorld Add a new pending chunk");
} }
} }
@@ -341,8 +343,10 @@ void ClientWorld::update(float delta_time) {
{ {
std::lock_guard lock(m_pending_queue_mutex); std::lock_guard lock(m_pending_queue_mutex);
for (auto& c : m_pending_queue) { for (auto& c : m_pending_queue) {
// Logger::info("{} {}", c.get_chunk_pos().x, c.get_chunk_pos().z);
new_chunks.emplace_back(std::move(c)); new_chunks.emplace_back(std::move(c));
} }
m_pending_queue.clear();
} }
for (auto& c : new_chunks) { for (auto& c : new_chunks) {
c.upload_to_gpu(); c.upload_to_gpu();

View File

@@ -64,11 +64,12 @@ asio::awaitable<void> NetworkClient::read_loop() {
co_await asio::async_read(m_socket, asio::buffer(body_data), co_await asio::async_read(m_socket, asio::buffer(body_data),
asio::use_awaitable); asio::use_awaitable);
} }
Logger::info("Client: Receive cmd {}", cmd_id);
constexpr auto& to_num = std::to_underlying<PacketEnum>; constexpr auto& to_num = std::to_underlying<PacketEnum>;
switch (cmd_id) { switch (cmd_id) {
case to_num(PacketEnum::LOGIN_RSP): { case to_num(PacketEnum::LOGIN_RSP): {
LoginRsp rsp; LoginRsp rsp;
Logger::info("Client: Receive Login rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) { if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
if (rsp.success()) { if (rsp.success()) {
m_world.start_client_thread(rsp.uuid()); m_world.start_client_thread(rsp.uuid());
@@ -79,16 +80,24 @@ asio::awaitable<void> NetworkClient::read_loop() {
} break; } break;
case to_num(PacketEnum::CHUNK_DATA_RSP): { case to_num(PacketEnum::CHUNK_DATA_RSP): {
ChunkDataRsp rsp; ChunkDataRsp rsp;
Logger::info("Client: Receive Chunk Data rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) { if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
m_world.receive_chunk(rsp); m_world.receive_chunk(rsp);
} }
} break; } break;
case to_num(PacketEnum::BLOCK_CHANGE_RSP): { case to_num(PacketEnum::BLOCK_CHANGE_RSP): {
BlockChangeRsp rsp; BlockChangeRsp rsp;
Logger::info("Client: Receive Block Change rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) { if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
m_world.receive_block_change(rsp); m_world.receive_block_change(rsp);
} }
} break; } break;
case to_num(PacketEnum::UPDATE_TIME): {
UpdateTime rsp;
if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
m_world.receive_time(rsp);
}
}
} }
} }
} catch (const asio::system_error& e) { } catch (const asio::system_error& e) {

View File

@@ -8,21 +8,29 @@ ServerChunk::ServerChunk(ServerWorld& world, ChunkPos chunk_pos,
: m_temp_chunk(temp_chunk), m_chunk_pos(chunk_pos), m_world(world) {} : m_temp_chunk(temp_chunk), m_chunk_pos(chunk_pos), m_world(world) {}
ServerChunk::ServerChunk(ServerChunk&& other) noexcept ServerChunk::ServerChunk(ServerChunk&& other) noexcept
: m_biome(other.m_biome.load()), m_chunk_pos(std::move(other.m_chunk_pos)), : m_gening(other.m_gening.load()), m_has_cave(other.m_has_cave),
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_world(other.m_world), m_heightmap(std::move(other.m_heightmap)),
m_blocks(std::move(other.m_blocks)), m_seed(other.m_seed), m_blocks(std::move(other.m_blocks)),
m_conditions(other.m_conditions) {} m_neightbor_blocks(std::move(other.m_neightbor_blocks)),
m_seed(other.m_seed), m_conditions(other.m_conditions) {}
ServerChunk& ServerChunk::operator=(ServerChunk&& other) noexcept { ServerChunk& ServerChunk::operator=(ServerChunk&& other) noexcept {
// Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&& // Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&&
// other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z, // other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z,
// static_cast<const void*>(&other)); // static_cast<const void*>(&other));
if (this == &other) {
return *this;
}
m_chunk_pos = std::move(other.m_chunk_pos); m_chunk_pos = std::move(other.m_chunk_pos);
m_heightmap = std::move(other.m_heightmap); m_heightmap = std::move(other.m_heightmap);
m_blocks = std::move(other.m_blocks); m_blocks = std::move(other.m_blocks);
m_biome = other.m_biome.load(); m_biome = other.m_biome.load();
m_seed = other.m_seed; m_seed = other.m_seed;
m_conditions = other.m_conditions; m_conditions = other.m_conditions;
m_neightbor_blocks = std::move(other.m_neightbor_blocks);
m_has_cave = other.m_has_cave;
m_gening = other.m_gening.load();
return *this; return *this;
} }

View File

@@ -477,10 +477,10 @@ void ServerWorld::handle_chunk_req(const std::string& uuid, ChunkPos pos) {
auto* nb2 = rsq.mutable_neighbor_blocks_2(); auto* nb2 = rsq.mutable_neighbor_blocks_2();
auto* nb3 = rsq.mutable_neighbor_blocks_3(); auto* nb3 = rsq.mutable_neighbor_blocks_3();
auto* nb4 = rsq.mutable_neighbor_blocks_4(); auto* nb4 = rsq.mutable_neighbor_blocks_4();
assign(nb1, neighbor_blocks[1]); assign(nb1, neighbor_blocks[0]);
assign(nb2, neighbor_blocks[2]); assign(nb2, neighbor_blocks[1]);
assign(nb3, neighbor_blocks[3]); assign(nb3, neighbor_blocks[2]);
assign(nb4, neighbor_blocks[4]); assign(nb4, neighbor_blocks[3]);
} }
std::shared_ptr<Session> s; std::shared_ptr<Session> s;
{ {
@@ -494,6 +494,7 @@ void ServerWorld::handle_chunk_req(const std::string& uuid, ChunkPos pos) {
Logger::error("Player {} session not exist", uuid); Logger::error("Player {} session not exist", uuid);
return; return;
} }
s->send(make_packet(rsq)); s->send(make_packet(rsq));
} }

View File

@@ -58,10 +58,10 @@ asio::awaitable<void> Session::read_loop() {
co_await asio::async_read(m_socket, asio::buffer(body_data), co_await asio::async_read(m_socket, asio::buffer(body_data),
asio::use_awaitable); asio::use_awaitable);
} }
Logger::info("Session: Receive cmd {}", cmd_id);
constexpr auto& to_num = std::to_underlying<PacketEnum>; constexpr auto& to_num = std::to_underlying<PacketEnum>;
if (cmd_id == to_num(PacketEnum::LOGIN_REQ)) { if (cmd_id == to_num(PacketEnum::LOGIN_REQ)) {
LoginReq req; LoginReq req;
Logger::info("Session: Receive Login req");
if (req.ParseFromArray(body_data.data(), body_data.size())) { if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_player_login(req.name(), m_server_world.handle_player_login(req.name(),
shared_from_this()); shared_from_this());
@@ -77,6 +77,7 @@ asio::awaitable<void> Session::read_loop() {
} }
if (cmd_id == to_num(PacketEnum::CHUNK_DATA_REQ)) { if (cmd_id == to_num(PacketEnum::CHUNK_DATA_REQ)) {
ChunkDataReq req; ChunkDataReq req;
Logger::info("Session: Receive Chunk Data req");
if (req.ParseFromArray(body_data.data(), body_data.size())) { if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_chunk_req( m_server_world.handle_chunk_req(
req.uuid(), ChunkPos(req.pos().x(), req.pos().z())); req.uuid(), ChunkPos(req.pos().x(), req.pos().z()));
@@ -84,6 +85,7 @@ asio::awaitable<void> Session::read_loop() {
} }
if (cmd_id == to_num(PacketEnum::BLOCK_CHANGE_REQ)) { if (cmd_id == to_num(PacketEnum::BLOCK_CHANGE_REQ)) {
BlockChangeReq req; BlockChangeReq req;
Logger::info("Session: Receive Block Change req");
if (req.ParseFromArray(body_data.data(), body_data.size())) { if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_block_change(req); m_server_world.handle_block_change(req);
} }