From 107c6a7382b0b1fa28869ce3ded4d622576ecc2a Mon Sep 17 00:00:00 2001 From: Ritchie Cunningham Date: Wed, 17 Sep 2025 20:07:02 +0100 Subject: [PATCH] [Add] Dynamic world chunk loading. --- srv/game/game.h | 4 +++- srv/game/game_chunk_management.cpp | 22 ++++++++++++++++++++++ srv/game/game_send_chunks.cpp | 8 ++++---- srv/game/player.cpp | 4 +++- srv/game/player.h | 7 +++++++ srv/main.cpp | 5 +++-- 6 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 srv/game/game_chunk_management.cpp diff --git a/srv/game/game.h b/srv/game/game.h index 0c5340e..0c88a00 100644 --- a/srv/game/game.h +++ b/srv/game/game.h @@ -12,7 +12,7 @@ public: Player* add_player(BettolaLib::Network::TCPSocket* socket); void remove_player(unsigned int player_id); - void send_initial_chunks(Player* player); + void update_player_chunks(void); void process_udp_message(const char* buffer, size_t size, const sockaddr_in& from_addr); void broadcast_game_state(BettolaLib::Network::UDPSocket& udp_socket); @@ -21,6 +21,8 @@ public: Player* get_player_by_id(unsigned int id); private: + void _send_chunks_around(Player* player, int chunk_x, int chunk_z); + std::vector _players; World _world; }; diff --git a/srv/game/game_chunk_management.cpp b/srv/game/game_chunk_management.cpp new file mode 100644 index 0000000..e34125e --- /dev/null +++ b/srv/game/game_chunk_management.cpp @@ -0,0 +1,22 @@ +#include +#include "game.h" +#include "bettola/game/chunk.h" + +void Game::update_player_chunks(void) { + const int chunk_width = BettolaLib::Game::CHUNK_WIDTH - 1; + const int chunk_height = BettolaLib::Game::CHUNK_HEIGHT - 1; + + for(Player* player : _players) { + const auto& pos = player->get_position(); + + /* Calculate player's current chunk coords. */ + int chunk_x = floor(pos.x / chunk_width); + int chunk_z = floor(pos.z / chunk_height); + + /* If they have moved into a new chunk, send them the new surrounding chunks. */ + if(chunk_z != player->get_chunk_x() || chunk_z != player->get_chunk_z()) { + player->set_chunk_pos(chunk_x, chunk_z); + _send_chunks_around(player, chunk_x, chunk_z); + } + } +} diff --git a/srv/game/game_send_chunks.cpp b/srv/game/game_send_chunks.cpp index bee1e47..8ddf370 100644 --- a/srv/game/game_send_chunks.cpp +++ b/srv/game/game_send_chunks.cpp @@ -5,14 +5,14 @@ #include "bettola/network/message.h" #include "player.h" -void Game::send_initial_chunks(Player* player) { +void Game::_send_chunks_around(Player* player, int center_x, int center_z) { BettolaLib::Network::MessageHeader header; header.type = BettolaLib::Network::MessageType::ChunkData; header.size = sizeof(BettolaLib::Network::ChunkMessage); - /* Send a 3x3 grid of chunks around the origin. */ - for(int x = -1; x <=1; ++x) { - for(int z = -1; z <= 1; ++z) { + /* Send a 3x3 grid of chunks around the player's current chunk. */ + for(int x = center_x; x <= center_x+1; ++x) { + for(int z = center_z-1; z <= center_z+1; ++z) { BettolaLib::Game::Chunk& chunk = _world.get_chunk(x, z); BettolaLib::Network::ChunkMessage msg; diff --git a/srv/game/player.cpp b/srv/game/player.cpp index d0f9f3f..b914f9d 100644 --- a/srv/game/player.cpp +++ b/srv/game/player.cpp @@ -8,7 +8,9 @@ Player::Player(BettolaLib::Network::TCPSocket* socket) : PlayerBase(), _socket(socket), - _has_udp_addr(false) { + _has_udp_addr(false), + _chunk_x(INT_MAX), + _chunk_z(INT_MAX) { _last_processed_sequence = 0; memset(&_udp_addr, 0, sizeof(_udp_addr)); diff --git a/srv/game/player.h b/srv/game/player.h index d34734f..50d62a3 100644 --- a/srv/game/player.h +++ b/srv/game/player.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "bettola/network/tcpsocket.h" @@ -19,9 +20,15 @@ public: void set_last_processed_sequence(unsigned int sequence) { _last_processed_sequence = sequence; } unsigned int get_last_processed_sequence(void) const { return _last_processed_sequence; } + int get_chunk_x(void) const { return _chunk_x; } + int get_chunk_z(void) const { return _chunk_z; } + void set_chunk_pos(int x, int z) { _chunk_x = x; _chunk_z = z; } + private: BettolaLib::Network::TCPSocket* _socket; sockaddr_in _udp_addr; bool _has_udp_addr; unsigned int _last_processed_sequence; + int _chunk_x; + int _chunk_z; }; diff --git a/srv/main.cpp b/srv/main.cpp index 0b6cc52..8b510af 100644 --- a/srv/main.cpp +++ b/srv/main.cpp @@ -112,8 +112,6 @@ int main(void) { unsigned int id = new_player->get_id(); client_socket->send(&id, sizeof(id)); - game.send_initial_chunks(new_player); - int client_flags = fcntl(client_socket->get_sockfd(), F_GETFL, 0); fcntl(client_socket->get_sockfd(), F_SETFL, client_flags | O_NONBLOCK); @@ -165,6 +163,9 @@ int main(void) { } } + /* Update dynamic game state, like chunk loading for players. */ + game.update_player_chunks(); + /* Broadcase game state. */ game.broadcast_game_state(udp_socket);