revise heartbeat

This commit is contained in:
JohnCorby 2022-08-24 14:07:22 -07:00
parent d8d56c472b
commit 00b5c4a4f2
3 changed files with 36 additions and 62 deletions

View File

@ -1,45 +1,21 @@
using OWML.Common;
using QSB.Messaging;
using QSB.Utility;
using QSB.Messaging;
namespace QSB.Player.Messages;
internal class PlayerHeartbeatMessage : QSBMessage
{
public const int TOTAL_HEARTBEAT_TRIES = 2;
public override void OnReceiveLocal()
{
if (QSBCore.IsHost)
{
var player = QSBPlayerManager.LocalPlayer;
if (!player.WaitingForHeartbeat)
{
DebugLog.DebugWrite($"Wait a minute... a heartbeat was already handled from the local player!", MessageType.Warning);
}
player.HeartbeatsRemaining = TOTAL_HEARTBEAT_TRIES;
player.WaitingForHeartbeat = false;
}
}
public override void OnReceiveRemote()
{
if (QSBCore.IsHost)
if (!QSBCore.IsHost)
{
var player = QSBPlayerManager.GetPlayer(From);
if (!player.WaitingForHeartbeat)
{
DebugLog.DebugWrite($"Wait a minute... a heartbeat was already handled from {From}!", MessageType.Warning);
}
player.HeartbeatsRemaining = TOTAL_HEARTBEAT_TRIES;
player.WaitingForHeartbeat = false;
return;
// send a response back to the host
new PlayerHeartbeatMessage { To = 0 }.Send();
}
else
{
// note that we got a response
var player = QSBPlayerManager.GetPlayer(From);
player.HeartbeatReceived = true;
}
new PlayerHeartbeatMessage() { To = 0 }.Send();
}
}

View File

@ -34,8 +34,11 @@ public partial class PlayerInfo
public bool IsLocalPlayer => TransformSync.isLocalPlayer; // if TransformSync is ever null, i give permission for nebula to make fun of me about it for the rest of time - johncorby
public ThrusterLightTracker ThrusterLightTracker;
public bool FlyingShip => ShipManager.Instance.CurrentFlyer == PlayerId;
public bool WaitingForHeartbeat;
public int HeartbeatsRemaining = PlayerHeartbeatMessage.TOTAL_HEARTBEAT_TRIES;
/// <summary>
/// only used on host
/// </summary>
public bool HeartbeatReceived;
public PlayerInfo(PlayerTransformSync transformSync)
{
@ -157,4 +160,4 @@ public partial class PlayerInfo
}
public override string ToString() => $"{PlayerId}:{GetType().Name} ({Name})";
}
}

View File

@ -1,4 +1,5 @@
using OWML.Common;
using Mirror;
using OWML.Common;
using QSB.ItemSync.WorldObjects.Items;
using QSB.Messaging;
using QSB.Player.Messages;
@ -24,7 +25,7 @@ public static class QSBPlayerManager
if (localInstance == null)
{
DebugLog.ToConsole("Error - Trying to get LocalPlayer when the local PlayerTransformSync instance is null." +
$"{Environment.NewLine} Stacktrace : {Environment.StackTrace} ", MessageType.Error);
$"{Environment.NewLine} Stacktrace : {Environment.StackTrace} ", MessageType.Error);
return null;
}
@ -68,8 +69,8 @@ public static class QSBPlayerManager
{
var cameraList = PlayerList.Where(x => x.Camera != null && x.PlayerId != LocalPlayerId).ToList();
if (includeLocalCamera
&& LocalPlayer != default
&& LocalPlayer.Camera != null)
&& LocalPlayer != default
&& LocalPlayer.Camera != null)
{
cameraList.Add(LocalPlayer);
}
@ -77,11 +78,11 @@ public static class QSBPlayerManager
{
if (LocalPlayer == default)
{
DebugLog.ToConsole($"Error - LocalPlayer is null.", MessageType.Error);
DebugLog.ToConsole("Error - LocalPlayer is null.", MessageType.Error);
return cameraList;
}
DebugLog.ToConsole($"Error - LocalPlayer.Camera is null.", MessageType.Error);
DebugLog.ToConsole("Error - LocalPlayer.Camera is null.", MessageType.Error);
LocalPlayer.Camera = Locator.GetPlayerCamera();
}
@ -111,7 +112,7 @@ public static class QSBPlayerManager
{
if (playerList == null)
{
DebugLog.ToConsole($"Error - Cannot get closest player from null player list.", MessageType.Error);
DebugLog.ToConsole("Error - Cannot get closest player from null player list.", MessageType.Error);
return null;
}
@ -119,7 +120,7 @@ public static class QSBPlayerManager
if (playerList.Count == 0)
{
DebugLog.ToConsole($"Error - Cannot get closest player from empty (ready) player list.", MessageType.Error);
DebugLog.ToConsole("Error - Cannot get closest player from empty (ready) player list.", MessageType.Error);
return null;
}
@ -131,36 +132,30 @@ public static class QSBPlayerManager
public static IEnumerator SendHeartbeat()
{
// yeah mirror has it's own hearbeat stuff, but we have problems with "ghost" PlayerInfos
// yeah mirror has it's own hearbeat stuff, but we have problems with "ghost" PlayerInfos due to epic transport being goofy
while (true)
{
if (QSBCore.IsInMultiplayer && QSBCore.IsHost)
{
for (var i = 0; i < PlayerList.Count; i++)
foreach (var player in PlayerList)
{
var player = PlayerList[i];
if (player.WaitingForHeartbeat)
// if we didnt receive a response in the last loop then we should kick them
if (!player.HeartbeatReceived)
{
player.HeartbeatsRemaining--;
DebugLog.DebugWrite($"Didn't hear from {player.PlayerId} in time. HeartbeatsRemaining is now {player.HeartbeatsRemaining}", MessageType.Warning);
DebugLog.DebugWrite($"Didn't receive heartbeat from {player.PlayerId} in time. Removing them.", MessageType.Warning);
if (player.HeartbeatsRemaining == 0)
{
OnRemovePlayer?.Invoke(player);
player.HudMarker?.Remove();
PlayerList.Remove(player);
DebugLog.ToConsole($"Haven't heard from {player.PlayerId} in {PlayerHeartbeatMessage.TOTAL_HEARTBEAT_TRIES} beats, removing...", MessageType.Error);
}
NetworkServer.Destroy(player.TransformSync.gameObject);
}
player.WaitingForHeartbeat = true;
// reset the state for the next send
player.HeartbeatReceived = false;
}
// send out the ping
new PlayerHeartbeatMessage().Send();
}
yield return new WaitForSecondsRealtime(3);
yield return new WaitForSecondsRealtime(10);
}
}
}
}