Server: Implement support for chunk requests
This commit is contained in:
parent
cfa99d24a0
commit
84d93d21ea
@ -72,6 +72,15 @@ void NetworkPacket::write(uint32_t val) {
|
||||
m_data.push_back(temp[3]);
|
||||
}
|
||||
|
||||
void NetworkPacket::write(int32_t val) {
|
||||
char temp[4];
|
||||
utils::int32_to_bytes(val, temp);
|
||||
m_data.push_back(temp[0]);
|
||||
m_data.push_back(temp[1]);
|
||||
m_data.push_back(temp[2]);
|
||||
m_data.push_back(temp[3]);
|
||||
}
|
||||
|
||||
void NetworkPacket::write(float val) {
|
||||
char temp[4];
|
||||
utils::float_to_bytes(val, temp);
|
||||
@ -146,6 +155,14 @@ bool NetworkPacket::read(uint32_t& output) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkPacket::read(int32_t& output) {
|
||||
if(m_reading_offset+4>m_data.size())
|
||||
return false;
|
||||
output = utils::bytes_to_int32((const char*)&m_data[m_reading_offset]);
|
||||
m_reading_offset+=4;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetworkPacket::read(float& output) {
|
||||
if(m_reading_offset+4>m_data.size())
|
||||
return false;
|
||||
|
@ -47,7 +47,7 @@ namespace polygun::network {
|
||||
// gameplay packets
|
||||
PACKET_ACTION,
|
||||
PACKET_MESSAGE,
|
||||
PACKET_TO_SERVER_CHUNK_REQUEST,
|
||||
PACKET_CHUNK,
|
||||
// node definition packets
|
||||
PACKET_NODE_DEFINITION,
|
||||
// resource packets
|
||||
@ -69,6 +69,7 @@ namespace polygun::network {
|
||||
void write(uint8_t val);
|
||||
void write(uint16_t val);
|
||||
void write(uint32_t val);
|
||||
void write(int32_t val);
|
||||
void write(float val);
|
||||
void write(const std::vector<uint8_t>& val);
|
||||
void write(const std::string& val);
|
||||
@ -78,6 +79,7 @@ namespace polygun::network {
|
||||
bool read(uint8_t& output); // unsigned 8-bit number
|
||||
bool read(uint16_t& output); // unsigned 16-bit number
|
||||
bool read(uint32_t& output); // unsigned 32-bit number
|
||||
bool read(int32_t& output); // signed 32-bit number
|
||||
bool read(float& output); // float
|
||||
bool read(std::vector<uint8_t>& output); // unsigned 8-bit number array
|
||||
bool read(std::string& output); // string
|
||||
|
@ -25,6 +25,7 @@ SOFTWARE.
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "common/network/network_packet.hpp"
|
||||
#include "common/binary_utils.hpp"
|
||||
#include "common/logger.hpp"
|
||||
|
||||
@ -48,7 +49,7 @@ namespace polygun::world {
|
||||
memset(m_chunk_data, 0, sizeof(m_chunk_data));
|
||||
}
|
||||
|
||||
uint8_t Chunk::to_compressed_data(std::vector<uint8_t>& output) {
|
||||
uint8_t Chunk::to_compressed_data(std::vector<uint8_t>& output) const {
|
||||
// Try CHUNK_COMPRESSION_MODE_FILL
|
||||
const uint16_t match = get_node(glm::vec3ub(0, 0, 0));
|
||||
bool fill_success = true;
|
||||
@ -89,7 +90,7 @@ namespace polygun::world {
|
||||
|
||||
// If none succeeded use CHUNK_COMPRESSION_MODE_NONE
|
||||
if(utils::is_little_endian())
|
||||
output.assign(reinterpret_cast<uint8_t*>(m_chunk_data), reinterpret_cast<uint8_t*>(m_chunk_data)+sizeof(m_chunk_data));
|
||||
output.assign(reinterpret_cast<const uint8_t*>(m_chunk_data), reinterpret_cast<const uint8_t*>(m_chunk_data)+sizeof(m_chunk_data));
|
||||
else {
|
||||
output.resize(sizeof(m_chunk_data));
|
||||
for(uint16_t i = 0; i<sizeof(m_chunk_data)/2; i++)
|
||||
@ -140,15 +141,15 @@ namespace polygun::world {
|
||||
m_chunk_data[pos.z*CHUNK_SIZE*CHUNK_SIZE+pos.y*CHUNK_SIZE+pos.x] = node_to_add;
|
||||
}
|
||||
|
||||
bool Chunk::is_air(const glm::vec3ub& pos) {
|
||||
bool Chunk::is_air(const glm::vec3ub& pos) const {
|
||||
return get_node(pos) == 0;
|
||||
}
|
||||
|
||||
uint16_t Chunk::get_node(const glm::vec3ub& pos) {
|
||||
uint16_t Chunk::get_node(const glm::vec3ub& pos) const {
|
||||
return m_chunk_data[pos.z*CHUNK_SIZE*CHUNK_SIZE+pos.y*CHUNK_SIZE+pos.x];
|
||||
}
|
||||
|
||||
bool Chunk::is_neighbour_air(const glm::vec3ub& pos) {
|
||||
bool Chunk::is_neighbour_air(const glm::vec3ub& pos) const {
|
||||
if (pos.x+1 == CHUNK_SIZE) {
|
||||
return true;
|
||||
}
|
||||
@ -189,4 +190,22 @@ namespace polygun::world {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Chunk::serialize(network::NetworkPacket& packet) const {
|
||||
std::vector<uint8_t> compressed_data;
|
||||
const uint8_t compression_mode = to_compressed_data(compressed_data);
|
||||
packet.write(compression_mode);
|
||||
packet.write(compressed_data);
|
||||
}
|
||||
|
||||
bool Chunk::deserialize(network::NetworkPacket& packet) {
|
||||
uint8_t compression_mode;
|
||||
std::vector<uint8_t> compressed_data;
|
||||
if(!packet.read(compression_mode))
|
||||
return false;
|
||||
if(!packet.read(compressed_data))
|
||||
return false;
|
||||
load_from_compressed_data(reinterpret_cast<char*>(compressed_data.data()), compressed_data.size(), compression_mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ SOFTWARE.
|
||||
#ifndef POLYGUN_WORLD_CHUNK_HPP
|
||||
#define POLYGUN_WORLD_CHUNK_HPP
|
||||
|
||||
#include "common/network/network_serializable.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/glm_ext.hpp"
|
||||
@ -35,17 +37,20 @@ namespace polygun::world {
|
||||
CHUNK_COMPRESSION_MODE_FILL
|
||||
};
|
||||
|
||||
class Chunk final {
|
||||
class Chunk final : public network::NetworkSerializable {
|
||||
public:
|
||||
Chunk();
|
||||
~Chunk() = default;
|
||||
|
||||
uint8_t to_compressed_data(std::vector<uint8_t>& output);
|
||||
uint8_t to_compressed_data(std::vector<uint8_t>& output) const;
|
||||
void load_from_compressed_data(const char* data, uint16_t data_size, uint8_t compression_mode);
|
||||
void add_node(uint16_t node_to_add, const glm::vec3ub& pos);
|
||||
bool is_air(const glm::vec3ub& pos);
|
||||
uint16_t get_node(const glm::vec3ub& pos);
|
||||
bool is_neighbour_air(const glm::vec3ub& pos);
|
||||
bool is_air(const glm::vec3ub& pos) const;
|
||||
uint16_t get_node(const glm::vec3ub& pos) const;
|
||||
bool is_neighbour_air(const glm::vec3ub& pos) const;
|
||||
|
||||
virtual void serialize(network::NetworkPacket& packet) const override;
|
||||
virtual bool deserialize(network::NetworkPacket& packet) override;
|
||||
|
||||
static const int CHUNK_SIZE = 32;
|
||||
|
||||
|
@ -34,7 +34,8 @@ Client::Client(std::unique_ptr<polygun::network::NetworkManager> network_manager
|
||||
m_uuid(0),
|
||||
m_pos(),
|
||||
m_join_completed(false),
|
||||
m_last_activity(time(0))
|
||||
m_last_activity(time(0)),
|
||||
m_editmode(false)
|
||||
{
|
||||
m_network_manager = std::move(network_manager);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ namespace polygun::server {
|
||||
uint32_t get_uuid() const { return m_uuid; }
|
||||
bool get_join_completed() const { return m_join_completed; }
|
||||
time_t get_last_activity() const { return m_last_activity; }
|
||||
bool has_editmode() const { return m_editmode; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<polygun::network::NetworkManager> m_network_manager;
|
||||
@ -55,6 +56,7 @@ namespace polygun::server {
|
||||
glm::vec3 m_pos;
|
||||
bool m_join_completed;
|
||||
time_t m_last_activity;
|
||||
bool m_editmode;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ SOFTWARE.
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "common/math/rect3d.hpp"
|
||||
#include "common/logger.hpp"
|
||||
#include "server/command_parser.hpp"
|
||||
|
||||
@ -48,7 +49,8 @@ Server::Server(std::atomic<bool>* running_atomic, std::optional<unsigned short>
|
||||
m_latest_client(),
|
||||
m_server_socket(new polygun::network::UDPSocket),
|
||||
m_command_thread(),
|
||||
m_mod_manager(*this)
|
||||
m_mod_manager(*this),
|
||||
m_chunk_manager(*this)
|
||||
{
|
||||
LOG_INFO("Starting server");
|
||||
m_server_socket->bind(port_override.value_or(m_config.m_port));
|
||||
@ -131,6 +133,8 @@ void Server::run() {
|
||||
m_clients.push_back(std::move(m_latest_client));
|
||||
}
|
||||
}
|
||||
|
||||
m_chunk_manager.update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,6 +205,9 @@ bool Server::handle_packet(polygun::network::NetworkPacket& packet, Client* clie
|
||||
switch(packet.get_id()) {
|
||||
case polygun::network::NetworkPacketID::PACKET_HANDSHAKE:
|
||||
return handle_new_player(packet);
|
||||
case polygun::network::NetworkPacketID::PACKET_CHUNK:
|
||||
handle_chunk_request(packet, client);
|
||||
return true;
|
||||
case polygun::network::NetworkPacketID::PACKET_NODE_DEFINITION:
|
||||
handle_node_definition(packet, client);
|
||||
return true;
|
||||
@ -243,6 +250,32 @@ bool Server::handle_new_player(polygun::network::NetworkPacket& packet) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::handle_chunk_request(polygun::network::NetworkPacket& packet, Client* client) {
|
||||
int32_t chunk_x, chunk_y, chunk_z;
|
||||
packet.read(chunk_x);
|
||||
packet.read(chunk_y);
|
||||
packet.read(chunk_z);
|
||||
|
||||
network::NetworkPacket out_packet = client->get_connection().create_packet(network::NetworkPacketFlag::FLAG_RELIABLE, network::NetworkPacketID::PACKET_CHUNK);
|
||||
out_packet.write(chunk_x);
|
||||
out_packet.write(chunk_y);
|
||||
out_packet.write(chunk_z);
|
||||
|
||||
const math::Rect3D chunk_rect(glm::vec3(chunk_x, chunk_y, chunk_z), glm::vec3(world::Chunk::CHUNK_SIZE));
|
||||
const math::Rect3D player_view_rect = math::Rect3D::with_center(client->get_position(), glm::vec3(5*world::Chunk::CHUNK_SIZE));
|
||||
if(player_view_rect.overlaps(chunk_rect)) {
|
||||
const world::Chunk& chunk = m_chunk_manager.get_chunk(glm::vec3i(chunk_x, chunk_y, chunk_z), client->has_editmode());
|
||||
out_packet.write(&chunk);
|
||||
}
|
||||
else {
|
||||
// Note: Maybe warn player for possible cheating/ddosing server with chunk requests outside of viewing range
|
||||
const world::Chunk dummy_chunk;
|
||||
out_packet.write(&dummy_chunk);
|
||||
}
|
||||
|
||||
client->get_connection().send_packet(out_packet);
|
||||
}
|
||||
|
||||
void Server::handle_node_definition(polygun::network::NetworkPacket& packet, Client* client) {
|
||||
uint16_t node_id;
|
||||
if(!packet.read(node_id)) {
|
||||
|
@ -31,6 +31,7 @@ SOFTWARE.
|
||||
#include <optional>
|
||||
|
||||
#include "server/client.hpp"
|
||||
#include "server/chunk_manager.hpp"
|
||||
#include "server/mod_manager.hpp"
|
||||
#include "server/server_config.hpp"
|
||||
#include "common/world/node_def.hpp"
|
||||
@ -59,12 +60,14 @@ namespace polygun::server {
|
||||
std::unique_ptr<std::thread> m_command_thread;
|
||||
ModManager m_mod_manager;
|
||||
std::map<std::string, world::NodeDef> m_node_defs;
|
||||
ChunkManager m_chunk_manager;
|
||||
|
||||
private:
|
||||
void command_thread_func();
|
||||
|
||||
bool handle_packet(polygun::network::NetworkPacket& packet, Client* client = nullptr);
|
||||
bool handle_new_player(polygun::network::NetworkPacket& packet);
|
||||
void handle_chunk_request(polygun::network::NetworkPacket& packet, Client* client);
|
||||
void handle_node_definition(polygun::network::NetworkPacket& packet, Client* client);
|
||||
void handle_resource_request(polygun::network::NetworkPacket& packet, Client* client);
|
||||
void handle_player_disconnected(const Client* client);
|
||||
|
Loading…
x
Reference in New Issue
Block a user