X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fserver%2Fnet.cpp;h=6ceb186644d3a9f7d5d24526d3cfb2376492db8c;hb=dbd214ac278019c20c883cbb76456b0b0fddc063;hp=ea5b4d995f19d38262891b0919f1fb2360ed05b3;hpb=c1da86ebab41895bf49ed747c75ecf722e8c5586;p=blank.git diff --git a/src/server/net.cpp b/src/server/net.cpp index ea5b4d9..6ceb186 100644 --- a/src/server/net.cpp +++ b/src/server/net.cpp @@ -3,11 +3,13 @@ #include "Server.hpp" #include "../app/init.hpp" -#include "../model/CompositeModel.hpp" +#include "../io/WorldSave.hpp" +#include "../model/Model.hpp" #include "../world/ChunkIndex.hpp" #include "../world/Entity.hpp" #include "../world/World.hpp" +#include #include #include #include @@ -283,7 +285,7 @@ uint16_t ClientConnection::Send() { } uint16_t ClientConnection::Send(size_t len) { - server.GetPacket().len = len; + server.GetPacket().len = sizeof(Packet::Header) + len; return Send(); } @@ -351,6 +353,23 @@ void ClientConnection::CheckPlayerFix() { } } +namespace { + +struct QueueCompare { + explicit QueueCompare(const glm::ivec3 &base) + : base(base) { } + bool operator ()(const glm::ivec3 &left, const glm::ivec3 &right) const noexcept { + const glm::ivec3 ld(left - base); + const glm::ivec3 rd(right - base); + return + ld.x * ld.x + ld.y * ld.y + ld.z * ld.z < + rd.x * rd.x + rd.y * rd.y + rd.z * rd.z; + } + const glm::ivec3 &base; +}; + +} + void ClientConnection::CheckChunkQueue() { if (PlayerChunks().Base() != old_base) { Chunk::Pos begin = PlayerChunks().CoordsBegin(); @@ -365,6 +384,7 @@ void ClientConnection::CheckChunkQueue() { } } old_base = PlayerChunks().Base(); + sort(chunk_queue.begin(), chunk_queue.end(), QueueCompare(old_base)); } if (transmitter.Transmitting()) { transmitter.Transmit(); @@ -405,6 +425,8 @@ void ClientConnection::AttachPlayer(Player &player) { } } } + sort(chunk_queue.begin(), chunk_queue.end(), QueueCompare(old_base)); + // TODO: should the server do this? if (HasPlayerModel()) { GetPlayerModel().Instantiate(PlayerEntity().GetModel()); } @@ -415,6 +437,7 @@ void ClientConnection::AttachPlayer(Player &player) { void ClientConnection::DetachPlayer() { if (!HasPlayer()) return; cout << "player \"" << input->GetPlayer().Name() << "\" left" << endl; + server.GetWorldSave().Write(input->GetPlayer()); PlayerEntity().Kill(); PlayerEntity().UnRef(); input.reset(); @@ -423,7 +446,7 @@ void ClientConnection::DetachPlayer() { old_actions = 0; } -void ClientConnection::SetPlayerModel(const CompositeModel &m) noexcept { +void ClientConnection::SetPlayerModel(const Model &m) noexcept { player_model = &m; if (HasPlayer()) { m.Instantiate(PlayerEntity().GetModel()); @@ -434,7 +457,7 @@ bool ClientConnection::HasPlayerModel() const noexcept { return player_model; } -const CompositeModel &ClientConnection::GetPlayerModel() const noexcept { +const Model &ClientConnection::GetPlayerModel() const noexcept { return *player_model; } @@ -482,7 +505,7 @@ void ClientConnection::On(const Packet::Login &pack) { string name; pack.ReadPlayerName(name); - Player *new_player = server.GetWorld().AddPlayer(name); + Player *new_player = server.JoinPlayer(name); if (new_player) { // success! @@ -555,12 +578,35 @@ void ClientConnection::On(const Packet::PlayerUpdate &pack) { old_actions = new_actions; } +bool ClientConnection::ChunkInRange(const glm::ivec3 &pos) const noexcept { + return HasPlayer() && PlayerChunks().InRange(pos); +} + +void ClientConnection::On(const Packet::Message &pack) { + uint8_t type; + uint32_t ref; + string msg; + pack.ReadType(type); + pack.ReadReferral(ref); + pack.ReadMessage(msg); -Server::Server(const Config::Network &conf, World &world) + if (type == 1 && HasPlayer()) { + server.DistributeMessage(1, PlayerEntity().ID(), msg); + } +} + + +Server::Server( + const Config::Network &conf, + World &world, + const World::Config &wc, + const WorldSave &save) : serv_sock(nullptr) , serv_pack{ -1, nullptr, 0 } , clients() , world(world) +, spawn_index(world.Chunks().MakeIndex(wc.spawn, 3)) +, save(save) , player_model(nullptr) { serv_sock = SDLNet_UDP_Open(conf.port); if (!serv_sock) { @@ -572,6 +618,7 @@ Server::Server(const Config::Network &conf, World &world) } Server::~Server() { + world.Chunks().UnregisterIndex(spawn_index); delete[] serv_pack.data; SDLNet_UDP_Close(serv_sock); } @@ -628,7 +675,7 @@ void Server::Update(int dt) { } } -void Server::SetPlayerModel(const CompositeModel &m) noexcept { +void Server::SetPlayerModel(const Model &m) noexcept { player_model = &m; for (ClientConnection &client : clients) { client.SetPlayerModel(m); @@ -639,14 +686,55 @@ bool Server::HasPlayerModel() const noexcept { return player_model; } -const CompositeModel &Server::GetPlayerModel() const noexcept { +const Model &Server::GetPlayerModel() const noexcept { return *player_model; } +Player *Server::JoinPlayer(const string &name) { + if (spawn_index.MissingChunks() > 0) { + return nullptr; + } + Player *player = world.AddPlayer(name); + if (!player) { + return nullptr; + } + if (save.Exists(*player)) { + save.Read(*player); + } else { + // TODO: spawn + } + return player; +} + void Server::SetBlock(Chunk &chunk, int index, const Block &block) { chunk.SetBlock(index, block); - // TODO: send to clients - // also TODO: batch chunk changes + // TODO: batch chunk changes + auto pack = Packet::Make(GetPacket()); + pack.WriteChunkCoords(chunk.Position()); + pack.WriteBlockCount(uint32_t(1)); + pack.WriteIndex(index, 0); + pack.WriteBlock(chunk.BlockAt(index), 0); + GetPacket().len = sizeof(Packet::Header) + Packet::BlockUpdate::GetSize(1); + for (ClientConnection &client : clients) { + if (client.ChunkInRange(chunk.Position())) { + client.Send(); + } + } +} + +void Server::DistributeMessage(uint8_t type, uint32_t ref, const string &msg) { + auto pack = Packet::Make(serv_pack); + pack.WriteType(type); + pack.WriteReferral(ref); + pack.WriteMessage(msg); + serv_pack.len = sizeof(Packet::Header) + Packet::Message::GetSize(msg); + SendAll(); +} + +void Server::SendAll() { + for (ClientConnection &client : clients) { + client.GetConnection().Send(serv_pack, serv_sock); + } } }