]> git.localhorst.tv Git - blank.git/blobdiff - src/net/net.cpp
unified location handling
[blank.git] / src / net / net.cpp
index 4de800e2429eb4c1c65e4a87ef0ec17567692058..5d062343b8976f28425b3c45fd7b704dc00e0e2b 100644 (file)
@@ -5,6 +5,7 @@
 #include "Packet.hpp"
 
 #include "../app/init.hpp"
+#include "../geometry/const.hpp"
 #include "../model/Model.hpp"
 #include "../world/Entity.hpp"
 #include "../world/EntityState.hpp"
@@ -47,12 +48,23 @@ CongestionControl::CongestionControl()
 , tx_bytes(0)
 , rx_bytes(0)
 , tx_kbps(0.0f)
-, rx_kbps(0.0f) {
+, rx_kbps(0.0f)
+, mode(GOOD)
+// rtt > 100ms or packet loss > 5% is BAD
+, bad_rtt(100.0f)
+, bad_loss(0.05f)
+// rtt > 250ms or packet loss > 15% is UGLY
+, ugly_rtt(250.0f)
+, ugly_loss(0.15f)
+, mode_keep_time(1000) {
        Uint32 now = SDL_GetTicks();
        for (Uint32 &s : stamps) {
                s = now;
        }
        next_sample += now;
+       mode_entered = now;
+       mode_reset = now;
+       mode_step = now;
 }
 
 void CongestionControl::PacketSent(uint16_t seq) noexcept {
@@ -87,7 +99,8 @@ void CongestionControl::UpdatePacketLoss() noexcept {
 
 void CongestionControl::UpdateRTT(std::uint16_t seq) noexcept {
        if (!SamplePacket(seq)) return;
-       int diff = HeadDiff(seq);
+       int16_t diff = int16_t(seq) - int16_t(stamp_last);
+       diff /= sample_skip;
        if (diff > 0 || diff < -15) {
                // packet outside observed time frame
                return;
@@ -100,11 +113,6 @@ bool CongestionControl::SamplePacket(std::uint16_t seq) const noexcept {
        return seq % sample_skip == 0;
 }
 
-int CongestionControl::HeadDiff(std::uint16_t seq) const noexcept {
-       int16_t diff = int16_t(seq) - int16_t(stamp_last);
-       return diff / sample_skip;
-}
-
 void CongestionControl::PacketIn(const UDPpacket &pack) noexcept {
        rx_bytes += pack.len + packet_overhead;
        UpdateStats();
@@ -117,12 +125,71 @@ void CongestionControl::PacketOut(const UDPpacket &pack) noexcept {
 
 void CongestionControl::UpdateStats() noexcept {
        Uint32 now = SDL_GetTicks();
-       if (now >= next_sample) {
-               tx_kbps = float(tx_bytes) * (1.0f / 1024.0f);
-               rx_kbps = float(rx_bytes) * (1.0f / 1024.0f);
-               tx_bytes = 0;
-               rx_bytes = 0;
-               next_sample += 1000;
+       if (now < next_sample) {
+               // not yet
+               return;
+       }
+       tx_kbps = float(tx_bytes) * (1.0f / 1024.0f);
+       rx_kbps = float(rx_bytes) * (1.0f / 1024.0f);
+       tx_bytes = 0;
+       rx_bytes = 0;
+       next_sample += 1000;
+       UpdateMode();
+}
+
+void CongestionControl::UpdateMode() noexcept {
+       Mode now_mode = Conditions();
+       if (now_mode > mode) {
+               ChangeMode(now_mode);
+       } else if (now_mode < mode) {
+               CheckUpgrade(now_mode);
+       } else {
+               KeepMode();
+       }
+}
+
+void CongestionControl::CheckUpgrade(Mode m) noexcept {
+       Uint32 now = SDL_GetTicks();
+       Uint32 time_in_mode = now - mode_entered;
+       if (time_in_mode < mode_keep_time) {
+               return;
+       }
+       ChangeMode(m);
+}
+
+void CongestionControl::ChangeMode(Mode m) noexcept {
+       Uint32 now = SDL_GetTicks();
+       if (m > mode) {
+               // changed to worse mode
+               // if we spent less than 10 seconds in better mode
+               // double keep time till up to 64 seconds
+               if (now - mode_entered < 10000) {
+                       if (mode_keep_time < 64000) {
+                               mode_keep_time *= 2;
+                       }
+               }
+       }
+       mode = m;
+       mode_entered = now;
+       mode_reset = mode_entered;
+}
+
+void CongestionControl::KeepMode() noexcept {
+       mode_reset = SDL_GetTicks();
+       // if in good mode for 10 seconds, halve keep time till down to one second
+       if (mode == GOOD && mode_keep_time > 1000 && mode_step - mode_reset > 10000) {
+               mode_keep_time /= 2;
+               mode_step = mode_reset;
+       }
+}
+
+CongestionControl::Mode CongestionControl::Conditions() const noexcept {
+       if (rtt > ugly_rtt || packet_loss > ugly_loss) {
+               return UGLY;
+       } else if (rtt > bad_rtt || packet_loss > bad_loss) {
+               return BAD;
+       } else {
+               return GOOD;
        }
 }
 
@@ -379,8 +446,8 @@ void Packet::Payload::Read(glm::quat &val, size_t off) const noexcept {
 }
 
 void Packet::Payload::Write(const EntityState &state, size_t off) noexcept {
-       Write(state.chunk_pos, off);
-       WritePackU(state.block_pos * (1.0f / 16.0f), off + 12);
+       Write(state.pos.chunk, off);
+       WritePackU(state.pos.block * (1.0f / ExactLocation::fscale), off + 12);
        Write(state.velocity, off + 18);
        Write(state.orient, off + 30);
        WritePackN(state.pitch * PI_0p5_inv, off + 38);
@@ -388,20 +455,20 @@ void Packet::Payload::Write(const EntityState &state, size_t off) noexcept {
 }
 
 void Packet::Payload::Read(EntityState &state, size_t off) const noexcept {
-       Read(state.chunk_pos, off);
-       ReadPackU(state.block_pos, off + 12);
+       Read(state.pos.chunk, off);
+       ReadPackU(state.pos.block, off + 12);
        Read(state.velocity, off + 18);
        Read(state.orient, off + 30);
        ReadPackN(state.pitch, off + 38);
        ReadPackN(state.yaw, off + 40);
-       state.block_pos *= 16.0f;
+       state.pos.block *= ExactLocation::fscale;
        state.pitch *= PI_0p5;
        state.yaw *= PI;
 }
 
 void Packet::Payload::Write(const EntityState &state, const glm::ivec3 &base, size_t off) noexcept {
-       WritePackB(state.chunk_pos - base, off);
-       WritePackU(state.block_pos * (1.0f / 16.0f), off + 3);
+       WritePackB(state.pos.chunk - base, off);
+       WritePackU(state.pos.block * (1.0f / ExactLocation::fscale), off + 3);
        Write(state.velocity, off + 9);
        Write(state.orient, off + 21);
        WritePackN(state.pitch * PI_0p5_inv, off + 29);
@@ -409,14 +476,14 @@ void Packet::Payload::Write(const EntityState &state, const glm::ivec3 &base, si
 }
 
 void Packet::Payload::Read(EntityState &state, const glm::ivec3 &base, size_t off) const noexcept {
-       ReadPackB(state.chunk_pos, off);
-       ReadPackU(state.block_pos, off + 3);
+       ReadPackB(state.pos.chunk, off);
+       ReadPackU(state.pos.block, off + 3);
        Read(state.velocity, off + 9);
        Read(state.orient, off + 21);
        ReadPackN(state.pitch, off + 29);
        ReadPackN(state.yaw, off + 31);
-       state.chunk_pos += base;
-       state.block_pos *= 16.0f;
+       state.pos.chunk += base;
+       state.pos.block *= ExactLocation::fscale;
        state.pitch *= PI_0p5;
        state.yaw *= PI;
 }