// // Game.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.Extensions.Options; using NosSmooth.Game.Data.Characters; using NosSmooth.Game.Data.Maps; using NosSmooth.Game.Data.Raids; namespace NosSmooth.Game; /// /// Represents base nostale game class with the character, current map, friends and current raid. /// public class Game { private readonly GameOptions _options; private Map? _currentMap; /// /// Initializes a new instance of the class. /// /// The options for the game. public Game(IOptions options) { _options = options.Value; } /// /// Gets the playing character of the client. /// public Character? Character { get; internal set; } /// /// Gets the current map of the client. /// /// /// Will be null until current map packet is received. /// public Map? CurrentMap { get => _currentMap; internal set { _currentMap = value; MapChanged?.CancelAfter(TimeSpan.FromSeconds(_options.EntityCacheDuration)); } } /// /// Gets the active raid the client is currently on. /// /// /// May be null if there is no raid in progress. /// public Raid? CurrentRaid { get; internal set; } /// /// Cancellation token for changing the map to use in memory cache. /// internal CancellationTokenSource? MapChanged { get; private set; } /// /// Gets the set semaphore used for changing internal fields. /// internal SemaphoreSlim SetSemaphore { get; } = new SemaphoreSlim(1, 1); /// /// Ensures that Character is not null. /// /// Whether to release the semaphore. /// The cancellation token for cancelling the operation. /// A Task that may or may not have succeeded. internal async Task EnsureCharacterCreatedAsync(bool releaseSemaphore, CancellationToken ct = default) { await SetSemaphore.WaitAsync(ct); Character? character = Character; if (Character is null) { Character = character = new Character(); } if (releaseSemaphore) { SetSemaphore.Release(); } return character!; } }