#nullable enable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Barotrauma.Extensions; using Barotrauma.Steam; namespace Barotrauma.Networking; readonly record struct ConnectCommand( Option NameAndP2PEndpointsOption, Option NameAndLidgrenEndpointOption, Option SteamLobbyIdOption) { public bool IsClientConnectedToEndpoint() { if (GameMain.Client?.ClientPeer == null) { return false; } if (NameAndP2PEndpointsOption.TryUnwrap(out var nameAndP2PEndpoints)) { if (nameAndP2PEndpoints.Endpoints.Any(e => e.Equals(GameMain.Client.ClientPeer.ServerEndpoint))) { return true; } } if (NameAndLidgrenEndpointOption.TryUnwrap(out var nameAndLidgrenEndpoint)) { if (nameAndLidgrenEndpoint.Endpoint.Equals(GameMain.Client.ClientPeer.ServerEndpoint)) { return true; } } if (SteamLobbyIdOption.TryUnwrap(out var steamLobbyId)) { if (SteamManager.CurrentLobbyID == steamLobbyId.Value) { return true; } } return false; } public readonly record struct NameAndP2PEndpoints( string ServerName, ImmutableArray Endpoints); public readonly record struct NameAndLidgrenEndpoint( string ServerName, LidgrenEndpoint Endpoint); public readonly record struct SteamLobbyId(ulong Value); public ConnectCommand(string serverName, Endpoint endpoint) : this( NameAndP2PEndpointsOption: endpoint is P2PEndpoint p2pEndpoint ? Option.Some(new NameAndP2PEndpoints(ServerName: serverName, p2pEndpoint.ToEnumerable().ToImmutableArray())) : Option.None, NameAndLidgrenEndpointOption: endpoint is LidgrenEndpoint lidgrenEndpoint ? Option.Some(new NameAndLidgrenEndpoint(ServerName: serverName, lidgrenEndpoint)) : Option.None, SteamLobbyIdOption: Option.None) { } public ConnectCommand(string serverName, ImmutableArray endpoints) : this( NameAndP2PEndpointsOption: Option.Some(new NameAndP2PEndpoints(ServerName: serverName, Endpoints: endpoints)), NameAndLidgrenEndpointOption: Option.None, SteamLobbyIdOption: Option.None) { } public ConnectCommand(string serverName, LidgrenEndpoint endpoint) : this( NameAndP2PEndpointsOption: Option.None, NameAndLidgrenEndpointOption: Option.Some(new NameAndLidgrenEndpoint(ServerName: serverName, Endpoint: endpoint)), SteamLobbyIdOption: Option.None) { } public ConnectCommand(SteamLobbyId lobbyId) : this( NameAndP2PEndpointsOption: Option.None, NameAndLidgrenEndpointOption: Option.None, SteamLobbyIdOption: Option.Some(lobbyId)) { } public static Option Parse(string str) => Parse(ToolBox.SplitCommand(str)); public static Option Parse(IReadOnlyList? args) { if (args == null || args.Count < 2) { return Option.None; } if (args[0].Equals("-connect", StringComparison.OrdinalIgnoreCase)) { if (args.Count < 3) { return Option.None; } var serverName = args[1]; var endpointStrs = args[2].Split(","); var endpoints = endpointStrs.Select(Endpoint.Parse).NotNone().ToImmutableArray(); if (endpoints.Length != endpointStrs.Length) { return Option.None; } if (endpoints.All(e => e is P2PEndpoint)) { return Option.Some( new ConnectCommand(serverName, endpoints.Cast().ToImmutableArray())); } else if (endpoints.Length == 1 && endpoints[0] is LidgrenEndpoint lidgrenEndpoint) { return Option.Some( new ConnectCommand(serverName, lidgrenEndpoint)); } return Option.None; } else if (args[0].Equals("+connect_lobby", StringComparison.OrdinalIgnoreCase)) { return UInt64.TryParse(args[1], out var lobbyId) ? Option.Some(new ConnectCommand(new SteamLobbyId(lobbyId))) : Option.None; } return Option.None; } public override string ToString() { if (SteamLobbyIdOption.TryUnwrap(out var steamLobbyId)) { return $"+connect_lobby {steamLobbyId.Value}"; } if (NameAndP2PEndpointsOption.TryUnwrap(out var nameAndP2PEndpoints)) { var escapedName = nameAndP2PEndpoints.ServerName.Replace("\"", "\\\""); var escapedEndpoints = nameAndP2PEndpoints.Endpoints.Select(e => e.StringRepresentation).JoinEscaped(','); return $"-connect \"{escapedName}\" {escapedEndpoints}"; } if (NameAndLidgrenEndpointOption.TryUnwrap(out var nameAndLidgrenEndpoint)) { var escapedName = nameAndLidgrenEndpoint.ServerName.Replace("\"", "\\\""); var endpoint = nameAndLidgrenEndpoint.Endpoint.StringRepresentation; return $"-connect \"{escapedName}\" {endpoint}"; } return ""; } }