355 lines
14 KiB
C#
355 lines
14 KiB
C#
using Discord.Commands;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Discord;
|
|
using NadekoBot.Services;
|
|
using NadekoBot.Attributes;
|
|
using Discord.WebSocket;
|
|
using NadekoBot.Services.Database.Models;
|
|
using System.Linq;
|
|
using NadekoBot.Services.Database;
|
|
|
|
//todo DB
|
|
namespace NadekoBot.Modules.ClashOfClans
|
|
{
|
|
[Module(",", AppendSpace = false)]
|
|
public class ClashOfClans : DiscordModule
|
|
{
|
|
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
|
|
|
|
public ClashOfClans(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client)
|
|
{
|
|
using (var uow = DbHandler.UnitOfWork())
|
|
{
|
|
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(
|
|
uow.ClashOfClans
|
|
.GetAll()
|
|
.Select(cw => {
|
|
cw.Channel = NadekoBot.Client.GetGuilds()
|
|
.FirstOrDefault(s => s.Id == cw.GuildId)?
|
|
.GetChannels()
|
|
.FirstOrDefault(c => c.Id == cw.ChannelId)
|
|
as ITextChannel;
|
|
cw.Bases.Capacity = cw.Size;
|
|
return cw;
|
|
})
|
|
.GroupBy(cw => cw.GuildId)
|
|
.ToDictionary(g => g.Key, g => g.ToList()));
|
|
}
|
|
}
|
|
|
|
private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
|
|
{
|
|
var Bases = war.Bases;
|
|
for (var i = 0; i < Bases.Capacity; i++)
|
|
{
|
|
if (Bases[i] == null) continue;
|
|
if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
|
|
{
|
|
await war.Channel.SendMessageAsync($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false);
|
|
Bases[i] = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task CreateWar(IUserMessage umsg, int size, [Remainder] string enemyClan = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
|
|
if (!(umsg.Author as IGuildUser).GuildPermissions.ManageChannels)
|
|
return;
|
|
|
|
if (string.IsNullOrWhiteSpace(enemyClan))
|
|
return;
|
|
|
|
if (size < 10 || size > 50 || size % 5 != 0)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 Not a Valid war size").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
List<ClashWar> wars;
|
|
if (!ClashWars.TryGetValue(channel.Guild.Id, out wars))
|
|
{
|
|
wars = new List<ClashWar>();
|
|
if (!ClashWars.TryAdd(channel.Guild.Id, wars))
|
|
return;
|
|
}
|
|
|
|
|
|
var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id);
|
|
//cw.Start();
|
|
|
|
wars.Add(cw);
|
|
await channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task StartWar(IUserMessage umsg, [Remainder] string number = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
|
|
int num = 0;
|
|
int.TryParse(number, out num);
|
|
|
|
var warsInfo = GetWarInfo(umsg, num);
|
|
if (warsInfo == null)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
var war = warsInfo.Item1[warsInfo.Item2];
|
|
try
|
|
{
|
|
war.Start();
|
|
await channel.SendMessageAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
|
|
}
|
|
catch
|
|
{
|
|
await channel.SendMessageAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
|
|
}
|
|
SaveWar(war);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task ListWar(IUserMessage umsg, [Remainder] string number = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
|
|
// if number is null, print all wars in a short way
|
|
if (string.IsNullOrWhiteSpace(number))
|
|
{
|
|
//check if there are any wars
|
|
List<ClashWar> wars = null;
|
|
ClashWars.TryGetValue(channel.Guild.Id, out wars);
|
|
if (wars == null || wars.Count == 0)
|
|
{
|
|
await channel.SendMessageAsync("🔰 **No active wars.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine("🔰 **LIST OF ACTIVE WARS**");
|
|
sb.AppendLine("**-------------------------**");
|
|
for (var i = 0; i < wars.Count; i++)
|
|
{
|
|
sb.AppendLine($"**#{i + 1}.** `Enemy:` **{wars[i].EnemyClan}**");
|
|
sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
|
|
sb.AppendLine("**-------------------------**");
|
|
}
|
|
await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
|
|
return;
|
|
|
|
}
|
|
var num = 0;
|
|
int.TryParse(number, out num);
|
|
//if number is not null, print the war needed
|
|
var warsInfo = GetWarInfo(umsg, num);
|
|
if (warsInfo == null)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
await channel.SendMessageAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task Claim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
var warsInfo = GetWarInfo(umsg, number);
|
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
var usr =
|
|
string.IsNullOrWhiteSpace(other_name) ?
|
|
umsg.Author.Username :
|
|
other_name;
|
|
try
|
|
{
|
|
var war = warsInfo.Item1[warsInfo.Item2];
|
|
war.Call(usr, baseNumber - 1);
|
|
SaveWar(war);
|
|
await channel.SendMessageAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
await FinishClaim(umsg, number, baseNumber, other_name, 1);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
await FinishClaim(umsg, number, baseNumber, other_name, 2);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
await FinishClaim(umsg, number, baseNumber, other_name);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task EndWar(IUserMessage umsg, int number)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
|
|
var warsInfo = GetWarInfo(umsg,number);
|
|
if (warsInfo == null)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 That war does not exist.").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
var war = warsInfo.Item1[warsInfo.Item2];
|
|
war.End();
|
|
SaveWar(war);
|
|
await channel.SendMessageAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
|
|
|
|
var size = warsInfo.Item1[warsInfo.Item2].Size;
|
|
warsInfo.Item1.RemoveAt(warsInfo.Item2);
|
|
}
|
|
|
|
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
|
|
[RequireContext(ContextType.Guild)]
|
|
public async Task Unclaim(IUserMessage umsg, int number, [Remainder] string otherName = null)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
|
|
var warsInfo = GetWarInfo(umsg, number);
|
|
if (warsInfo == null || warsInfo.Item1.Count == 0)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
var usr =
|
|
string.IsNullOrWhiteSpace(otherName) ?
|
|
umsg.Author.Username :
|
|
otherName;
|
|
try
|
|
{
|
|
var war = warsInfo.Item1[warsInfo.Item2];
|
|
var baseNumber = war.Uncall(usr);
|
|
SaveWar(war);
|
|
await channel.SendMessageAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
var warInfo = GetWarInfo(umsg, number);
|
|
if (warInfo == null || warInfo.Item1.Count == 0)
|
|
{
|
|
await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false);
|
|
return;
|
|
}
|
|
var usr =
|
|
string.IsNullOrWhiteSpace(other_name) ?
|
|
umsg.Author.Username :
|
|
other_name;
|
|
|
|
var war = warInfo.Item1[warInfo.Item2];
|
|
try
|
|
{
|
|
var baseNum = war.FinishClaim(usr, stars);
|
|
SaveWar(war);
|
|
await channel.SendMessageAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await channel.SendMessageAsync($"💢🔰 {ex.Message}").ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
private static Tuple<List<ClashWar>, int> GetWarInfo(IUserMessage umsg, int num)
|
|
{
|
|
var channel = (ITextChannel)umsg.Channel;
|
|
//check if there are any wars
|
|
List<ClashWar> wars = null;
|
|
ClashWars.TryGetValue(channel.Guild.Id, out wars);
|
|
if (wars == null || wars.Count == 0)
|
|
{
|
|
return null;
|
|
}
|
|
// get the number of the war
|
|
else if (num < 1 || num > wars.Count)
|
|
{
|
|
return null;
|
|
}
|
|
num -= 1;
|
|
//get the actual war
|
|
return new Tuple<List<ClashWar>, int>(wars, num);
|
|
}
|
|
|
|
public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId)
|
|
{
|
|
using (var uow = DbHandler.UnitOfWork())
|
|
{
|
|
var cw = new ClashWar
|
|
{
|
|
EnemyClan = enemyClan,
|
|
Size = size,
|
|
Bases = new List<ClashCaller>(size),
|
|
GuildId = serverId,
|
|
ChannelId = channelId,
|
|
Channel = NadekoBot.Client.GetGuilds()
|
|
.FirstOrDefault(s => s.Id == serverId)?
|
|
.GetChannels()
|
|
.FirstOrDefault(c => c.Id == channelId)
|
|
as ITextChannel
|
|
};
|
|
uow.ClashOfClans.Add(cw);
|
|
await uow.CompleteAsync();
|
|
return cw;
|
|
}
|
|
}
|
|
|
|
public static void SaveWar(ClashWar cw)
|
|
{
|
|
if (cw.WarState == ClashWar.StateOfWar.Ended)
|
|
{
|
|
using (var uow = DbHandler.UnitOfWork())
|
|
{
|
|
uow.ClashOfClans.Remove(cw);
|
|
uow.CompleteAsync();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
using (var uow = DbHandler.UnitOfWork())
|
|
{
|
|
uow.ClashOfClans.Update(cw);
|
|
uow.CompleteAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|