public async Task Start(CommandContext ctx) { var joinEmoji = DiscordEmoji.FromName(ctx.Client, ":white_check_mark:"); var startEmoji = DiscordEmoji.FromName(ctx.Client, ":arrow_forward:"); var embed = new DiscordEmbedBuilder { Title = "Mafia: Joining", Description = "Click the join button to join the game" }; var msg = await ctx.RespondAsync(embed : embed); await msg.CreateReactionAsync(joinEmoji); var players = new DiscordUser[1]; var allowStartGame = false; var startGame = false; // used instead of thread sleep so function in timer can interrupt sleep var sleeper = new BlockingCollection <int>(); // run once every half a second var joinTimer = new Timer( async e => { var currentPlayers = (await msg.GetReactionsAsync(joinEmoji)) .Where(p => p.Id != ctx.Client.CurrentUser.Id).ToArray(); if (currentPlayers.Length <= 1 && allowStartGame) { allowStartGame = false; foreach (var discordUser in await msg.GetReactionsAsync(startEmoji)) { await msg.DeleteReactionAsync( startEmoji, discordUser, "Game does not have enough users to start"); } } if (!players.SequenceEqual(currentPlayers)) { embed.Description = string.Join('\n', currentPlayers.Select(p => p.Username)) + "\n\nClick the join button to join the game"; if (currentPlayers.Length > 1) { embed.Description += "\nGame now has enough players to start, Click the start button to begin"; } players = currentPlayers; await msg.ModifyAsync(embed: embed); } if (currentPlayers.Length <= 1) { return; } if (!allowStartGame) { allowStartGame = true; await msg.CreateReactionAsync(startEmoji); } int startRequests = (await msg.GetReactionsAsync(startEmoji)) .Count(p => p.Username != ctx.Client.CurrentUser.Username); if (startRequests <= 0) { return; } // interrupt sleep sleeper.Add(0); startGame = true; }, null, 500, 500); // sleep for 2 minutes sleeper.TryTake(out _, TimeSpan.FromMinutes(2)); joinTimer.Change(-1, -1); await msg.DeleteAllReactionsAsync("joining is over"); if (!startGame) { await msg.ModifyAsync(null, new DiscordEmbedBuilder { Title = "Mafia: Game Canceled" }); return; } currentGame = new Mafia(1, 0, false, ctx.Client, msg, players.Select(p => new Player(p)).ToArray()); await currentGame.RunAsync(); }