X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fclient%2Fnet.cpp;h=f1e555336699738a4434470c1bd1955ad8bea4d4;hb=20d0a76d2519c71009c3b3babec0df27529f8142;hp=73931f44c1825ba166a743cafd53c8e9747e4d7c;hpb=d38be21d103052761505d58a6d13e30a896dde01;p=blank.git diff --git a/src/client/net.cpp b/src/client/net.cpp index 73931f4..f1e5553 100644 --- a/src/client/net.cpp +++ b/src/client/net.cpp @@ -4,6 +4,7 @@ #include "NetworkedInput.hpp" #include "../app/init.hpp" +#include "../geometry/distance.hpp" #include "../io/WorldSave.hpp" #include "../net/Packet.hpp" #include "../world/Chunk.hpp" @@ -22,8 +23,9 @@ namespace blank { namespace client { -ChunkReceiver::ChunkReceiver(ChunkStore &store, const WorldSave &save) -: store(store) +ChunkReceiver::ChunkReceiver(Client &client, ChunkStore &store, const WorldSave &save) +: client(client) +, store(store) , save(save) , transmissions() , timer(5000) { @@ -39,7 +41,14 @@ void ChunkReceiver::Update(int dt) { for (ChunkTransmission &trans : transmissions) { if (trans.active && (timer.Elapsed() - trans.last_update) > timer.Interval()) { cout << "timeout for transmission of chunk " << trans.coords << endl; - trans.Clear(); + if (trans.header_received) { + client.SendChunkRequest(trans.coords); + trans.Reset(); + trans.last_update = timer.Elapsed(); + } else { + // well shit + trans.Clear(); + } } } if (transmissions.size() > 3) { @@ -61,7 +70,7 @@ int ChunkReceiver::ToLoad() const noexcept { void ChunkReceiver::LoadOne() { if (!store.HasMissing()) return; - Chunk::Pos pos = store.NextMissing(); + ExactLocation::Coarse pos = store.NextMissing(); Chunk *chunk = store.Allocate(pos); if (!chunk) { // chunk store corrupted? @@ -151,7 +160,7 @@ void ChunkReceiver::Commit(ChunkTransmission &trans) { Chunk *chunk = store.Allocate(trans.coords); if (!chunk) { - // chunk no longer of interes, just drop the data + // chunk no longer of interest, just drop the data // it should probably be cached to disk, but not now :P trans.Clear(); return; @@ -166,10 +175,17 @@ void ChunkReceiver::Commit(ChunkTransmission &trans) { if (uncompress(dst, &dst_len, src, src_len) != Z_OK) { // omg, now what? cout << "got corruped chunk data for " << trans.coords << endl; + client.SendChunkRequest(trans.coords); + trans.Reset(); + // chunk data can, and probably will, contain invalid block IDs, so + // zero it to be safe + memset(dst, 0, dst_len); + return; } } else { memcpy(dst, src, min(src_len, dst_len)); } + chunk->ScanActive(); chunk->Invalidate(); trans.Clear(); } @@ -187,11 +203,15 @@ ChunkTransmission::ChunkTransmission() } -void ChunkTransmission::Clear() noexcept { +void ChunkTransmission::Reset() noexcept { data_size = 0; data_received = 0; last_update = 0; header_received = false; +} + +void ChunkTransmission::Clear() noexcept { + Reset(); active = false; } @@ -224,10 +244,15 @@ IPaddress client_resolve(const char *host, Uint16 port) { } +// relying on {} zero intitialization for UDPpacket, because +// the type and number of fields is not well defined +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" Client::Client(const Config::Network &conf) : conn(client_resolve(conf.host.c_str(), conf.port)) , client_sock(client_bind(0)) , client_pack{ -1, nullptr, 0 } { +#pragma GCC diagnostic pop client_pack.data = new Uint8[sizeof(Packet)]; client_pack.maxlen = sizeof(Packet); // establish connection @@ -286,16 +311,14 @@ uint16_t Client::SendLogin(const string &name) { uint16_t Client::SendPlayerUpdate( const EntityState &prediction, const glm::vec3 &movement, - float pitch, - float yaw, + float, + float, uint8_t actions, uint8_t slot ) { auto pack = Packet::Make(client_pack); pack.WritePredictedState(prediction); pack.WriteMovement(movement); - pack.WritePitch(pitch); - pack.WriteYaw(yaw); pack.WriteActions(actions); pack.WriteSlot(slot); return conn.Send(client_pack, client_sock); @@ -306,16 +329,42 @@ uint16_t Client::SendPart() { return conn.Send(client_pack, client_sock); } +uint16_t Client::SendChunkRequest( + const glm::ivec3 &coords +) { + auto pack = Packet::Make(client_pack); + pack.WriteChunkCoords(coords); + return conn.Send(client_pack, client_sock); +} + +uint16_t Client::SendMessage( + uint8_t type, + uint32_t ref, + const string &msg +) { + auto pack = Packet::Make(client_pack); + pack.WriteType(type); + pack.WriteReferral(ref); + pack.WriteMessage(msg); + client_pack.len = sizeof(Packet::Header) + Packet::Message::GetSize(msg); + return conn.Send(client_pack, client_sock); +} NetworkedInput::NetworkedInput(World &world, Player &player, Client &client) : PlayerController(world, player) , client(client) , player_hist() +, old_movement(0.0f) +, old_actions(0) , actions(0) { } -void NetworkedInput::Update(int dt) { +bool NetworkedInput::UpdateImportant() const noexcept { + return old_actions != actions || !iszero(old_movement - GetMovement()); +} + +void NetworkedInput::Update(Entity &, float) { Invalidate(); UpdatePlayer(); } @@ -332,15 +381,17 @@ void NetworkedInput::PushPlayerUpdate(int dt) { InventorySlot() ); if (player_hist.size() < 16) { - player_hist.emplace_back(state, GetPlayer().GetEntity().TargetVelocity(), dt, packet); + player_hist.emplace_back(state, GetMovement(), dt * 0.001f, packet); } else { auto entry = player_hist.begin(); entry->state = state; - entry->tgt_vel = GetPlayer().GetEntity().TargetVelocity(); - entry->delta_t = dt; + entry->movement = GetMovement(); + entry->delta_t = dt * 0.001f; entry->packet = packet; player_hist.splice(player_hist.end(), player_hist, entry); } + old_movement = GetMovement(); + old_actions = actions; } void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corrected_state) { @@ -366,34 +417,30 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr } } - EntityState &player_state = GetPlayer().GetEntity().GetState(); + glm::vec3 restore_movement(GetMovement()); + + EntityState player_state = GetPlayer().GetEntity().GetState(); Entity replay(GetPlayer().GetEntity()); replay.SetState(corrected_state); if (entry != end) { - entry->state.chunk_pos = replay.GetState().chunk_pos; - entry->state.block_pos = replay.GetState().block_pos; + entry->state.pos = replay.GetState().pos; ++entry; } vector col; while (entry != end) { - replay.Velocity(entry->state.velocity); - replay.TargetVelocity(entry->tgt_vel); - replay.Update(entry->delta_t); - if (GetWorld().Intersection(replay, col)) { - GetWorld().Resolve(replay, col); - col.clear(); - } - entry->state.chunk_pos = replay.GetState().chunk_pos; - entry->state.block_pos = replay.GetState().block_pos; + SetMovement(entry->movement); + replay.Update(GetWorld(), entry->delta_t); + entry->state.pos = replay.GetState().pos; ++entry; } glm::vec3 displacement(replay.GetState().Diff(player_state)); - const float disp_squared = dot(displacement, displacement); + const float disp_squared = glm::dot(displacement, displacement); if (disp_squared < 16.0f * numeric_limits::epsilon()) { + SetMovement(restore_movement); return; } @@ -404,14 +451,15 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr constexpr float max_disp = 0.0001f; // (1/100)^2 if (disp_squared > warp_thresh) { - player_state.chunk_pos = replay.GetState().chunk_pos; - player_state.block_pos = replay.GetState().block_pos; + player_state.pos = replay.GetState().pos; } else if (disp_squared < max_disp) { - player_state.block_pos += displacement; + player_state.pos.block += displacement; } else { displacement *= 0.01f / sqrt(disp_squared); - player_state.block_pos += displacement; + player_state.pos.block += displacement; } + GetPlayer().GetEntity().SetState(player_state); + SetMovement(restore_movement); } void NetworkedInput::StartPrimaryAction() {