player timeouts

This commit is contained in:
RandomityGuy 2024-05-01 14:23:33 +05:30
parent 9b4a5ac398
commit 1da7fb7e12
6 changed files with 80 additions and 18 deletions

View file

@ -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);
}

View file

@ -189,6 +189,7 @@ class MarbleGame {
public function update(dt:Float) {
MasterServerClient.process();
Net.checkPacketTimeout(dt);
if (limitingFps) {
fpsLimitAccum += dt;

View file

@ -27,6 +27,8 @@ class ClientConnection extends GameConnection {
var rtt:Float;
var pingSendTime:Float;
var _rttRecords:Array<Float> = [];
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

View file

@ -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) {

View file

@ -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());
}
}
}

View file

@ -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;