X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fserver%2Fnet.cpp;h=aa1bdeb89448c46c757f6a4f47eb283c730ce581;hb=c58e8bce2b5eb61dea7bd78e98da8e1dcceb2d29;hp=27643ee8fc34abb4d9b18c0b2b47f0837df7f491;hpb=9711e8f340be713d9c4949cc92e680b2c3349bc4;p=blank.git diff --git a/src/server/net.cpp b/src/server/net.cpp index 27643ee..aa1bdeb 100644 --- a/src/server/net.cpp +++ b/src/server/net.cpp @@ -4,7 +4,7 @@ #include "../app/init.hpp" #include "../io/WorldSave.hpp" -#include "../model/CompositeModel.hpp" +#include "../model/Model.hpp" #include "../world/ChunkIndex.hpp" #include "../world/Entity.hpp" #include "../world/World.hpp" @@ -180,6 +180,7 @@ ClientConnection::ClientConnection(Server &server, const IPaddress &addr) , spawns() , confirm_wait(0) , entity_updates() +, entity_updates_skipped(0) , player_update_state() , player_update_pack(0) , player_update_timer(1500) @@ -211,7 +212,7 @@ void ClientConnection::Update(int dt) { // they're the same if (CanDespawn(*global_iter)) { SendDespawn(*local_iter); - } else { + } else if (SendingUpdates()) { // update QueueUpdate(*local_iter); } @@ -247,7 +248,6 @@ void ClientConnection::Update(int dt) { } SendUpdates(); - input->Update(dt); CheckPlayerFix(); CheckChunkQueue(); } @@ -309,6 +309,10 @@ void ClientConnection::SendDespawn(SpawnStatus &status) { ++confirm_wait; } +bool ClientConnection::SendingUpdates() const noexcept { + return entity_updates_skipped >= NetStat().SuggestedPacketSkip(); +} + void ClientConnection::QueueUpdate(SpawnStatus &status) { // don't send updates while spawn not ack'd or despawn sent if (status.spawn_pack == -1 && status.despawn_pack == -1) { @@ -317,10 +321,17 @@ void ClientConnection::QueueUpdate(SpawnStatus &status) { } void ClientConnection::SendUpdates() { + if (!SendingUpdates()) { + entity_updates.clear(); + ++entity_updates_skipped; + return; + } + auto base = PlayerChunks().Base(); auto pack = Prepare(); + pack.WriteChunkBase(base); int entity_pos = 0; for (SpawnStatus *status : entity_updates) { - pack.WriteEntity(*status->entity, entity_pos); + pack.WriteEntity(*status->entity, base, entity_pos); ++entity_pos; if (entity_pos == Packet::EntityUpdate::MAX_ENTITIES) { pack.WriteEntityCount(entity_pos); @@ -334,6 +345,7 @@ void ClientConnection::SendUpdates() { Send(Packet::EntityUpdate::GetSize(entity_pos)); } entity_updates.clear(); + entity_updates_skipped = 0; } void ClientConnection::CheckPlayerFix() { @@ -386,6 +398,11 @@ void ClientConnection::CheckChunkQueue() { old_base = PlayerChunks().Base(); sort(chunk_queue.begin(), chunk_queue.end(), QueueCompare(old_base)); } + // if we have packet skip enabled and just pushed an entity + // update, don't also send chunk data + if (NetStat().SuggestedPacketSkip() > 0 && entity_updates_skipped == 0) { + return; + } if (transmitter.Transmitting()) { transmitter.Transmit(); return; @@ -431,12 +448,17 @@ void ClientConnection::AttachPlayer(Player &player) { GetPlayerModel().Instantiate(PlayerEntity().GetModel()); } - cout << "player \"" << player.Name() << "\" joined" << endl; + string msg = "player \"" + player.Name() + "\" joined"; + cout << msg << endl; + server.DistributeMessage(0, 0, msg); } void ClientConnection::DetachPlayer() { if (!HasPlayer()) return; - cout << "player \"" << input->GetPlayer().Name() << "\" left" << endl; + string msg = "player \"" + input->GetPlayer().Name() + "\" left"; + cout << msg << endl; + server.DistributeMessage(0, 0, msg); + server.GetWorldSave().Write(input->GetPlayer()); PlayerEntity().Kill(); PlayerEntity().UnRef(); @@ -446,7 +468,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()); @@ -457,7 +479,7 @@ bool ClientConnection::HasPlayerModel() const noexcept { return player_model; } -const CompositeModel &ClientConnection::GetPlayerModel() const noexcept { +const Model &ClientConnection::GetPlayerModel() const noexcept { return *player_model; } @@ -543,21 +565,17 @@ void ClientConnection::On(const Packet::PlayerUpdate &pack) { return; } glm::vec3 movement(0.0f); - float pitch = 0.0f; - float yaw = 0.0f; uint8_t new_actions; uint8_t slot; player_update_pack = pack.Seq(); pack.ReadPredictedState(player_update_state); pack.ReadMovement(movement); - pack.ReadPitch(pitch); - pack.ReadYaw(yaw); pack.ReadActions(new_actions); pack.ReadSlot(slot); input->SetMovement(movement); - input->TurnHead(pitch - input->GetPitch(), yaw - input->GetYaw()); + input->TurnHead(player_update_state.pitch - input->GetPitch(), player_update_state.yaw - input->GetYaw()); input->SelectInventory(slot); if ((new_actions & 0x01) && !(old_actions & 0x01)) { @@ -582,6 +600,19 @@ 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); + + if (type == 1 && HasPlayer()) { + server.DispatchMessage(input->GetPlayer(), msg); + } +} + Server::Server( const Config::Network &conf, @@ -594,7 +625,8 @@ Server::Server( , world(world) , spawn_index(world.Chunks().MakeIndex(wc.spawn, 3)) , save(save) -, player_model(nullptr) { +, player_model(nullptr) +, cli(world) { serv_sock = SDLNet_UDP_Open(conf.port); if (!serv_sock) { throw NetError("SDLNet_UDP_Open"); @@ -662,7 +694,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); @@ -673,7 +705,7 @@ bool Server::HasPlayerModel() const noexcept { return player_model; } -const CompositeModel &Server::GetPlayerModel() const noexcept { +const Model &Server::GetPlayerModel() const noexcept { return *player_model; } @@ -709,5 +741,31 @@ void Server::SetBlock(Chunk &chunk, int index, const Block &block) { } } +void Server::DispatchMessage(Player &player, const string &msg) { + if (msg.empty()) { + return; + } + if (msg[0] == '/' && msg.size() > 1 && msg[1] != '/') { + cli.Execute(player, msg.substr(1)); + } else { + DistributeMessage(1, player.GetEntity().ID(), msg); + } +} + +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); + } +} + } }