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();
RiverParams& river_params();
inline BiomeType get_biome(int id) {
inline BiomeType get_biome_from_id(int id) {
using enum BiomeType;
auto to = std::to_underlying<BiomeType>;
if (id == to(PLAIN)) {

View File

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

View File

@@ -96,7 +96,11 @@ inline int choose_buf(BlockType id) {
}
} // 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&& other) noexcept
@@ -110,7 +114,9 @@ ClientChunk& ClientChunk::operator=(ClientChunk&& 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<const void*>(&other));
if (this == &other) {
return *this;
}
m_chunk_pos = std::move(other.m_chunk_pos);
m_blocks = std::move(other.m_blocks);
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) {
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++) {
neighbor[i] = std::nullopt;
}
@@ -506,41 +517,28 @@ void ClientChunk::receive_chunk(const ChunkDataRsp& data) {
Logger::error("Bad Chunk, size {}", data.chunk_blocks_size());
return;
}
m_blocks.reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) {
m_blocks.push_back(static_cast<BlockType>(b));
}
// temp neighbor block data
if (data.neighbor_blocks_1_size() == BLOCK_SIZE) {
neighbor[0] = std::vector<BlockType>();
neighbor[0]->reserve(BLOCK_SIZE);
for (const auto& b : data.chunk_blocks()) {
neighbor[0]->push_back(static_cast<BlockType>(b));
auto load_neighbor = [&](int idx, const auto& blocks) {
if (blocks.size() != BLOCK_SIZE)
return;
neighbor[idx].emplace();
neighbor[idx]->reserve(BLOCK_SIZE);
for (auto b : blocks) {
neighbor[idx]->push_back(static_cast<BlockType>(b));
}
}
if (data.neighbor_blocks_2_size() == BLOCK_SIZE) {
neighbor[1] = std::vector<BlockType>();
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);
mark_dirty();

View File

@@ -8,15 +8,13 @@ namespace Cubed {
ClientPlayer::ClientPlayer(ClientWorld& world) : m_world(world) {}
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_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 min{pos.x - half_width, pos.y, 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};
glm::vec3 max{pos.x + half_width, pos.y + m_size.y, pos.z + half_depth};
return AABB{min, max};
}
@@ -293,7 +291,7 @@ void ClientPlayer::update_lookup_block() {
glm::vec3{static_cast<float>(x + 1),
static_cast<float>(y + 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)) {
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) {
m_player_pos.x += move_distance.x;
void ClientPlayer::update_x_move(glm::vec3& player_pos) {
player_pos.x += move_distance.x;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb();
AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x);
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)}};
if (player_box.intersects(block_box)) {
m_gait = Gait::WALK;
m_player_pos.x -= move_distance.x;
player_pos.x -= move_distance.x;
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) {
m_player_pos.y += move_distance.y;
void ClientPlayer::update_y_move(glm::vec3& player_pos) {
player_pos.y += move_distance.y;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb();
AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x);
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>(z + 1)}};
if (player_box.intersects(block_box)) {
m_player_pos.y -= move_distance.y;
player_pos.y -= move_distance.y;
m_y_speed = 0.0f;
if (move_distance.y < 0) {
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) {
m_player_pos.z += move_distance.z;
void ClientPlayer::update_z_move(glm::vec3& player_pos) {
player_pos.z += move_distance.z;
if (m_game_mode == SPECTATOR) {
return;
}
AABB player_box = get_aabb();
AABB player_box = get_aabb(player_pos);
int minx = std::floor(player_box.min.x);
int maxx = std::floor(player_box.max.x);
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)}};
if (player_box.intersects(block_box)) {
m_gait = Gait::WALK;
m_player_pos.z -= move_distance.z;
player_pos.z -= move_distance.z;
return;
}
}

View File

@@ -197,7 +197,7 @@ void ClientWorld::init(std::string_view player_name,
m_client = client;
// timer
register_timer("player_pos", 2, [this]() { report_player_pos(); });
// register_timer("chunk_request", 20, [this]() { request_chunk(); });
LoginReq req;
req.set_name(m_player.get_name());
while (!client->is_connected()) {
@@ -219,6 +219,7 @@ void ClientWorld::start_client_thread(std::string_view uuid) {
m_game_running = true;
client_run(token);
});
request_chunk();
}
void ClientWorld::stop_client_thread() {
@@ -317,6 +318,7 @@ void ClientWorld::receive_chunk(const ChunkDataRsp& data) {
{
std::lock_guard lock(m_pending_queue_mutex);
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);
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));
}
m_pending_queue.clear();
}
for (auto& c : new_chunks) {
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),
asio::use_awaitable);
}
Logger::info("Client: Receive cmd {}", cmd_id);
constexpr auto& to_num = std::to_underlying<PacketEnum>;
switch (cmd_id) {
case to_num(PacketEnum::LOGIN_RSP): {
LoginRsp rsp;
Logger::info("Client: Receive Login rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
if (rsp.success()) {
m_world.start_client_thread(rsp.uuid());
@@ -79,16 +80,24 @@ asio::awaitable<void> NetworkClient::read_loop() {
} break;
case to_num(PacketEnum::CHUNK_DATA_RSP): {
ChunkDataRsp rsp;
Logger::info("Client: Receive Chunk Data rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
m_world.receive_chunk(rsp);
}
} break;
case to_num(PacketEnum::BLOCK_CHANGE_RSP): {
BlockChangeRsp rsp;
Logger::info("Client: Receive Block Change rsp");
if (rsp.ParseFromArray(body_data.data(), body_data.size())) {
m_world.receive_block_change(rsp);
}
} 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) {

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) {}
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_blocks(std::move(other.m_blocks)), m_seed(other.m_seed),
m_conditions(other.m_conditions) {}
m_blocks(std::move(other.m_blocks)),
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 {
// Logger::info("other Chunk pos {} {} in Chunk& Chunk::operator=(Chunk&&
// other) this {}", other.m_chunk_pos.x, other.m_chunk_pos.z,
// static_cast<const void*>(&other));
if (this == &other) {
return *this;
}
m_chunk_pos = std::move(other.m_chunk_pos);
m_heightmap = std::move(other.m_heightmap);
m_blocks = std::move(other.m_blocks);
m_biome = other.m_biome.load();
m_seed = other.m_seed;
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;
}

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* nb3 = rsq.mutable_neighbor_blocks_3();
auto* nb4 = rsq.mutable_neighbor_blocks_4();
assign(nb1, neighbor_blocks[1]);
assign(nb2, neighbor_blocks[2]);
assign(nb3, neighbor_blocks[3]);
assign(nb4, neighbor_blocks[4]);
assign(nb1, neighbor_blocks[0]);
assign(nb2, neighbor_blocks[1]);
assign(nb3, neighbor_blocks[2]);
assign(nb4, neighbor_blocks[3]);
}
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);
return;
}
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),
asio::use_awaitable);
}
Logger::info("Session: Receive cmd {}", cmd_id);
constexpr auto& to_num = std::to_underlying<PacketEnum>;
if (cmd_id == to_num(PacketEnum::LOGIN_REQ)) {
LoginReq req;
Logger::info("Session: Receive Login req");
if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_player_login(req.name(),
shared_from_this());
@@ -77,6 +77,7 @@ asio::awaitable<void> Session::read_loop() {
}
if (cmd_id == to_num(PacketEnum::CHUNK_DATA_REQ)) {
ChunkDataReq req;
Logger::info("Session: Receive Chunk Data req");
if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_chunk_req(
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)) {
BlockChangeReq req;
Logger::info("Session: Receive Block Change req");
if (req.ParseFromArray(body_data.data(), body_data.size())) {
m_server_world.handle_block_change(req);
}