X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fserver%2Fnet.cpp;h=16aa1cb004733865337976e72c51c78da6382e87;hb=78dcbeb7a905c4c153cb1b20e23f5adc1efc6d7e;hp=44a42682497276f0c647578bd592c1725e94adde;hpb=b066e776622f96e906600a0c4a08de392bd03676;p=blank.git diff --git a/src/server/net.cpp b/src/server/net.cpp index 44a4268..16aa1cb 100644 --- a/src/server/net.cpp +++ b/src/server/net.cpp @@ -3,6 +3,7 @@ #include "Server.hpp" #include "../app/init.hpp" +#include "../io/WorldSave.hpp" #include "../model/CompositeModel.hpp" #include "../world/ChunkIndex.hpp" #include "../world/Entity.hpp" @@ -10,6 +11,7 @@ #include #include +#include using namespace std; @@ -172,7 +174,7 @@ void ChunkTransmitter::Release() { ClientConnection::ClientConnection(Server &server, const IPaddress &addr) : server(server) , conn(addr) -, player(nullptr) +, input() , player_model(nullptr) , spawns() , confirm_wait(0) @@ -180,6 +182,7 @@ ClientConnection::ClientConnection(Server &server, const IPaddress &addr) , player_update_state() , player_update_pack(0) , player_update_timer(1500) +, old_actions(0) , transmitter(*this) , chunk_queue() , old_base() { @@ -243,6 +246,7 @@ void ClientConnection::Update(int dt) { } SendUpdates(); + input->Update(dt); CheckPlayerFix(); CheckChunkQueue(); } @@ -280,7 +284,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(); } @@ -387,10 +391,15 @@ void ClientConnection::CheckChunkQueue() { } } -void ClientConnection::AttachPlayer(Player &new_player) { +void ClientConnection::AttachPlayer(Player &player) { DetachPlayer(); - player = &new_player; + input.reset(new DirectInput(server.GetWorld(), player, server)); PlayerEntity().Ref(); + if (server.GetWorldSave().Exists(player)) { + server.GetWorldSave().Read(player); + } else { + // TODO: spawn + } old_base = PlayerChunks().Base(); Chunk::Pos begin = PlayerChunks().CoordsBegin(); @@ -406,17 +415,19 @@ void ClientConnection::AttachPlayer(Player &new_player) { GetPlayerModel().Instantiate(PlayerEntity().GetModel()); } - cout << "player \"" << player->Name() << "\" joined" << endl; + cout << "player \"" << player.Name() << "\" joined" << endl; } void ClientConnection::DetachPlayer() { if (!HasPlayer()) return; - cout << "player \"" << player->Name() << "\" left" << endl; - player->GetEntity().Kill(); - player->GetEntity().UnRef(); - player = nullptr; + cout << "player \"" << input->GetPlayer().Name() << "\" left" << endl; + server.GetWorldSave().Write(input->GetPlayer()); + PlayerEntity().Kill(); + PlayerEntity().UnRef(); + input.reset(); transmitter.Abort(); chunk_queue.clear(); + old_actions = 0; } void ClientConnection::SetPlayerModel(const CompositeModel &m) noexcept { @@ -511,21 +522,57 @@ void ClientConnection::On(const Packet::PlayerUpdate &pack) { int pack_diff = int16_t(pack.Seq()) - int16_t(player_update_pack); bool overdue = player_update_timer.HitOnce(); player_update_timer.Reset(); - if (pack_diff > 0 || overdue) { - player_update_pack = pack.Seq(); - pack.ReadPlayerState(player_update_state); - // accept velocity and orientation as "user input" - PlayerEntity().Velocity(player_update_state.velocity); - PlayerEntity().Orientation(player_update_state.orient); + if (pack_diff <= 0 && !overdue) { + // drop old packets if we have a fairly recent state + 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->SelectInventory(slot); + + if ((new_actions & 0x01) && !(old_actions & 0x01)) { + input->StartPrimaryAction(); + } else if (!(new_actions & 0x01) && (old_actions & 0x01)) { + input->StopPrimaryAction(); + } + if ((new_actions & 0x02) && !(old_actions & 0x02)) { + input->StartSecondaryAction(); + } else if (!(new_actions & 0x02) && (old_actions & 0x02)) { + input->StopSecondaryAction(); } + if ((new_actions & 0x04) && !(old_actions & 0x04)) { + input->StartTertiaryAction(); + } else if (!(new_actions & 0x04) && (old_actions & 0x04)) { + input->StopTertiaryAction(); + } + old_actions = new_actions; +} + +bool ClientConnection::ChunkInRange(const glm::ivec3 &pos) const noexcept { + return HasPlayer() && PlayerChunks().InRange(pos); } -Server::Server(const Config::Network &conf, World &world) +Server::Server(const Config::Network &conf, World &world, const WorldSave &save) : serv_sock(nullptr) , serv_pack{ -1, nullptr, 0 } , clients() , world(world) +, save(save) , player_model(nullptr) { serv_sock = SDLNet_UDP_Open(conf.port); if (!serv_sock) { @@ -608,5 +655,21 @@ const CompositeModel &Server::GetPlayerModel() const noexcept { return *player_model; } +void Server::SetBlock(Chunk &chunk, int index, const Block &block) { + chunk.SetBlock(index, block); + // 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(); + } + } +} + } }