using Steamworks; namespace ytLive.Services.Entitlement; /// /// Reads ownership of the paid app from Steam. In the free Demo, this checks the associated paid /// app ID; no key, server, or LlamaCasty account is involved. A missing ID, Steam client, or native /// library fails closed so the app can continue with the free output profile. /// public sealed class SteamEntitlement : IEntitlement { private readonly uint _paidAppId; private readonly Func _initializeSteam; private readonly Func _isAppSubscribed; private readonly Action _shutdownSteam; private bool _initAttempted; private bool _available; private bool? _cached; public SteamEntitlement(uint paidAppId) : this( paidAppId, SteamAPI.Init, appId => SteamApps.BIsSubscribedApp(new AppId_t(appId)), SteamAPI.Shutdown) { } internal SteamEntitlement( uint paidAppId, Func initializeSteam, Func isAppSubscribed, Action shutdownSteam) { _paidAppId = paidAppId; _initializeSteam = initializeSteam; _isAppSubscribed = isAppSubscribed; _shutdownSteam = shutdownSteam; } /// Configured with no paid app ID; ownership fails closed without touching Steam. public static SteamEntitlement NotConfigured() => new(0); public bool IsAppOwned { get { if (_paidAppId == 0) return false; if (_cached is { } known) return known; if (!_initAttempted) { _initAttempted = true; try { _available = _initializeSteam(); } catch (Exception) { _available = false; } } if (!_available) { _cached = false; return false; } try { var owned = _isAppSubscribed(_paidAppId); _cached = owned; return owned; } catch (Exception) { return false; } } } public void Shutdown() { if (_available) _shutdownSteam(); _available = false; _cached = null; _initAttempted = false; } }