164 lines
6.4 KiB
C#
164 lines
6.4 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using NitroxClient.Communication.Abstract;
|
|
using NitroxClient.Communication.MultiplayerSession.ConnectionState;
|
|
using NitroxClient.GameLogic;
|
|
using NitroxModel.DataStructures;
|
|
using NitroxModel.Helper;
|
|
using NitroxModel.MultiplayerSession;
|
|
using NitroxModel.Packets;
|
|
using NitroxModel.Serialization;
|
|
|
|
namespace NitroxClient.Communication.MultiplayerSession
|
|
{
|
|
public class MultiplayerSessionManager : IMultiplayerSession, IMultiplayerSessionConnectionContext
|
|
{
|
|
private static readonly Task initSerializerTask;
|
|
|
|
static MultiplayerSessionManager()
|
|
{
|
|
initSerializerTask = Task.Run(Packet.InitSerializer);
|
|
}
|
|
|
|
public IClient Client { get; }
|
|
public string IpAddress { get; private set; }
|
|
public int ServerPort { get; private set; }
|
|
public MultiplayerSessionPolicy SessionPolicy { get; private set; }
|
|
public PlayerSettings PlayerSettings { get; private set; }
|
|
public AuthenticationContext AuthenticationContext { get; private set; }
|
|
public IMultiplayerSessionConnectionState CurrentState { get; private set; }
|
|
public MultiplayerSessionReservation Reservation { get; private set; }
|
|
|
|
public MultiplayerSessionManager(IClient client)
|
|
{
|
|
Log.Info("Initializing MultiplayerSessionManager...");
|
|
Client = client;
|
|
CurrentState = new Disconnected();
|
|
}
|
|
|
|
// Testing entry point
|
|
internal MultiplayerSessionManager(IClient client, IMultiplayerSessionConnectionState initialState)
|
|
{
|
|
Client = client;
|
|
CurrentState = initialState;
|
|
}
|
|
|
|
public event MultiplayerSessionConnectionStateChangedEventHandler ConnectionStateChanged;
|
|
|
|
public async Task ConnectAsync(string ipAddress, int port)
|
|
{
|
|
IpAddress = ipAddress;
|
|
ServerPort = port;
|
|
await initSerializerTask;
|
|
await CurrentState.NegotiateReservationAsync(this);
|
|
}
|
|
|
|
public void ProcessSessionPolicy(MultiplayerSessionPolicy policy)
|
|
{
|
|
SessionPolicy = policy;
|
|
NitroxConsole.DisableConsole = SessionPolicy.DisableConsole;
|
|
Version localVersion = NitroxEnvironment.Version;
|
|
NitroxVersion nitroxVersion = new(localVersion.Major, localVersion.Minor);
|
|
switch (nitroxVersion.CompareTo(SessionPolicy.NitroxVersionAllowed))
|
|
{
|
|
case -1:
|
|
Log.Error($"Client is out of date. Server: {SessionPolicy.NitroxVersionAllowed}, Client: {localVersion}");
|
|
Log.InGame(Language.main.Get("Nitrox_OutOfDateClient")
|
|
.Replace("{serverVersion}", SessionPolicy.NitroxVersionAllowed.ToString())
|
|
.Replace("{localVersion}", localVersion.ToString()));
|
|
CurrentState.Disconnect(this);
|
|
return;
|
|
case 1:
|
|
Log.Error($"Server is out of date. Server: {SessionPolicy.NitroxVersionAllowed}, Client: {localVersion}");
|
|
Log.InGame(Language.main.Get("Nitrox_OutOfDateServer")
|
|
.Replace("{serverVersion}", SessionPolicy.NitroxVersionAllowed.ToString())
|
|
.Replace("{localVersion}", localVersion.ToString()));
|
|
CurrentState.Disconnect(this);
|
|
return;
|
|
}
|
|
|
|
CurrentState.NegotiateReservationAsync(this);
|
|
}
|
|
|
|
public void RequestSessionReservation(PlayerSettings playerSettings, AuthenticationContext authenticationContext)
|
|
{
|
|
// If a reservation has already been sent (in which case the client is enqueued in the join queue)
|
|
if (CurrentState.CurrentStage == MultiplayerSessionConnectionStage.AWAITING_SESSION_RESERVATION)
|
|
{
|
|
Log.Info("Waiting in join queue…");
|
|
Log.InGame(Language.main.Get("Nitrox_Waiting"));
|
|
return;
|
|
}
|
|
|
|
PlayerSettings = playerSettings;
|
|
AuthenticationContext = authenticationContext;
|
|
CurrentState.NegotiateReservationAsync(this);
|
|
}
|
|
|
|
public void ProcessReservationResponsePacket(MultiplayerSessionReservation reservation)
|
|
{
|
|
if (reservation.ReservationState == MultiplayerSessionReservationState.ENQUEUED_IN_JOIN_QUEUE)
|
|
{
|
|
Log.Info("Waiting in join queue…");
|
|
Log.InGame(Language.main.Get("Nitrox_Waiting"));
|
|
return;
|
|
}
|
|
|
|
Reservation = reservation;
|
|
CurrentState.NegotiateReservationAsync(this);
|
|
}
|
|
|
|
public void JoinSession()
|
|
{
|
|
CurrentState.JoinSession(this);
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
if (CurrentState.CurrentStage != MultiplayerSessionConnectionStage.DISCONNECTED)
|
|
{
|
|
CurrentState.Disconnect(this);
|
|
}
|
|
}
|
|
|
|
public bool Send<T>(T packet) where T : Packet
|
|
{
|
|
if (!PacketSuppressor<T>.IsSuppressed)
|
|
{
|
|
Client.Send(packet);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void UpdateConnectionState(IMultiplayerSessionConnectionState sessionConnectionState)
|
|
{
|
|
Validate.NotNull(sessionConnectionState);
|
|
|
|
string fromStage = CurrentState == null ? "null" : CurrentState.CurrentStage.ToString();
|
|
string username = AuthenticationContext == null ? "" : AuthenticationContext.Username;
|
|
Log.Debug($"Updating session stage from '{fromStage}' to '{sessionConnectionState.CurrentStage}' for '{username}'");
|
|
|
|
CurrentState = sessionConnectionState;
|
|
|
|
// Last connection state changed will not have any handlers
|
|
ConnectionStateChanged?.Invoke(CurrentState);
|
|
|
|
if (sessionConnectionState.CurrentStage == MultiplayerSessionConnectionStage.SESSION_RESERVED)
|
|
{
|
|
Log.PlayerName = username;
|
|
}
|
|
}
|
|
|
|
public void ClearSessionState()
|
|
{
|
|
IpAddress = null;
|
|
ServerPort = ServerList.DEFAULT_PORT;
|
|
SessionPolicy = null;
|
|
PlayerSettings = null;
|
|
AuthenticationContext = null;
|
|
Reservation = null;
|
|
}
|
|
}
|
|
}
|