diff --git a/MSBuild/Robust.Engine.Version.props b/MSBuild/Robust.Engine.Version.props index a0cf8993c3..affd67b860 100644 --- a/MSBuild/Robust.Engine.Version.props +++ b/MSBuild/Robust.Engine.Version.props @@ -1,4 +1,4 @@ - - - 260.2.0 - + + + 0.2.0 + diff --git a/README.md b/README.md index a8d9fc8c08..20410395f2 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -![Robust Toolbox](https://raw.githubusercontent.com/space-wizards/asset-dump/3dd3078e49e3a7e06709a6e0fc6e3223d8d44ca2/robust.png) +Supermatter Engine is a game engine primarily being developed for [Space Station 14](https://github.com/Simple-Station/Einstein-Engines). -Robust Toolbox is an engine primarily being developed for [Space Station 14](https://github.com/space-wizards/space-station-14), although we're working on making it usable for both [singleplayer](https://github.com/space-wizards/RobustToolboxTemplateSingleplayer) and [multiplayer](https://github.com/space-wizards/RobustToolboxTemplate) projects. - -Use the [content repo](https://github.com/space-wizards/space-station-14) for actual development, even if you're modifying the engine itself. +Use the [content repo](https://github.com/Simple-Station/Einstein-Engines) for actual development, even if you're modifying the engine itself. ## Project Links -[Website](https://spacestation14.io/) | [Discord](https://discord.gg/t2jac3p) | [Forum](https://forum.spacestation14.io/) | [Steam](https://store.steampowered.com/app/1255460/Space_Station_14/) | [Standalone Download](https://spacestation14.io/about/nightlies/) +[Website](https://simplestation.org/) | [Discord](https://discord.gg/X4QEXxUrsJ) | [Steam](https://store.steampowered.com/app/1255460/Space_Station_14/) | [Standalone Download](https://spacestation14.io/about/nightlies/) ## Documentation/Wiki @@ -14,12 +12,12 @@ The [wiki](https://docs.spacestation14.io/) has documentation on SS14s content, ## Contributing -We are happy to accept contributions from anybody. Get in Discord or IRC if you want to help. We've got a [list of issues](https://github.com/space-wizards/RobustToolbox/issues) that need to be done and anybody can pick them up. Don't be afraid to ask for help either! +We are happy to accept contributions from anybody. It is recommended to join our Discord if you want to help. We've got a [list of issues](https://github.com/Simple-Station/SupermatterEngine/issues) that need to be done and anybody can pick them up. Don't be afraid to ask for help either! ## Building -This repository is the **engine** part of SS14. It's the base engine all SS14 servers will be built on. As such, it does not start on its own: it needs the [content repo](https://github.com/space-wizards/space-station-14). Think of Robust Toolbox as BYOND in the context of Space Station 13. +This repository is the **engine** part of SS14. It's an engine SS14 servers are built on. As such, it does not start on its own: it needs the [content repo](https://github.com/Simple-Station/Einstein-Engines). Think of SME as BYOND in the context of Space Station 13. ## Legal Info -See [legal.md](https://github.com/space-wizards/RobustToolbox/blob/master/legal.md) for licenses and copyright. +See [legal.md](https://github.com/Simple-Station/SupermatterEngine/blob/master/legal.md) for licenses and copyright. diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 609dafe116..39b0727d6a 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -54,6 +54,15 @@ END TEMPLATE--> *None yet* +## 0.2.0 + + +## 0.1.0 + + +## 0.1.0 + + ## 260.2.0 ### New features diff --git a/Robust.Client/Console/Commands/LauncherAuthCommand.cs b/Robust.Client/Console/Commands/LauncherAuthCommand.cs index 5fa5c51925..88c1fb1edb 100644 --- a/Robust.Client/Console/Commands/LauncherAuthCommand.cs +++ b/Robust.Client/Console/Commands/LauncherAuthCommand.cs @@ -5,6 +5,7 @@ using Robust.Client.Utility; using Robust.Shared.Console; using Robust.Shared.IoC; +using Robust.Shared.Log; using Robust.Shared.Network; namespace Robust.Client.Console.Commands @@ -15,31 +16,61 @@ internal sealed class LauncherAuthCommand : LocalizedCommands [Dependency] private readonly IGameControllerInternal _gameController = default!; public override string Command => "launchauth"; + public override string Help => "Usage: launchauth "; public override void Execute(IConsoleShell shell, string argStr, string[] args) { - var wantName = args.Length > 0 ? args[0] : null; + string? username = null; + string? serverId = null; + string? serverUrl = null; + if (args.Length > 0) + username = args[0]; + if (args.Length > 1) + serverId = args[1]; + if (args.Length > 2) + serverUrl = args[2]; var basePath = UserDataDir.GetRootUserDataDir(_gameController); var launcherDirName = Environment.GetEnvironmentVariable("SS14_LAUNCHER_APPDATA_NAME") ?? "launcher"; var dbPath = Path.Combine(basePath, launcherDirName, "settings.db"); -#if USE_SYSTEM_SQLITE - SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); -#endif + #if USE_SYSTEM_SQLITE + SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); + #endif using var con = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly"); con.Open(); using var cmd = con.CreateCommand(); - cmd.CommandText = "SELECT UserId, UserName, Token FROM Login WHERE Expires > datetime('NOW')"; + cmd.CommandText = "SELECT UserId, UserName, Token, Server, ServerUrl FROM Login WHERE Expires > datetime('NOW')"; - if (wantName != null) + if (username != null) { cmd.CommandText += " AND UserName = @userName"; - cmd.Parameters.AddWithValue("@userName", wantName); + cmd.Parameters.AddWithValue("@userName", username); } - cmd.CommandText += " LIMIT 1;"; + if (serverId != null) + { + cmd.CommandText += " AND Server = @serverId"; + cmd.Parameters.AddWithValue("@serverId", serverId); + if (serverId == IAuthManager.CustomServerId) + { + if (serverUrl == null) + { + shell.WriteLine("Custom server requires a URL"); + return; + } + cmd.CommandText += " AND ServerUrl = @serverUrl"; + cmd.Parameters.AddWithValue("@serverUrl", serverUrl); + } + else if (serverUrl != null) + { + shell.WriteLine("Server URL is only valid for custom servers"); + return; + } + } + + cmd.CommandText += " LIMIT 1;"; using var reader = cmd.ExecuteReader(); if (!reader.Read()) @@ -51,11 +82,13 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args) var userId = Guid.Parse(reader.GetString(0)); var userName = reader.GetString(1); var token = reader.GetString(2); + serverUrl = reader.GetString(4); _auth.Token = token; _auth.UserId = new NetUserId(userId); + _auth.UserServer = new("unset", new(serverUrl)); - shell.WriteLine($"Logged into account {userName}"); + shell.WriteLine($"Logged into account {userName}@{reader.GetString(3)} ({serverUrl})"); } } } diff --git a/Robust.Client/GameControllerOptions.cs b/Robust.Client/GameControllerOptions.cs index d386b39066..fdb0b2b2da 100644 --- a/Robust.Client/GameControllerOptions.cs +++ b/Robust.Client/GameControllerOptions.cs @@ -1,3 +1,4 @@ +using System; using Robust.Shared; using Robust.Shared.Utility; @@ -19,7 +20,7 @@ public sealed class GameControllerOptions /// /// Name the userdata directory will have. /// - public string UserDataDirectoryName { get; init; } = "Space Station 14"; + public string UserDataDirectoryName { get; init; } = Environment.GetEnvironmentVariable("SS14_LAUNCHER_DATADIR") ?? "SimpleStation14"; /// /// Name of the configuration file in the user data directory. diff --git a/Robust.Server/Console/Commands/PlayerCommands.cs b/Robust.Server/Console/Commands/PlayerCommands.cs index 6f504d844b..623cdec53b 100644 --- a/Robust.Server/Console/Commands/PlayerCommands.cs +++ b/Robust.Server/Console/Commands/PlayerCommands.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using Robust.Server.Player; +using Robust.Shared.Configuration; using Robust.Shared.Console; using Robust.Shared.IoC; using Robust.Shared.Network; @@ -11,6 +12,7 @@ namespace Robust.Server.Console.Commands public sealed class ListPlayers : LocalizedCommands { [Dependency] private readonly IPlayerManager _players = default!; + [Dependency] private readonly IConfigurationManager _config = default!; public override string Command => "listplayers"; public override void Execute(IConsoleShell shell, string argStr, string[] args) @@ -22,17 +24,18 @@ public override void Execute(IConsoleShell shell, string argStr, string[] args) var sb = new StringBuilder(); var players = _players.Sessions; - sb.AppendLine($"{"Player Name",20} {"Status",12} {"Playing Time",14} {"Ping",9} {"IP EndPoint",20}"); - sb.AppendLine("-------------------------------------------------------------------------------"); + sb.AppendLine($"{"Player Name",26} {"Auth Server",16} {"Status",12} {"Playing Time",14} {"Ping",9} {"IP EndPoint",20}"); + sb.AppendLine(new('-', 26 + 16 + 12 + 14 + 9 + 20)); foreach (var p in players) { - sb.AppendLine(string.Format("{4,20} {1,12} {2,14:hh\\:mm\\:ss} {3,9} {0,20}", - p.Channel.RemoteEndPoint, + sb.AppendLine(string.Format("{0,26} {1,16} {2,12} {3,14:hh\\:mm\\:ss} {4,9} {5,20}", + p.Name, + AuthServer.GetServerFromCVarListByUrl(_config, p.Channel.UserData.AuthServer)?.Id, p.Status.ToString(), DateTime.UtcNow - p.ConnectedTime, p.Channel.Ping + "ms", - p.Name)); + p.Channel.RemoteEndPoint)); } shell.WriteLine(sb.ToString()); diff --git a/Robust.Server/ServerStatus/StatusHost.Handlers.cs b/Robust.Server/ServerStatus/StatusHost.Handlers.cs index 0a52403b4a..a5fc41b789 100644 --- a/Robust.Server/ServerStatus/StatusHost.Handlers.cs +++ b/Robust.Server/ServerStatus/StatusHost.Handlers.cs @@ -5,6 +5,7 @@ using System.Text.Json.Nodes; using System.Web; using Robust.Shared; +using Robust.Shared.Network; using Robust.Shared.Utility; namespace Robust.Server.ServerStatus @@ -39,25 +40,29 @@ private async Task HandleStatus(IStatusHandlerContext context) return false; } + var buildInfo = GameBuildInformation.GetBuildInfoFromConfig(_cfg); + var jObject = new JsonObject { // We need to send at LEAST name and player count to have the launcher work with us. // Tags is optional technically but will be necessary practically for future organization. // Content can override these if it wants (e.g. stealthmins). ["name"] = _serverNameCache, - ["players"] = _playerManager.PlayerCount + ["players"] = _playerManager.PlayerCount, + ["engine_type"] = buildInfo.EngineType, + ["engine"] = buildInfo.EngineVersion, }; - var tagsCache = _serverTagsCache; - if (tagsCache != null) - { - var tags = new JsonArray(); - foreach (var tag in tagsCache) - { - tags.Add(tag); - } - jObject["tags"] = tags; - } + var tags = new JsonArray(); + foreach (var tag in _serverTagsCache) + tags.Add(tag); + jObject["tags"] = tags; + + // Can't cast :( + var auths = new JsonArray(); + foreach (var auth in AuthServer.FromCVarList(_cfg).Select(s => s.AuthUrl.AbsoluteUri)) + auths.Add(auth); + jObject["auth_methods"] = auths; OnStatusRequest?.Invoke(jObject); @@ -88,12 +93,16 @@ private async Task HandleInfo(IStatusHandlerContext context) buildInfo = GetExternalBuildInfo(); } + var logins = new JsonArray(); + foreach (var authServer in AuthServer.FromCVarList(_cfg)) + logins.Add(authServer.AuthUrl); var authInfo = new JsonObject { ["mode"] = _netManager.Auth.ToString(), ["public_key"] = _netManager.CryptoPublicKey != null ? Convert.ToBase64String(_netManager.CryptoPublicKey) - : null + : null, + ["login_urls"] = logins, }; var jObject = new JsonObject @@ -134,6 +143,7 @@ private JsonObject GetExternalBuildInfo() return new JsonObject { + ["engine_type"] = buildInfo.EngineType, ["engine_version"] = buildInfo.EngineVersion, ["fork_id"] = buildInfo.ForkId, ["version"] = buildInfo.Version, @@ -160,6 +170,7 @@ private JsonObject GetExternalBuildInfo() } return new JsonObject { + ["engine_type"] = _cfg.GetCVar(CVars.BuildEngineType), ["engine_version"] = _cfg.GetCVar(CVars.BuildEngineVersion), ["fork_id"] = fork, ["version"] = acm.ManifestHash, diff --git a/Robust.Shared/CVars.cs b/Robust.Shared/CVars.cs index e68e8ee361..c673b8f3c3 100644 --- a/Robust.Shared/CVars.cs +++ b/Robust.Shared/CVars.cs @@ -669,6 +669,12 @@ protected CVars() * BUILD */ + /// + /// Engine type the launcher needs to connect to this server. + /// + public static readonly CVarDef BuildEngineType = + CVarDef.Create("build.engine_type", "Supermatter"); + /// /// Engine version that launcher needs to connect to this server. /// @@ -942,12 +948,12 @@ protected CVars() public static readonly CVarDef AuthAllowLocal = CVarDef.Create("auth.allowlocal", true, CVar.SERVERONLY); - // Only respected on server, client goes through IAuthManager for security. /// - /// Authentication server address. + /// List of comma separated URLs to use as whitelisted authentication servers /// - public static readonly CVarDef AuthServer = - CVarDef.Create("auth.server", AuthManager.DefaultAuthServer, CVar.SERVERONLY); + /// "Space-Wizards@https://auth.spacestation14.com/,SimpleStation@https://auth.simplestation.org/" + public static readonly CVarDef AuthServers = + CVarDef.Create("auth.servers", AuthServer.ToStringList(AuthManager.DefaultAuthServers), CVar.REPLICATED); /* * RENDERING diff --git a/Robust.Shared/Network/AuthManager.cs b/Robust.Shared/Network/AuthManager.cs index ea2250e891..7a1c1c5888 100644 --- a/Robust.Shared/Network/AuthManager.cs +++ b/Robust.Shared/Network/AuthManager.cs @@ -1,5 +1,9 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Robust.Shared.Configuration; + namespace Robust.Shared.Network { @@ -10,8 +14,12 @@ namespace Robust.Shared.Network /// internal interface IAuthManager { + public const string CustomServerId = "Custom"; + public const string DefaultServerUrl = "https://auth.spacestation14.com/"; + NetUserId? UserId { get; set; } - string? Server { get; set; } + AuthServer UserServer { get; set; } + HashSet Servers { get; set; } string? Token { get; set; } string? PubKey { get; set; } @@ -23,12 +31,54 @@ internal interface IAuthManager void LoadFromEnv(); } + public sealed class AuthServer(string id, Uri authUrl) + { + public string Id { get; } = id; + public Uri AuthUrl { get; } = authUrl; + + /// Returns a string representation of the auth server + /// "Space-Wizards@https://auth.spacestation14.com/" + public override string ToString() => $"{Id}@{AuthUrl}"; + + + /// Returns a string representation of a list of auth servers + /// "Space-Wizards@https://auth.spacestation14.com/,SimpleStation@https://auth.simplestation.org/" + public static string ToStringList(HashSet servers) => string.Join(',', servers.Select(s => s.ToString())); + + /// Takes a representation of an auth server and returns an AuthServer object + /// "Space-Wizards@https://auth.spacestation14.com/" + public static AuthServer FromString(string str) + { + var parts = str.Split('@'); + if (parts.Length != 2) + throw new ArgumentException($"Invalid auth server string: {str}"); + + return new(parts[0], new(parts[1])); + } + + /// Takes a list of auth server representations and returns a HashSet of AuthServer objects + /// "Space-Wizards@https://auth.spacestation14.com/,SimpleStation@https://auth.simplestation.org/" + public static HashSet FromStringList(string str) => new(str.Split(',').Select(FromString)); + + public static HashSet FromCVarList(IConfigurationManager config) => FromStringList(config.GetCVar(CVars.AuthServers)); + + public static AuthServer? GetServerFromCVarListById(IConfigurationManager config, string id) => FromCVarList(config).FirstOrDefault(s => s.Id == id); + public static AuthServer? GetServerFromCVarListByUrl(IConfigurationManager config, Uri url) => FromCVarList(config).FirstOrDefault(s => s.AuthUrl == url); + public static AuthServer? GetServerFromCVarListByUrl(IConfigurationManager config, string url) => FromCVarList(config).FirstOrDefault(s => s.AuthUrl.ToString() == url); + } + internal sealed class AuthManager : IAuthManager { - public const string DefaultAuthServer = "https://auth.spacestation14.com/"; + public static readonly AuthServer FallbackAuthServer = new("Space-Wizards", new("https://auth.spacestation14.com/")); + public static readonly HashSet DefaultAuthServers = new() + { + FallbackAuthServer, + new("SimpleStation", new("https://auth.simplestation.org/")), + }; public NetUserId? UserId { get; set; } - public string? Server { get; set; } = DefaultAuthServer; + public AuthServer UserServer { get; set; } = FallbackAuthServer; + public HashSet Servers { get; set; } = DefaultAuthServers; public string? Token { get; set; } public string? PubKey { get; set; } public bool AllowHwid { get; set; } = true; @@ -36,29 +86,22 @@ internal sealed class AuthManager : IAuthManager public void LoadFromEnv() { if (TryGetVar("ROBUST_AUTH_SERVER", out var server)) - { - Server = server; - } + UserServer = AuthServer.FromString("unset@" + server); + + if (TryGetVar("ROBUST_AUTH_SERVERS", out var servers)) + Servers = AuthServer.FromStringList(servers); if (TryGetVar("ROBUST_AUTH_USERID", out var userId)) - { UserId = new NetUserId(Guid.Parse(userId)); - } if (TryGetVar("ROBUST_AUTH_PUBKEY", out var pubKey)) - { PubKey = pubKey; - } if (TryGetVar("ROBUST_AUTH_TOKEN", out var token)) - { Token = token; - } if (TryGetVar("ROBUST_AUTH_ALLOW_HWID", out var allowHwid)) - { AllowHwid = allowHwid.Trim() == "1"; - } static bool TryGetVar(string var, [NotNullWhen(true)] out string? val) { diff --git a/Robust.Shared/Network/Messages/Handshake/MsgLoginStart.cs b/Robust.Shared/Network/Messages/Handshake/MsgLoginStart.cs index ca8d39755f..a29bd20474 100644 --- a/Robust.Shared/Network/Messages/Handshake/MsgLoginStart.cs +++ b/Robust.Shared/Network/Messages/Handshake/MsgLoginStart.cs @@ -16,6 +16,7 @@ internal sealed class MsgLoginStart : NetMessage public override MsgGroups MsgGroup => MsgGroups.Core; public string UserName; + public string AuthServer; public bool CanAuth; public bool NeedPubKey; public bool Encrypt; @@ -23,6 +24,7 @@ internal sealed class MsgLoginStart : NetMessage public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer serializer) { UserName = buffer.ReadString(); + AuthServer = buffer.ReadString(); CanAuth = buffer.ReadBoolean(); NeedPubKey = buffer.ReadBoolean(); Encrypt = buffer.ReadBoolean(); @@ -31,6 +33,7 @@ public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer serializer) { buffer.Write(UserName); + buffer.Write(AuthServer); buffer.Write(CanAuth); buffer.Write(NeedPubKey); buffer.Write(Encrypt); diff --git a/Robust.Shared/Network/Messages/Handshake/MsgLoginSuccess.cs b/Robust.Shared/Network/Messages/Handshake/MsgLoginSuccess.cs index 81a185e995..d815a56331 100644 --- a/Robust.Shared/Network/Messages/Handshake/MsgLoginSuccess.cs +++ b/Robust.Shared/Network/Messages/Handshake/MsgLoginSuccess.cs @@ -19,11 +19,12 @@ public override void ReadFromBuffer(NetIncomingMessage buffer, IRobustSerializer { var name = buffer.ReadString(); var id = buffer.ReadGuid(); + var authServer = buffer.ReadString(); var patreonTier = buffer.ReadString(); if (patreonTier.Length == 0) patreonTier = null; - UserData = new NetUserData(new NetUserId(id), name) {PatronTier = patreonTier}; + UserData = new(new(id), name, authServer) {PatronTier = patreonTier}; Type = (LoginType) buffer.ReadByte(); } @@ -31,6 +32,7 @@ public override void WriteToBuffer(NetOutgoingMessage buffer, IRobustSerializer { buffer.Write(UserData.UserName); buffer.Write(UserData.UserId); + buffer.Write(UserData.AuthServer); buffer.Write(UserData.PatronTier); buffer.Write((byte) Type); buffer.Write(new byte[100]); diff --git a/Robust.Shared/Network/NetManager.ClientConnect.cs b/Robust.Shared/Network/NetManager.ClientConnect.cs index 238bc9d0aa..129b429e00 100644 --- a/Robust.Shared/Network/NetManager.ClientConnect.cs +++ b/Robust.Shared/Network/NetManager.ClientConnect.cs @@ -127,7 +127,7 @@ private async Task CCDoHandshake( var encrypt = _config.GetCVar(CVars.NetEncrypt); var authToken = _authManager.Token; var pubKey = _authManager.PubKey; - var authServer = _authManager.Server; + var authServer = _authManager.UserServer; var userId = _authManager.UserId; var hasPubKey = !string.IsNullOrEmpty(pubKey); @@ -138,9 +138,10 @@ private async Task CCDoHandshake( var msgLogin = new MsgLoginStart { UserName = userNameRequest, + AuthServer = authServer.AuthUrl.ToString(), CanAuth = authenticate, NeedPubKey = !hasPubKey, - Encrypt = encrypt + Encrypt = encrypt, }; var outLoginMsg = peer.Peer.CreateMessage(); @@ -200,7 +201,7 @@ private async Task CCDoHandshake( } var joinReq = new JoinRequest(authHash, Base64Helpers.ToBase64Nullable(modernHwid)); - var request = new HttpRequestMessage(HttpMethod.Post, authServer + "api/session/join"); + var request = new HttpRequestMessage(HttpMethod.Post, authServer.AuthUrl + "api/session/join"); request.Content = JsonContent.Create(joinReq); request.Headers.Authorization = new AuthenticationHeaderValue("SS14Auth", authToken); var joinResp = await _http.Client.SendAsync(request, cancel); diff --git a/Robust.Shared/Network/NetManager.ServerAuth.cs b/Robust.Shared/Network/NetManager.ServerAuth.cs index a8eda20dc8..687fa46145 100644 --- a/Robust.Shared/Network/NetManager.ServerAuth.cs +++ b/Robust.Shared/Network/NetManager.ServerAuth.cs @@ -50,11 +50,11 @@ private async void HandleHandshake(NetPeerData peer, NetConnection connection) var isLocal = IPAddress.IsLoopback(ip) && _config.GetCVar(CVars.AuthAllowLocal); var canAuth = msgLogin.CanAuth; var needPk = msgLogin.NeedPubKey; - var authServer = _config.GetCVar(CVars.AuthServer); + var authServer = msgLogin.AuthServer; _logger.Verbose( $"{connection.RemoteEndPoint}: Received MsgLoginStart. " + - $"canAuth: {canAuth}, needPk: {needPk}, username: {msgLogin.UserName}, encrypt: {msgLogin.Encrypt}"); + $"canAuth: {canAuth}, needPk: {needPk}, username: {msgLogin.UserName}, auth server: {msgLogin.AuthServer}, encrypt: {msgLogin.Encrypt}"); _logger.Verbose( $"{connection.RemoteEndPoint}: Connection is specialized local? {isLocal} "); @@ -78,6 +78,13 @@ private async void HandleHandshake(NetPeerData peer, NetConnection connection) _logger.Verbose( $"{connection.RemoteEndPoint}: Initiating authentication"); + var servers = _authManager.Servers.Select(s => s.AuthUrl.ToString()).ToArray(); + if (!servers.Contains(authServer)) + { + connection.Disconnect($"Invalid or disallowed auth server {authServer}, needs to be one of {string.Join(", ", servers)}"); + return; + } + var verifyToken = new byte[4]; RandomNumberGenerator.Fill(verifyToken); var wantHwid = _config.GetCVar(CVars.NetHWId); @@ -168,7 +175,7 @@ private async void HandleHandshake(NetPeerData peer, NetConnection connection) legacyHwid = []; } - userData = new NetUserData(userId, joinedRespJson.UserData.UserName) + userData = new(userId, joinedRespJson.UserData.UserName, authServer) { PatronTier = joinedRespJson.UserData.PatronTier, HWId = legacyHwid, @@ -214,7 +221,7 @@ private async void HandleHandshake(NetPeerData peer, NetConnection connection) _logger.Verbose( $"{connection.RemoteEndPoint}: Assigned user ID: {userId}"); - userData = new NetUserData(userId, name) + userData = new(userId, name, authServer) { HWId = [], ModernHWIds = [] diff --git a/Robust.Shared/Network/NetUserData.cs b/Robust.Shared/Network/NetUserData.cs index 428ea3d96a..a76ea17aef 100644 --- a/Robust.Shared/Network/NetUserData.cs +++ b/Robust.Shared/Network/NetUserData.cs @@ -7,14 +7,11 @@ namespace Robust.Shared.Network /// /// Contains data about players returned from auth server. /// - public sealed record NetUserData + public sealed record NetUserData( + [property: ViewVariables] NetUserId UserId, + [property: ViewVariables] string UserName, + [property: ViewVariables] string AuthServer = IAuthManager.DefaultServerUrl) { - [ViewVariables] - public NetUserId UserId { get; } - - [ViewVariables] - public string UserName { get; } - [ViewVariables] public string? PatronTier { get; init; } @@ -37,12 +34,6 @@ public sealed record NetUserData /// public float Trust { get; init; } - public NetUserData(NetUserId userId, string userName) - { - UserId = userId; - UserName = userName; - } - public sealed override string ToString() { var stringBuilder = new StringBuilder(); diff --git a/Robust.Shared/Utility/GameBuildInformation.cs b/Robust.Shared/Utility/GameBuildInformation.cs index cd533b1cad..4bf766302d 100644 --- a/Robust.Shared/Utility/GameBuildInformation.cs +++ b/Robust.Shared/Utility/GameBuildInformation.cs @@ -7,6 +7,7 @@ internal sealed record GameBuildInformation( string? ZipHash, string? ZipDownload, string ForkId, + string EngineType, string Version, string? ManifestHash, string? ManifestUrl, @@ -18,6 +19,7 @@ public static GameBuildInformation GetBuildInfoFromConfig(IConfigurationManager var zipHash = cfg.GetCVar(CVars.BuildHash); var manifestHash = cfg.GetCVar(CVars.BuildManifestHash); var forkId = cfg.GetCVar(CVars.BuildForkId); + var engineType = cfg.GetCVar(CVars.BuildEngineType); var forkVersion = cfg.GetCVar(CVars.BuildVersion); var manifestDownloadUrl = Interpolate(cfg.GetCVar(CVars.BuildManifestDownloadUrl)); @@ -44,6 +46,7 @@ public static GameBuildInformation GetBuildInfoFromConfig(IConfigurationManager zipHash, zipDownload, forkId, + engineType, forkVersion, manifestHash, manifestUrl, diff --git a/Tools/package_client_build.py b/Tools/package_client_build.py index 8acea51266..c58935d43a 100755 --- a/Tools/package_client_build.py +++ b/Tools/package_client_build.py @@ -196,7 +196,7 @@ def build_linux(skip_build: bool, platform, name) -> None: client_zip = zipfile.ZipFile( p("release", "Robust.Client_%s.zip" % rid), "w", - compression=zipfile.ZIP_DEFLATED) + compression=zipfile.ZIP_DEFLATED, strict_timestamps=False) copy_dir_into_zip(p("bin", "Client", rid, "publish"), "", client_zip, IGNORED_FILES_LINUX) copy_resources("Resources", client_zip)