renamed nunchi to countup, added remaining user count to each guess
This commit is contained in:
parent
e357c78fbe
commit
85f735fcc7
7 changed files with 148 additions and 138 deletions
src/EllieBot
Modules/Games
strings
|
@ -2,7 +2,6 @@
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
using EllieBot.Modules.Games.Common;
|
||||
using EllieBot.Modules.Games.Common.Acrophobia;
|
||||
using EllieBot.Modules.Games.Common.Nunchi;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EllieBot.Modules.Games.Services;
|
||||
|
@ -21,7 +20,7 @@ public class GamesService : IEService
|
|||
public ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new();
|
||||
public Dictionary<ulong, TicTacToe> TicTacToeGames { get; } = new();
|
||||
public ConcurrentDictionary<ulong, TypingGame> RunningContests { get; } = new();
|
||||
public ConcurrentDictionary<ulong, NunchiGame> NunchiGames { get; } = new();
|
||||
public ConcurrentDictionary<ulong, CountUpGame> Games { get; } = new();
|
||||
|
||||
private readonly GamesConfigService _gamesConfig;
|
||||
|
||||
|
|
117
src/EllieBot/Modules/Games/Nunchi/CountUpCommands.cs
Normal file
117
src/EllieBot/Modules/Games/Nunchi/CountUpCommands.cs
Normal file
|
@ -0,0 +1,117 @@
|
|||
#nullable disable
|
||||
using EllieBot.Modules.Games.Services;
|
||||
|
||||
namespace EllieBot.Modules.Games;
|
||||
|
||||
public partial class Games
|
||||
{
|
||||
[Group]
|
||||
public partial class CountUpCommands : EllieModule<GamesService>
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public CountUpCommands(DiscordSocketClient client)
|
||||
=> _client = client;
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task CountUp()
|
||||
{
|
||||
var newGame = new CountUpGame(ctx.User.Id, ctx.User.ToString());
|
||||
CountUpGame countUp;
|
||||
|
||||
// if a game was already active
|
||||
if ((countUp = _service.Games.GetOrAdd(ctx.Guild.Id, newGame)) != newGame)
|
||||
{
|
||||
// join it
|
||||
// if you failed joining, that means the game is running or just ended
|
||||
if (!await countUp.Join(ctx.User.Id, ctx.User.ToString()))
|
||||
return;
|
||||
|
||||
await Response().Confirm(strs.countup_joined(countUp.ParticipantCount)).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{ await Response().Confirm(strs.countup_created).SendAsync(); }
|
||||
catch { }
|
||||
|
||||
countUp.OnGameEnded += CountUpOnGameEnded;
|
||||
countUp.OnRoundEnded += CountUpOnRoundEnded;
|
||||
countUp.OnUserGuessed += CountUpOnUserGuessed;
|
||||
countUp.OnRoundStarted += CountUpOnRoundStarted;
|
||||
_client.MessageReceived += ClientMessageReceived;
|
||||
|
||||
var success = await countUp.Initialize();
|
||||
if (!success)
|
||||
{
|
||||
if (_service.Games.TryRemove(ctx.Guild.Id, out var game))
|
||||
game.Dispose();
|
||||
await Response().Confirm(strs.countup_failed_to_start).SendAsync();
|
||||
}
|
||||
|
||||
Task ClientMessageReceived(SocketMessage arg)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
if (arg.Channel.Id != ctx.Channel.Id)
|
||||
return;
|
||||
|
||||
if (!int.TryParse(arg.Content, out var number))
|
||||
return;
|
||||
try
|
||||
{
|
||||
await countUp.Input(arg.Author.Id, arg.Author.ToString(), number);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task CountUpOnGameEnded(CountUpGame arg1, string arg2)
|
||||
{
|
||||
if (_service.Games.TryRemove(ctx.Guild.Id, out var game))
|
||||
{
|
||||
_client.MessageReceived -= ClientMessageReceived;
|
||||
game.Dispose();
|
||||
}
|
||||
|
||||
if (arg2 is null)
|
||||
return Response().Confirm(strs.countup_ended_no_winner).SendAsync();
|
||||
return Response().Confirm(strs.countup_ended(Format.Bold(arg2))).SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private Task CountUpOnRoundStarted(CountUpGame arg, int cur)
|
||||
=> Response()
|
||||
.Confirm(strs.countup_round_started(Format.Bold(arg.ParticipantCount.ToString()),
|
||||
Format.Bold(cur.ToString())))
|
||||
.SendAsync();
|
||||
|
||||
private Task CountUpOnUserGuessed(CountUpGame arg)
|
||||
=> Response()
|
||||
.Embed(CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithDescription(GetText(strs.countup_next_number(Format.Bold(arg.CurrentNumber.ToString()))))
|
||||
.WithFooter($"{arg.PassedCount} / {arg.ParticipantCount}"))
|
||||
.SendAsync();
|
||||
|
||||
private Task CountUpOnRoundEnded(CountUpGame arg1, (ulong Id, string Name)? arg2)
|
||||
{
|
||||
if (arg2.HasValue)
|
||||
return Response().Confirm(strs.countup_round_ended(Format.Bold(arg2.Value.Name))).SendAsync();
|
||||
return Response()
|
||||
.Confirm(strs.countup_round_ended_boot(
|
||||
Format.Bold("\n"
|
||||
+ string.Join("\n, ",
|
||||
arg1.Participants.Select(x
|
||||
=> x.Name)))))
|
||||
.SendAsync(); // this won't work if there are too many users
|
||||
}
|
||||
|
||||
private Task CountUpOnGameStarted(CountUpGame arg)
|
||||
=> Response().Confirm(strs.countup_started(Format.Bold(arg.ParticipantCount.ToString()))).SendAsync();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
#nullable disable
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace EllieBot.Modules.Games.Common.Nunchi;
|
||||
namespace EllieBot.Modules.Games;
|
||||
|
||||
public sealed class NunchiGame : IDisposable
|
||||
public sealed class CountUpGame : IDisposable
|
||||
{
|
||||
public enum Phase
|
||||
{
|
||||
|
@ -16,11 +16,11 @@ public sealed class NunchiGame : IDisposable
|
|||
private const int KILL_TIMEOUT = 20 * 1000;
|
||||
private const int NEXT_ROUND_TIMEOUT = 5 * 1000;
|
||||
|
||||
public event Func<NunchiGame, Task> OnGameStarted;
|
||||
public event Func<NunchiGame, int, Task> OnRoundStarted;
|
||||
public event Func<NunchiGame, Task> OnUserGuessed;
|
||||
public event Func<NunchiGame, (ulong Id, string Name)?, Task> OnRoundEnded; // tuple of the user who failed
|
||||
public event Func<NunchiGame, string, Task> OnGameEnded; // name of the user who won
|
||||
public event Func<CountUpGame, Task> OnGameStarted;
|
||||
public event Func<CountUpGame, int, Task> OnRoundStarted;
|
||||
public event Func<CountUpGame, Task> OnUserGuessed;
|
||||
public event Func<CountUpGame, (ulong Id, string Name)?, Task> OnRoundEnded; // tuple of the user who failed
|
||||
public event Func<CountUpGame, string, Task> OnGameEnded; // name of the user who won
|
||||
|
||||
public int CurrentNumber { get; private set; } = new EllieRandom().Next(0, 100);
|
||||
public Phase CurrentPhase { get; private set; } = Phase.Joining;
|
||||
|
@ -31,13 +31,16 @@ public sealed class NunchiGame : IDisposable
|
|||
public int ParticipantCount
|
||||
=> participants.Count;
|
||||
|
||||
public int PassedCount
|
||||
=> _passed.Count;
|
||||
|
||||
private readonly SemaphoreSlim _locker = new(1, 1);
|
||||
|
||||
private HashSet<(ulong Id, string Name)> participants = [];
|
||||
private readonly HashSet<(ulong Id, string Name)> _passed = [];
|
||||
private Timer killTimer;
|
||||
|
||||
public NunchiGame(ulong creatorId, string creatorName)
|
||||
public CountUpGame(ulong creatorId, string creatorName)
|
||||
=> participants.Add((creatorId, creatorName));
|
||||
|
||||
public async Task<bool> Join(ulong userId, string userName)
|
|
@ -1,114 +0,0 @@
|
|||
#nullable disable
|
||||
using EllieBot.Modules.Games.Common.Nunchi;
|
||||
using EllieBot.Modules.Games.Services;
|
||||
|
||||
namespace EllieBot.Modules.Games;
|
||||
|
||||
public partial class Games
|
||||
{
|
||||
[Group]
|
||||
public partial class NunchiCommands : EllieModule<GamesService>
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public NunchiCommands(DiscordSocketClient client)
|
||||
=> _client = client;
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Nunchi()
|
||||
{
|
||||
var newNunchi = new NunchiGame(ctx.User.Id, ctx.User.ToString());
|
||||
NunchiGame nunchi;
|
||||
|
||||
//if a game was already active
|
||||
if ((nunchi = _service.NunchiGames.GetOrAdd(ctx.Guild.Id, newNunchi)) != newNunchi)
|
||||
{
|
||||
// join it
|
||||
// if you failed joining, that means game is running or just ended
|
||||
if (!await nunchi.Join(ctx.User.Id, ctx.User.ToString()))
|
||||
return;
|
||||
|
||||
await Response().Confirm(strs.nunchi_joined(nunchi.ParticipantCount)).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try { await Response().Confirm(strs.nunchi_created).SendAsync(); }
|
||||
catch { }
|
||||
|
||||
nunchi.OnGameEnded += NunchiOnGameEnded;
|
||||
//nunchi.OnGameStarted += Nunchi_OnGameStarted;
|
||||
nunchi.OnRoundEnded += Nunchi_OnRoundEnded;
|
||||
nunchi.OnUserGuessed += Nunchi_OnUserGuessed;
|
||||
nunchi.OnRoundStarted += Nunchi_OnRoundStarted;
|
||||
_client.MessageReceived += ClientMessageReceived;
|
||||
|
||||
var success = await nunchi.Initialize();
|
||||
if (!success)
|
||||
{
|
||||
if (_service.NunchiGames.TryRemove(ctx.Guild.Id, out var game))
|
||||
game.Dispose();
|
||||
await Response().Confirm(strs.nunchi_failed_to_start).SendAsync();
|
||||
}
|
||||
|
||||
Task ClientMessageReceived(SocketMessage arg)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
if (arg.Channel.Id != ctx.Channel.Id)
|
||||
return;
|
||||
|
||||
if (!int.TryParse(arg.Content, out var number))
|
||||
return;
|
||||
try
|
||||
{
|
||||
await nunchi.Input(arg.Author.Id, arg.Author.ToString(), number);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
Task NunchiOnGameEnded(NunchiGame arg1, string arg2)
|
||||
{
|
||||
if (_service.NunchiGames.TryRemove(ctx.Guild.Id, out var game))
|
||||
{
|
||||
_client.MessageReceived -= ClientMessageReceived;
|
||||
game.Dispose();
|
||||
}
|
||||
|
||||
if (arg2 is null)
|
||||
return Response().Confirm(strs.nunchi_ended_no_winner).SendAsync();
|
||||
return Response().Confirm(strs.nunchi_ended(Format.Bold(arg2))).SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private Task Nunchi_OnRoundStarted(NunchiGame arg, int cur)
|
||||
=> Response()
|
||||
.Confirm(strs.nunchi_round_started(Format.Bold(arg.ParticipantCount.ToString()),
|
||||
Format.Bold(cur.ToString())))
|
||||
.SendAsync();
|
||||
|
||||
private Task Nunchi_OnUserGuessed(NunchiGame arg)
|
||||
=> Response().Confirm(strs.nunchi_next_number(Format.Bold(arg.CurrentNumber.ToString()))).SendAsync();
|
||||
|
||||
private Task Nunchi_OnRoundEnded(NunchiGame arg1, (ulong Id, string Name)? arg2)
|
||||
{
|
||||
if (arg2.HasValue)
|
||||
return Response().Confirm(strs.nunchi_round_ended(Format.Bold(arg2.Value.Name))).SendAsync();
|
||||
return Response()
|
||||
.Confirm(strs.nunchi_round_ended_boot(
|
||||
Format.Bold("\n"
|
||||
+ string.Join("\n, ",
|
||||
arg1.Participants.Select(x
|
||||
=> x.Name)))))
|
||||
.SendAsync(); // this won't work if there are too many users
|
||||
}
|
||||
|
||||
private Task Nunchi_OnGameStarted(NunchiGame arg)
|
||||
=> Response().Confirm(strs.nunchi_started(Format.Bold(arg.ParticipantCount.ToString()))).SendAsync();
|
||||
}
|
||||
}
|
|
@ -442,7 +442,8 @@ race:
|
|||
joinrace:
|
||||
- joinrace
|
||||
- jr
|
||||
nunchi:
|
||||
countup:
|
||||
- countup
|
||||
- nunchi
|
||||
connect4:
|
||||
- connect4
|
||||
|
|
|
@ -1473,8 +1473,12 @@ joinrace:
|
|||
params:
|
||||
- amount:
|
||||
desc: "The amount to be wagered on the race."
|
||||
nunchi:
|
||||
desc: Creates or joins an existing nunchi game. Users have to count up by 1 from the starting number shown by the bot. If someone makes a mistake (types an incorrect number, or repeats the same number) they are out of the game and a new round starts without them. Minimum 3 users required.
|
||||
countup:
|
||||
desc: |-
|
||||
Creates or joins an existing CountUp game.
|
||||
Bot will show a number - count up from it.
|
||||
Whoever writes a duplicate number, or is the last person without a number loses, a new round starts!
|
||||
Minimum 3 users required.
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
|
|
|
@ -806,16 +806,16 @@
|
|||
"connect4_failed_to_start": "Connect4 game failed to start because nobody joined.",
|
||||
"connect4_draw": "Connect4 game ended in a draw.",
|
||||
"connect4_won": "{0} won the game of Connect4 against {1}.",
|
||||
"nunchi_joined": "Joined nunchi game. {0} users joined so far.",
|
||||
"nunchi_ended": "Nunchi game ended. {0} won",
|
||||
"nunchi_ended_no_winner": "Nunchi game ended with no winner.",
|
||||
"nunchi_started": "Nunchi game started with {0} participants.",
|
||||
"nunchi_round_ended": "Nunchi round ended. {0} is out of the game.",
|
||||
"nunchi_round_ended_boot": "Nunchi round ended due to timeout of some users. These users are still in the game: {0}",
|
||||
"nunchi_round_started": "Nunchi round started with {0} users. Start counting from the number {1}.",
|
||||
"nunchi_next_number": "Number registered. Last number was {0}.",
|
||||
"nunchi_failed_to_start": "Nunchi failed to start because there were not enough participants.",
|
||||
"nunchi_created": "Nunchi game created. Waiting for users to join.",
|
||||
"countup_joined": "Joined countup game. {0} users joined so far.",
|
||||
"countup_ended": "CountUp game ended. {0} won",
|
||||
"countup_ended_no_winner": "CountUp game ended with no winner.",
|
||||
"countup_started": "CountUp game started with {0} participants.",
|
||||
"countup_round_ended": "CountUp round ended. {0} is out of the game.",
|
||||
"countup_round_ended_boot": "CountUp round ended due to timeout of some users. These users are still in the game: {0}",
|
||||
"countup_round_started": "CountUp round started with {0} users. Start counting from the number {1}.",
|
||||
"countup_next_number": "Number registered. Last number was {0}.",
|
||||
"countup_failed_to_start": "CountUp failed to start because there were not enough participants.",
|
||||
"countup_created": "CountUp game created. Waiting for users to join.",
|
||||
"stream_role_enabled": "When a user from {0} role starts streaming, I will give them {1} role.",
|
||||
"stream_role_disabled": "Stream role feature has been disabled.",
|
||||
"stream_role_kw_set": "Streamers now require {0} keyword in order to receive the role.",
|
||||
|
@ -994,7 +994,7 @@
|
|||
"module_page_empty": "No module on this page.",
|
||||
"module_description_help": "Get command help, descriptions and usage examples",
|
||||
"module_description_gambling": "Bet on dice rolls, blackjack, slots, coinflips and others",
|
||||
"module_description_games": "Play trivia, nunchi, hangman, connect4 and other games",
|
||||
"module_description_games": "Play trivia, countup, hangman, connect4 and other games",
|
||||
"module_description_music": "Play music from youtube, local files and radio streams",
|
||||
"module_description_utility": "Manage custom quotes, repeating messages and check facts about the server",
|
||||
"module_description_administration": "Moderation, punish users, setup self assignable roles and greet messages",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue