From 1da7fb7e1267bf2e6f1cd9c0a5bf35fdb39f985b Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Wed, 1 May 2024 14:23:33 +0530 Subject: [PATCH] player timeouts --- src/Console.hx | 24 +++++++++---------- src/MarbleGame.hx | 1 + src/net/ClientConnection.hx | 10 ++++++++ src/net/Net.hx | 43 ++++++++++++++++++++++++++++++---- src/net/NetCommands.hx | 16 +++++++++++++ src/shaders/CubemapRenderer.hx | 4 ++-- 6 files changed, 80 insertions(+), 18 deletions(-) diff --git a/src/Console.hx b/src/Console.hx index a6ac8bef..72e3569f 100644 --- a/src/Console.hx +++ b/src/Console.hx @@ -51,11 +51,11 @@ class Console { entries = []; } - public static function time() { + public static inline function time() { return haxe.Timer.stamp(); } - function getTime() { + inline function getTime() { return Std.int((haxe.Timer.stamp() - timeSinceStart) * 1000) / 1000; } @@ -73,43 +73,43 @@ class Console { } } - function _log(t:String) { + inline function _log(t:String) { addEntry("log", t); } - function _warn(t:String) { + inline function _warn(t:String) { addEntry("warn", t); } - function _error(t:String) { + inline function _error(t:String) { addEntry("error", t); } - function _debug(t:String) { + inline function _debug(t:String) { addEntry("debug", t); } - public static function log(t:String) { + public static inline function log(t:String) { instance._log(t); } - public static function warn(t:String) { + public static inline function warn(t:String) { instance._warn(t); } - public static function error(t:String) { + public static inline function error(t:String) { instance._error(t); } - public static function debug(t:String) { + public static inline function debug(t:String) { instance._debug(t); } - public static function addConsumer(c:ConsoleEntry->Void) { + public static inline function addConsumer(c:ConsoleEntry->Void) { instance.consumers.push(c); } - public static function removeConsumer(c:ConsoleEntry->Void) { + public static inline function removeConsumer(c:ConsoleEntry->Void) { instance.consumers.remove(c); } diff --git a/src/MarbleGame.hx b/src/MarbleGame.hx index c50fbc60..1c7e234e 100644 --- a/src/MarbleGame.hx +++ b/src/MarbleGame.hx @@ -189,6 +189,7 @@ class MarbleGame { public function update(dt:Float) { MasterServerClient.process(); + Net.checkPacketTimeout(dt); if (limitingFps) { fpsLimitAccum += dt; diff --git a/src/net/ClientConnection.hx b/src/net/ClientConnection.hx index 0611d680..519f0ad2 100644 --- a/src/net/ClientConnection.hx +++ b/src/net/ClientConnection.hx @@ -27,6 +27,8 @@ class ClientConnection extends GameConnection { var rtt:Float; var pingSendTime:Float; var _rttRecords:Array = []; + var lastRecvTime:Float; + var didWarnTimeout:Bool = false; public function new(id:Int, socket:RTCPeerConnection, datachannel:RTCDataChannel) { super(id); @@ -40,6 +42,14 @@ class ClientConnection extends GameConnection { override function sendBytes(b:Bytes) { datachannel.sendBytes(b); } + + public inline function needsTimeoutWarn(t:Float) { + return (t - lastRecvTime) > 10 && !didWarnTimeout; + } + + public inline function needsTimeoutKick(t:Float) { + return (t - lastRecvTime) > 15 && didWarnTimeout; + } } @:publicFields diff --git a/src/net/Net.hx b/src/net/Net.hx index b48fb28d..c7b9c7cb 100644 --- a/src/net/Net.hx +++ b/src/net/Net.hx @@ -159,7 +159,7 @@ class Net { haxe.Timer.delay(() -> connectedCb(), 1500); // 1.5 second delay to do the RTT calculation } clientDatachannel.onMessage = (b) -> { - onPacketReceived(client, clientDatachannel, new InputBitStream(b)); + onPacketReceived(clientConnection, client, clientDatachannel, new InputBitStream(b)); } clientDatachannel.onClosed = () -> { var weLeftOurselves = !Net.isClient; // If we left ourselves, this would be set to false due to order of ops, disconnect being called first, and then the datachannel closing @@ -230,13 +230,46 @@ class Net { } } + public static function checkPacketTimeout(dt:Float) { + if (!Net.isMP) + return; + static var accum = 0.0; + accum += dt; + if (accum > 1.0) { + accum = 0; + var t = Console.time(); + for (dc => cc in clients) { + if (cc is ClientConnection) { + var conn = cast(cc, ClientConnection); + if (conn.needsTimeoutWarn(t)) { + conn.didWarnTimeout = true; + if (Net.isClient) { + NetCommands.requestPing(); + } + if (Net.isHost) { + NetCommands.pingClient(cc, t); + } + } + if (conn.needsTimeoutKick(t)) { + if (Net.isHost) { + dc.close(); + } + if (Net.isClient) { + disconnect(); + } + } + } + } + } + } + static function onClientConnect(c:RTCPeerConnection, dc:RTCDataChannel) { clientId += 1; var cc = new ClientConnection(clientId, c, dc); clients.set(c, cc); clientIdMap[clientId] = clients[c]; dc.onMessage = (msgBytes) -> { - onPacketReceived(c, dc, new InputBitStream(msgBytes)); + onPacketReceived(cc, c, dc, new InputBitStream(msgBytes)); } dc.onClosed = () -> { clients.remove(c); @@ -347,9 +380,12 @@ class Net { return b.getBytes(); } - static function onPacketReceived(c:RTCPeerConnection, dc:RTCDataChannel, input:InputBitStream) { + static function onPacketReceived(conn:ClientConnection, c:RTCPeerConnection, dc:RTCDataChannel, input:InputBitStream) { if (!Net.isMP) return; // only for MP + conn.lastRecvTime = Console.time(); + conn.didWarnTimeout = false; + var packetType = input.readByte(); switch (packetType) { case NetCommand: @@ -372,7 +408,6 @@ class Net { case PingBack: var pingLeft = input.readByte(); Console.log("Got pingback packet!"); - var conn:ClientConnection = cast clients[c]; var now = Console.time(); conn._rttRecords.push((now - conn.pingSendTime)); if (pingLeft > 0) { diff --git a/src/net/NetCommands.hx b/src/net/NetCommands.hx index 250b4fe8..71f7ad1a 100644 --- a/src/net/NetCommands.hx +++ b/src/net/NetCommands.hx @@ -248,4 +248,20 @@ class NetCommands { } world.multiplayerStarted = false; } + + @:rpc(server) public static function ping(sendTime:Float) { + if (Net.isClient) { + pingBack(Console.time() - sendTime); + } + } + + @:rpc(client) public static function pingBack(ping:Float) { + // Do nothing??? + } + + @:rpc(client) public static function requestPing() { + if (Net.isHost) { + ping(Console.time()); + } + } } diff --git a/src/shaders/CubemapRenderer.hx b/src/shaders/CubemapRenderer.hx index 2317f83b..889e74eb 100644 --- a/src/shaders/CubemapRenderer.hx +++ b/src/shaders/CubemapRenderer.hx @@ -19,7 +19,7 @@ class CubemapRenderer { var scene:Scene; var nextFaceToRender:Int; var facesPerRender:Int = 2; - var updateFps:Float = 360.0; + var updateFps:Float = 360.0; // 6 faces in (1/60) seconds, 1 face in (1/360) seconds var lastRenderTime:Float = 0; var usingSky:Bool = false; @@ -42,7 +42,7 @@ class CubemapRenderer { if (usingSky) return; var start = haxe.Timer.stamp(); - if (start - lastRenderTime > 1.0 / updateFps) { + if (start - lastRenderTime > facesPerRender * 1.0 / updateFps) { lastRenderTime = start; } else { return;