- InitializeAsync in InitializeSafeAsync mit Fehlerbehandlung umbenannt, App-Start robuster gestaltet - Asynchrone Initialisierung bei Window.Created - Navigation vereinheitlicht: Routing.RegisterRoute statt Doppelslash, Navigation ohne Präfix - Flyout-Menü in AppShell deaktiviert, ShellContent-Einträge entfernt - Login/Register-ViewModels nutzen private Felder statt ObservableProperty - SignalRService nutzt AccessToken aus AuthSessionService - GameStateService: Automatischer Resync bei Verbindung, Fehlerhandling verbessert - Navigation in ViewModels an neues Routing angepasst - Aufräumarbeiten: Entfernte auskommentierte Messenger-Registrierungen, Initialisierung vereinheitlicht
134 lines
4.3 KiB
C#
134 lines
4.3 KiB
C#
using System.Text.Json;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using SlipItIn.Messages;
|
|
using SlipItIn.Models;
|
|
using SlipItIn.Services.Interfaces;
|
|
using SlipItIn.Shared.DTOs;
|
|
|
|
namespace SlipItIn.Services;
|
|
|
|
public class GameStateService : IGameStateService
|
|
{
|
|
private readonly ISignalRService _signalR;
|
|
private readonly ILocalStorageService _localStorage;
|
|
private readonly IMessenger _messenger;
|
|
|
|
private readonly List<QueuedGameAction> _queuedActions = [];
|
|
|
|
public GameStateDto? CurrentGameState { get; private set; }
|
|
public PlayerHandDto? CurrentPlayerHand { get; private set; }
|
|
public SlipChallengeDto? PendingChallenge { get; private set; }
|
|
|
|
public GameStateService(ISignalRService signalR, ILocalStorageService localStorage)
|
|
{
|
|
_signalR = signalR;
|
|
_localStorage = localStorage;
|
|
_messenger = WeakReferenceMessenger.Default;
|
|
|
|
_signalR.LobbyCreated += (_, value) => _messenger.Send(new LobbyCreatedMessage(value));
|
|
|
|
_signalR.GameStateUpdated += async (_, state) =>
|
|
{
|
|
CurrentGameState = state;
|
|
await _localStorage.SaveGameStateAsync(state);
|
|
_messenger.Send(new GameStateChangedMessage(state));
|
|
};
|
|
|
|
_signalR.GameStarted += (_, gameId) => _messenger.Send(new GameStartedMessage(gameId));
|
|
|
|
_signalR.PlayerHandUpdated += async (_, hand) =>
|
|
{
|
|
CurrentPlayerHand = hand;
|
|
await _localStorage.SavePlayerHandAsync(hand);
|
|
_messenger.Send(new PlayerHandChangedMessage(hand));
|
|
};
|
|
|
|
_signalR.ChallengeReceived += (_, challenge) =>
|
|
{
|
|
PendingChallenge = challenge;
|
|
_messenger.Send(new ChallengeReceivedMessage(challenge));
|
|
};
|
|
|
|
_signalR.ErrorReceived += (_, error) => _messenger.Send(new ErrorOccurredMessage(error));
|
|
_signalR.ConnectionStateChanged += async (_, connected) =>
|
|
{
|
|
_messenger.Send(new ConnectionStateChangedMessage(connected));
|
|
if (connected)
|
|
{
|
|
try
|
|
{
|
|
await ResyncAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_messenger.Send(new ErrorOccurredMessage($"Resync fehlgeschlagen: {ex.Message}"));
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
public async Task InitializeAsync()
|
|
{
|
|
CurrentGameState = await _localStorage.GetGameStateAsync();
|
|
CurrentPlayerHand = await _localStorage.GetPlayerHandAsync();
|
|
|
|
var queued = await _localStorage.GetQueuedActionsAsync();
|
|
_queuedActions.Clear();
|
|
_queuedActions.AddRange(queued.OrderBy(a => a.CreatedAtUtc));
|
|
|
|
if (CurrentGameState is not null)
|
|
_messenger.Send(new GameStateChangedMessage(CurrentGameState));
|
|
|
|
if (CurrentPlayerHand is not null)
|
|
_messenger.Send(new PlayerHandChangedMessage(CurrentPlayerHand));
|
|
}
|
|
|
|
public async Task ResyncAsync()
|
|
{
|
|
if (CurrentGameState?.GameId > 0 && _signalR.IsConnected)
|
|
await _signalR.RequestGameStateAsync(CurrentGameState.GameId);
|
|
|
|
await FlushQueuedActionsAsync();
|
|
}
|
|
|
|
public async Task EnqueueActionAsync(string method, params object[] arguments)
|
|
{
|
|
var action = new QueuedGameAction
|
|
{
|
|
Method = method,
|
|
ArgumentsJson = JsonSerializer.Serialize(arguments),
|
|
CreatedAtUtc = DateTime.UtcNow
|
|
};
|
|
|
|
_queuedActions.Add(action);
|
|
await _localStorage.SaveQueuedActionsAsync(_queuedActions);
|
|
}
|
|
|
|
public async Task FlushQueuedActionsAsync()
|
|
{
|
|
if (!_signalR.IsConnected || _queuedActions.Count == 0)
|
|
return;
|
|
|
|
var snapshot = _queuedActions.ToList();
|
|
foreach (var action in snapshot)
|
|
{
|
|
await _signalR.SendQueuedActionAsync(action);
|
|
_queuedActions.Remove(action);
|
|
}
|
|
|
|
await _localStorage.SaveQueuedActionsAsync(_queuedActions);
|
|
}
|
|
|
|
public async Task ClearLocalGameDataAsync()
|
|
{
|
|
CurrentGameState = null;
|
|
CurrentPlayerHand = null;
|
|
PendingChallenge = null;
|
|
_queuedActions.Clear();
|
|
|
|
await _localStorage.ClearGameStateAsync();
|
|
await _localStorage.ClearPlayerHandAsync();
|
|
await _localStorage.ClearQueuedActionsAsync();
|
|
}
|
|
}
|