public virtual async Task StartAsync(Game.StartCommand command, CancellationToken cancellationToken = default) { var(session, id) = command; var context = CommandContext.GetCurrent(); var user = await AuthService.GetUserAsync(session, cancellationToken); user = user.MustBeAuthenticated(); var userId = long.Parse(user.Id); await using var dbContext = await CreateCommandDbContextAsync(cancellationToken); var dbGame = await GetDbGame(dbContext, id, cancellationToken); var game = dbGame.ToModel(); var engine = GameEngines[game.EngineId]; if (game.Stage != GameStage.New) { throw new InvalidOperationException("Game has already been started."); } if (game.UserId != userId && !engine.AutoStart) { throw new InvalidOperationException("Only the creator of the game can start it."); } if (game.Players.Count < engine.MinPlayerCount) { throw new InvalidOperationException( $"{engine.MinPlayerCount - game.Players.Count} more player(s) must join to start the game."); } if (game.Players.Count > engine.MaxPlayerCount) { throw new InvalidOperationException( $"Too many players: {engine.MaxPlayerCount - game.Players.Count} player(s) must leave to start the game."); } context.Operation().Items.Set(game.Stage); // Saving prev. stage var now = Clock.Now; game = game with { StartedAt = now, LastMoveAt = now, Stage = GameStage.Playing, }; game = GameEngines[game.EngineId].Start(game); dbGame.UpdateFrom(game); await dbContext.SaveChangesAsync(cancellationToken); context.Operation().Items.Set(game); }
public Task Start([FromBody] Game.StartCommand command, CancellationToken cancellationToken = default) { command.UseDefaultSession(SessionResolver); return(Games.Start(command, cancellationToken)); }