using System.Collections.Concurrent; using Steamworks; namespace SVSim.EmulatedEntrypoint.Services; public class SteamSessionService : IDisposable { private readonly ConcurrentDictionary _validatedSessionTickets = new(); private readonly object _initLock = new(); private bool _steamInitialized; private const int ShadowVerseAppId = 453480; /// /// Validates if a given session ticket is valid, and matches up with the given steamid. /// /// the ticket, represented as a hexadecimal string /// the steamid that should be associated with the ticket /// whether the ticket is valid for the given steamid public bool IsTicketValidForUser(string ticket, ulong steamId) { if (_validatedSessionTickets.TryGetValue(ticket, out ulong storedSteamId)) { return storedSteamId == steamId; } EnsureSteamInitialized(); List ticketBytes = new List(); for (int i = 0; i < ticket.Length; i += 2) { ticketBytes.Add(Convert.ToByte(ticket.Substring(i, 2), 16)); } var steamCheckResults = SteamServer.BeginAuthSession(ticketBytes.ToArray(), new SteamId { Value = steamId }); if (steamCheckResults) { _validatedSessionTickets.TryAdd(ticket, steamId); } return steamCheckResults; } private void EnsureSteamInitialized() { if (_steamInitialized) return; lock (_initLock) { if (_steamInitialized) return; SteamServer.Init(ShadowVerseAppId, new SteamServerInit { GamePort = default, QueryPort = default }); _steamInitialized = true; } } public void Dispose() { if (_steamInitialized) { SteamServer.Shutdown(); } } }