Example #1
0
        public virtual async Task JoinAsync(Game.JoinCommand command, CancellationToken cancellationToken = default)
        {
            var(session, id, join) = 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 (join)
            {
                if (game.Players.Any(p => p.UserId == userId))
                {
                    throw new InvalidOperationException("You've already joined this game.");
                }
                if (game.Players.Count > engine.MaxPlayerCount)
                {
                    throw new InvalidOperationException("You can't join this game: there too many players already.");
                }
                game = game with {
                    Players = game.Players.Add(new GamePlayer(userId))
                };
            }
            else     // Leave
            {
                var leftPlayer = game.Players.SingleOrDefault(p => p.UserId == userId);
                if (leftPlayer == null)
                {
                    throw new InvalidOperationException("You've already left this game.");
                }
                game = game with {
                    Players = game.Players.Remove(leftPlayer)
                };
                context.Operation().Items.Set(leftPlayer);
            }

            dbGame.UpdateFrom(game);
            await dbContext.SaveChangesAsync(cancellationToken);

            context.Operation().Items.Set(game);

            // Try auto-start
            if (join && engine.AutoStart && game.Players.Count == engine.MaxPlayerCount)
            {
                await StartAsync(new Game.StartCommand(session, id), cancellationToken);
            }
        }
Example #2
0
 public Task Join([FromBody] Game.JoinCommand command, CancellationToken cancellationToken = default)
 {
     command.UseDefaultSession(SessionResolver);
     return(Games.Join(command, cancellationToken));
 }