]> git.localhorst.tv Git - blank.git/blobdiff - src/client/net.cpp
penalty force collision response
[blank.git] / src / client / net.cpp
index 6e8d00cc69de3922c063d912fdf34b82b46927b1..8a4930410605b7a8eacf0ae0dd8886ef2630ad51 100644 (file)
@@ -4,10 +4,12 @@
 #include "NetworkedInput.hpp"
 
 #include "../app/init.hpp"
+#include "../io/WorldSave.hpp"
 #include "../net/Packet.hpp"
 #include "../world/Chunk.hpp"
 #include "../world/ChunkStore.hpp"
 #include "../world/Player.hpp"
+#include "../world/World.hpp"
 
 #include <iostream>
 #include <zlib.h>
@@ -20,8 +22,9 @@ namespace blank {
 namespace client {
 
 
-ChunkReceiver::ChunkReceiver(ChunkStore &store)
+ChunkReceiver::ChunkReceiver(ChunkStore &store, const WorldSave &save)
 : store(store)
+, save(save)
 , transmissions()
 , timer(5000) {
        timer.Start();
@@ -47,8 +50,50 @@ void ChunkReceiver::Update(int dt) {
                        }
                }
        }
+       LoadN(10);
+       StoreN(10);
 }
 
+int ChunkReceiver::ToLoad() const noexcept {
+       return store.EstimateMissing();
+}
+
+void ChunkReceiver::LoadOne() {
+       if (!store.HasMissing()) return;
+
+       Chunk::Pos pos = store.NextMissing();
+       Chunk *chunk = store.Allocate(pos);
+       if (!chunk) {
+               // chunk store corrupted?
+               return;
+       }
+
+       if (save.Exists(pos)) {
+               save.Read(*chunk);
+       }
+}
+
+void ChunkReceiver::LoadN(size_t n) {
+       size_t end = min(n, size_t(ToLoad()));
+       for (size_t i = 0; i < end && store.HasMissing(); ++i) {
+               LoadOne();
+       }
+}
+
+void ChunkReceiver::StoreN(size_t n) {
+       size_t saved = 0;
+       for (Chunk &chunk : store) {
+               if (chunk.ShouldUpdateSave()) {
+                       save.Write(chunk);
+                       ++saved;
+                       if (saved >= n) {
+                               break;
+                       }
+               }
+       }
+}
+
+
 void ChunkReceiver::Handle(const Packet::ChunkBegin &pack) {
        uint32_t id;
        pack.ReadTransmissionId(id);
@@ -243,8 +288,8 @@ uint16_t Client::SendPlayerUpdate(
        const glm::vec3 &movement,
        float pitch,
        float yaw,
-       std::uint8_t actions,
-       std::uint8_t slot
+       uint8_t actions,
+       uint8_t slot
 ) {
        auto pack = Packet::Make<Packet::PlayerUpdate>(client_pack);
        pack.WritePredictedState(prediction);
@@ -278,7 +323,7 @@ void NetworkedInput::Update(int dt) {
 void NetworkedInput::PushPlayerUpdate(int dt) {
        const EntityState &state = GetPlayer().GetEntity().GetState();
 
-       std::uint16_t packet = client.SendPlayerUpdate(
+       uint16_t packet = client.SendPlayerUpdate(
                state,
                GetMovement(),
                GetPitch(),
@@ -287,10 +332,11 @@ void NetworkedInput::PushPlayerUpdate(int dt) {
                InventorySlot()
        );
        if (player_hist.size() < 16) {
-               player_hist.emplace_back(state, dt, packet);
+               player_hist.emplace_back(state, GetPlayer().GetEntity().TargetVelocity(), dt, packet);
        } else {
                auto entry = player_hist.begin();
                entry->state = state;
+               entry->tgt_vel = GetPlayer().GetEntity().TargetVelocity();
                entry->delta_t = dt;
                entry->packet = packet;
                player_hist.splice(player_hist.end(), player_hist, entry);
@@ -320,24 +366,27 @@ void NetworkedInput::MergePlayerCorrection(uint16_t seq, const EntityState &corr
                }
        }
 
-       EntityState replay_state(corrected_state);
        EntityState &player_state = GetPlayer().GetEntity().GetState();
+       Entity replay(GetPlayer().GetEntity());
+       replay.SetState(corrected_state);
 
        if (entry != end) {
-               entry->state.chunk_pos = replay_state.chunk_pos;
-               entry->state.block_pos = replay_state.block_pos;
+               entry->state.chunk_pos = replay.GetState().chunk_pos;
+               entry->state.block_pos = replay.GetState().block_pos;
                ++entry;
        }
 
+       vector<WorldCollision> col;
        while (entry != end) {
-               replay_state.velocity = entry->state.velocity;
-               replay_state.Update(entry->delta_t);
-               entry->state.chunk_pos = replay_state.chunk_pos;
-               entry->state.block_pos = replay_state.block_pos;
+               replay.Velocity(entry->state.velocity);
+               replay.TargetVelocity(entry->tgt_vel);
+               GetWorld().Update(replay, entry->delta_t);
+               entry->state.chunk_pos = replay.GetState().chunk_pos;
+               entry->state.block_pos = replay.GetState().block_pos;
                ++entry;
        }
 
-       glm::vec3 displacement(replay_state.Diff(player_state));
+       glm::vec3 displacement(replay.GetState().Diff(player_state));
        const float disp_squared = dot(displacement, displacement);
 
        if (disp_squared < 16.0f * numeric_limits<float>::epsilon()) {
@@ -351,8 +400,8 @@ 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_state.chunk_pos;
-               player_state.block_pos = replay_state.block_pos;
+               player_state.chunk_pos = replay.GetState().chunk_pos;
+               player_state.block_pos = replay.GetState().block_pos;
        } else if (disp_squared < max_disp) {
                player_state.block_pos += displacement;
        } else {