Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handshake before spawning players >:) #884

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions Assets/Scripts/Control&Input/ItemSelectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,12 @@
using Mirror;
using UnityEngine;

internal struct ClientReadyMessage : NetworkMessage
public class ItemSelectManager : NetworkBehaviour
{
}
private struct ClientReadyMessage : NetworkMessage { }

internal struct ClientNotReadyMessage : NetworkMessage
{
}
private struct ClientNotReadyMessage : NetworkMessage { }

public class ItemSelectManager : NetworkBehaviour
{
[SerializeField] private float graceTime = 1;

private List<ItemSelectMenu> itemSelectMenus;
Expand Down
204 changes: 134 additions & 70 deletions Assets/Scripts/Control&Input/RPRNetworkManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using UnityEngine.SceneManagement;

// TODO consider splitting this into match-specific state and general player metadata
// TODO also consider sticking some of the metadata onto the playermanager/playeridentity component for ease of access...
public struct PlayerDetails
{
public uint id;
Expand Down Expand Up @@ -41,95 +42,102 @@ public PlayerConnectedMessage(int inputID, ulong steamID = 0)
public ulong steamID;
}

public struct PlayerLeftMessage : NetworkMessage
{
public PlayerLeftMessage(uint id)
{
this.id = id;
}

public uint id;
public enum PlayerType
{
Local,
AI,
Remote
}

public struct RulesetMessage : NetworkMessage
public class RPRNetworkManager : NetworkManager
{
public RulesetMessage(Ruleset ruleset)
#region Messages
private struct PlayerLeftMessage : NetworkMessage
{
this.ruleset = ruleset.ToNetworkRuleset();
public PlayerLeftMessage(uint id)
{
this.id = id;
}

public uint id;
}
public NetworkRuleset ruleset;
}

public struct InitialPlayerDetailsMessage : NetworkMessage
{
public InitialPlayerDetailsMessage(PlayerDetails details)
private struct RulesetMessage : NetworkMessage
{
this.details = details;
public RulesetMessage(Ruleset ruleset)
{
this.ruleset = ruleset.ToNetworkRuleset();
}
public NetworkRuleset ruleset;
}
public PlayerDetails details;
}

public struct UpdatedPlayerDetailsMessage : NetworkMessage
{
public UpdatedPlayerDetailsMessage(PlayerDetails details)
private struct InitialPlayerDetailsMessage : NetworkMessage
{
this.details = details;
public InitialPlayerDetailsMessage(PlayerDetails details)
{
this.details = details;
}
public PlayerDetails details;
}
public PlayerDetails details;
}

public struct UpdateLoadoutMessage : NetworkMessage
{
public UpdateLoadoutMessage(uint id, string body, string barrel, string extension)
private struct UpdatedPlayerDetailsMessage : NetworkMessage
{
this.id = id;
this.body = body;
this.barrel = barrel;
this.extension = extension;
public UpdatedPlayerDetailsMessage(PlayerDetails details)
{
this.details = details;
}
public PlayerDetails details;
}
public uint id;
public string body;
public string barrel;
public string extension;
}

public struct StartMatchMessage : NetworkMessage { }

public struct SpawnPlayerMessage : NetworkMessage
{
public SpawnPlayerMessage(uint id, PlayerType type)
private struct UpdateLoadoutMessage : NetworkMessage
{
this.id = id;
this.type = type;
public UpdateLoadoutMessage(uint id, string body, string barrel, string extension)
{
this.id = id;
this.body = body;
this.barrel = barrel;
this.extension = extension;
}
public uint id;
public string body;
public string barrel;
public string extension;
}

public uint id;
public PlayerType type;
}
private struct StartMatchMessage : NetworkMessage { }

public struct InitializePlayerMessage : NetworkMessage
{
public InitializePlayerMessage(uint id, Vector3 position, Quaternion rotation)
private struct ClientReadyMessage : NetworkMessage { }

private struct AllClientsReadyMessage : NetworkMessage { }

private struct SpawnPlayerMessage : NetworkMessage
{
this.id = id;
this.position = position;
this.rotation = rotation;
public SpawnPlayerMessage(uint id)
{
this.id = id;
}

public uint id;
}

public uint id;
public Vector3 position;
public Quaternion rotation;
}
private struct InitializePlayerMessage : NetworkMessage
{
public InitializePlayerMessage(uint id, Vector3 position, Quaternion rotation)
{
this.id = id;
this.position = position;
this.rotation = rotation;
}

public enum PlayerType
{
Local,
AI,
Remote
}
public uint id;
public Vector3 position;
public Quaternion rotation;
}
#endregion;

#region State

public class RPRNetworkManager : NetworkManager
{
private const int FPSPlayerPrefabIndex = 0;
private const int BiddingPlayerPrefabIndexOffset = 1;
private const int AIFPSPlayerPrefabIndex = 2;
Expand All @@ -146,6 +154,8 @@ public class RPRNetworkManager : NetworkManager
private static bool isInMatch;
public static bool IsInMatch => isInMatch;

private static bool allClientsAreReady;

private static Dictionary<uint, PlayerDetails> players = new();
public static int NumPlayers => players.Count;
public static int NumAvailableSlots => Mathf.Max(0, MaxPlayers - players.Count);
Expand All @@ -163,6 +173,7 @@ public class RPRNetworkManager : NetworkManager
/// </summary>
private static List<NetworkConnectionToClient> connections = new();
private static Dictionary<int, List<uint>> playersForConnection = new();
private static Dictionary<int, bool> readinessForConnection = new();
private static List<uint> connectedPlayers = new();
public static ReadOnlyCollection<NetworkConnectionToClient> Connections;

Expand All @@ -177,9 +188,14 @@ public class RPRNetworkManager : NetworkManager
public GamestateEvent OnMatchStart;
public GamestateEvent OnMatchEnd;

#endregion

#region Initializing

private void ResetState()
{
isInMatch = false;
allClientsAreReady = false;
playerIndex = 0;
players = new();
playerInstances = new();
Expand All @@ -190,22 +206,24 @@ private void ResetState()
connections = new();
connectedPlayers = new();
playersForConnection = new();
readinessForConnection = new();
Connections = new(connections);
}

public override void OnStartServer()
{
NetworkServer.RegisterHandler<PlayerConnectedMessage>(OnSpawnPlayerInput);
NetworkServer.RegisterHandler<UpdateLoadoutMessage>(OnReceiveUpdateLoadout);
NetworkServer.RegisterHandler<UpdateLoadoutMessage>(OnReceiveUpdatedLoadout);
NetworkServer.RegisterHandler<ClientReadyMessage>(OnClientReady);

ResetState();
}

#region Player joining

public override void OnClientConnect()
{
base.OnClientConnect();
NetworkClient.RegisterHandler<AllClientsReadyMessage>(OnAllClientsReady);
NetworkClient.RegisterHandler<StartMatchMessage>(OnStartMatch);
NetworkClient.RegisterHandler<PlayerLeftMessage>(OnPlayerLeft);
NetworkClient.RegisterHandler<InitialPlayerDetailsMessage>(OnReceivePlayerDetails);
Expand All @@ -220,6 +238,10 @@ public override void OnClientConnect()
ResetState();
}

#endregion

#region Disconnecting

public override void OnServerDisconnect(NetworkConnectionToClient connection)
{
if (playersForConnection == null || !playersForConnection.ContainsKey(connection.connectionId))
Expand Down Expand Up @@ -291,6 +313,10 @@ private void OnPlayerLeft(PlayerLeftMessage message)
OnPlayerRemoved?.Invoke(playerDetails);
}

#endregion

#region Network startup

public void JoinLobby(string address = "127.0.0.1")
{
if (NetworkServer.active)
Expand Down Expand Up @@ -346,6 +372,10 @@ private static IEnumerator WaitAndSwitchToTrainingMode()
MusicTrackManager.Singleton.SwitchTo(MusicType.Tutorial);
}

#endregion

#region Match start

// TODO custom method for leaving training mode :)
// TODO handle leaving of match/lobby better

Expand All @@ -369,6 +399,10 @@ private void OnStartMatch(StartMatchMessage message)
LoadingScreen.Singleton.Show(FindObjectsByType<Camera>(FindObjectsSortMode.None).Where(camera => camera.gameObject.activeInHierarchy && camera.enabled == true).First());
}

#endregion

#region Joining

private void RefuseConnection(NetworkConnectionToClient connection)
{
// Don't refuse existing connections
Expand Down Expand Up @@ -631,7 +665,7 @@ public void UpdateLoadout()
}
}

private void OnReceiveUpdateLoadout(NetworkConnectionToClient connection, UpdateLoadoutMessage message)
private void OnReceiveUpdatedLoadout(NetworkConnectionToClient connection, UpdateLoadoutMessage message)
{
if (!players.TryGetValue(message.id, out var playerDetails))
return;
Expand All @@ -646,6 +680,7 @@ private void OnReceiveUpdateLoadout(NetworkConnectionToClient connection, Update

public override void OnClientChangeScene(string newSceneName, SceneOperation sceneOperation, bool customHandling)
{
allClientsAreReady = false;
var originalSceneName = SceneManager.GetActiveScene().name;
switch (newSceneName)
{
Expand All @@ -672,15 +707,43 @@ public override void OnClientChangeScene(string newSceneName, SceneOperation sce
StartCoroutine(SendSpawnRequestsAfterSceneLoad(originalSceneName));
}

#endregion

#region Start of round handshake

private void OnClientReady(NetworkConnectionToClient connection, ClientReadyMessage _)
{
readinessForConnection[connection.connectionId] = true;
if (Connections.All(c => readinessForConnection.TryGetValue(c.connectionId, out var isReady) && isReady))
NetworkServer.SendToAll(new AllClientsReadyMessage());
}

private void OnAllClientsReady(AllClientsReadyMessage _)
{
Debug.Log("yea we all ready");
allClientsAreReady = true;
}

private IEnumerator SendSpawnRequestsAfterSceneLoad(string originalSceneName)
{
readinessForConnection = new();
allClientsAreReady = false;

while (SceneManager.GetActiveScene().name == originalSceneName)
yield return null;

Debug.Log("yeah I sent msg");

NetworkClient.Send(new ClientReadyMessage());

// Wait for ready msg from clients!
while (!allClientsAreReady)
yield return null;

// Spawn players for our inputs (and bots)
foreach (var id in localPlayerIds)
{
NetworkClient.Send(new SpawnPlayerMessage(id, PlayerType.Local));
NetworkClient.Send(new SpawnPlayerMessage(id));
}

if (!NetworkServer.active)
Expand All @@ -691,12 +754,12 @@ private IEnumerator SendSpawnRequestsAfterSceneLoad(string originalSceneName)
// (perhaps you could call the spawn methods directly?)
foreach (var p in players.Values.Where(p => p.type == PlayerType.AI))
{
NetworkClient.Send(new SpawnPlayerMessage(p.id, PlayerType.AI));
NetworkClient.Send(new SpawnPlayerMessage(p.id));
}

foreach (var p in players.Values.Where(p => p.type is PlayerType.Remote && !connectedPlayers.Contains(p.id)))
{
NetworkClient.Send(new SpawnPlayerMessage(p.id, PlayerType.Local));
NetworkClient.Send(new SpawnPlayerMessage(p.id));
}
}

Expand Down Expand Up @@ -892,6 +955,7 @@ private IEnumerator WaitAndInitializeFPSPlayer(InitializePlayerMessage message)
}

playerInstances[player.id] = player;
Debug.Log("finish init player!", player.gameObject);
}

#endregion
Expand Down
2 changes: 2 additions & 0 deletions Assets/Scripts/Gamestate/MatchController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,15 @@ private void LateUpdate()
[Server]
private void EndActiveRound()
{
Debug.Log("omg nei fredrik stopp (end active round fra server)");
roundTimer.OnTimerRunCompleted -= EndActiveRound;
EndActiveRoundRpc(LastRound.SummarizeRound());
}

[ClientRpc]
private void EndActiveRoundRpc(NetworkRound serverRound)
{
Debug.Log("end active round client");
rounds[^1].UpdateFromSummary(serverRound);

isRoundInProgress = false;
Expand Down