using Barotrauma.Extensions; using Barotrauma.IO; using Barotrauma.Networking; using RestSharp; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Xml.Linq; using Color = Microsoft.Xna.Framework.Color; namespace Barotrauma.Steam { static partial class SteamManager { private static readonly List initializationErrors = new List(); public static IReadOnlyList InitializationErrors => initializationErrors; private static bool IsInitializedProjectSpecific => Steamworks.SteamClient.IsValid && Steamworks.SteamClient.IsLoggedOn; private static void InitializeProjectSpecific() { if (IsInitialized) { return; } try { Steamworks.SteamClient.Init(AppID, false); if (IsInitialized) { DebugConsole.NewMessage( $"Logged in as {GetUsername()} (SteamID {(GetSteamId().TryUnwrap(out var steamId) ? steamId.ToString() : "[NULL]")})"); popularTags.Clear(); int i = 0; foreach (KeyValuePair commonness in tagCommonness) { popularTags.Insert(i, commonness.Key); i++; } } Steamworks.SteamNetworkingUtils.OnDebugOutput += (Steamworks.NetDebugOutput nType, string pszMsg) => { if (GameSettings.CurrentConfig.VerboseLogging) { LogSteamworksNetworking(nType, pszMsg); } }; // Needed to detect invites for social overlay Steamworks.SteamFriends.ListenForFriendsMessages = true; } catch (DllNotFoundException) { initializationErrors.Add("SteamDllNotFound".ToIdentifier()); } catch (Exception e) { DebugConsole.ThrowError("SteamManager initialization threw an exception", e); initializationErrors.Add("SteamClientInitFailed".ToIdentifier()); } if (!IsInitialized) { try { if (Steamworks.SteamClient.IsValid) { Steamworks.SteamClient.Shutdown(); } } catch (Exception e) { if (GameSettings.CurrentConfig.VerboseLogging) DebugConsole.ThrowError("Disposing Steam client failed.", e); } } else { //Steamworks is completely insane so the following needs comments: //This callback seems to take place when the item in question has not been downloaded recently Steamworks.SteamUGC.OnItemInstalled += (appId, itemId) => Workshop.OnItemDownloadComplete(itemId); //This callback seems to take place when the item has been downloaded recently and an update //or a redownload has taken place Steamworks.SteamUGC.OnDownloadItemResult += (result, id) => { if (result == Steamworks.Result.OK) { Workshop.OnItemDownloadComplete(id); } }; //Maybe I'm completely wrong! All I know is that we need to handle both! } SteamTimelineManager.Initialize(); } public static bool NetworkingDebugLog { get; private set; } = false; private static void LogSteamworksNetworking(Steamworks.NetDebugOutput nType, string pszMsg) { DebugConsole.NewMessage($"({nType}) {pszMsg}", Color.Orange); } public static void SetSteamworksNetworkingDebugLog(bool enabled) { if (enabled == NetworkingDebugLog) { return; } if (enabled) { Steamworks.SteamNetworkingUtils.DebugLevel = Steamworks.NetDebugOutput.Everything; } else { Steamworks.SteamNetworkingUtils.DebugLevel = Steamworks.NetDebugOutput.None; } NetworkingDebugLog = enabled; } public static async Task InitRelayNetworkAccess() { if (!IsInitialized) { return; } await Task.Yield(); Steamworks.SteamNetworkingUtils.InitRelayNetworkAccess(); //SetSteamworksNetworkingDebugLog(true); var status = Steamworks.SteamNetworkingUtils.Status; while (status.Avail != Steamworks.SteamNetworkingAvailability.Current) { if (status.Avail == Steamworks.SteamNetworkingAvailability.CannotTry || status.Avail == Steamworks.SteamNetworkingAvailability.Previously || status.Avail == Steamworks.SteamNetworkingAvailability.Failed) { DebugConsole.ThrowError($"Failed to initialize Steamworks network relay: " + $"{Steamworks.SteamNetworkingUtils.Status.Avail}, " + $"{Steamworks.SteamNetworkingUtils.Status.AvailNetConfig}, " + $"{Steamworks.SteamNetworkingUtils.Status.Avail}, " + $"{Steamworks.SteamNetworkingUtils.Status.Msg}"); break; } await Task.Delay(25); status = Steamworks.SteamNetworkingUtils.Status; } //SetSteamworksNetworkingDebugLog(false); } public static bool OverlayCustomUrl(string url) { if (!IsInitialized || !Steamworks.SteamClient.IsValid) { return false; } Steamworks.SteamFriends.OpenWebOverlay(url); return true; } } }