From be7673319a10e24b86b35a09c85e57be09914868 Mon Sep 17 00:00:00 2001 From: sichii Date: Wed, 15 Jan 2025 22:03:50 -0500 Subject: [PATCH] more group commands - /kick, /promote - group stuff should work with names with spaces i think maybe --- Chaos/Collections/Group.cs | 30 +++++++++- Chaos/Messaging/GroupInviteCommand.cs | 4 ++ Chaos/Messaging/KickCommand.cs | 39 +++++++++++++ Chaos/Messaging/PromoteLeaderCommand.cs | 39 +++++++++++++ Chaos/Messaging/RequestGroupInviteCommand.cs | 4 ++ .../ReactorTileScripts/LeaderboardScript.cs | 4 +- .../Other/Abstractions/IGroupService.cs | 4 ++ Chaos/Services/Other/GroupService.cs | 58 +++++++++++++++++++ Chaos/Services/Servers/WorldServer.cs | 2 + Data/LocalStorage/LeaderboardObj.json | 7 +++ Data/LocalStorage/LeaderboardObj.json.bak | 7 +++ Tools/SeqConfigurator/Program.cs | 13 ++++- 12 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 Chaos/Messaging/KickCommand.cs create mode 100644 Chaos/Messaging/PromoteLeaderCommand.cs create mode 100644 Data/LocalStorage/LeaderboardObj.json create mode 100644 Data/LocalStorage/LeaderboardObj.json.bak diff --git a/Chaos/Collections/Group.cs b/Chaos/Collections/Group.cs index ced0061889..ea50cb373f 100644 --- a/Chaos/Collections/Group.cs +++ b/Chaos/Collections/Group.cs @@ -1,5 +1,6 @@ #region using Chaos.DarkAges.Definitions; +using Chaos.Extensions.Common; using Chaos.Messaging.Abstractions; using Chaos.Models.World; using Chaos.Models.World.Abstractions; @@ -245,6 +246,27 @@ public void Leave(Aisling aisling) } } + public void Promote(Aisling aisling) + { + using var @lock = Sync.EnterScope(); + + if (aisling.Equals(Leader)) + { + aisling.SendActiveMessage("You dumbly point to yourself"); + + return; + } + + Members.Remove(aisling); + Members.Insert(0, aisling); + + foreach (var member in Members) + { + member.SendActiveMessage($"{aisling.Name} has been promoted to group leader"); + member.Client.SendSelfProfile(); + } + } + private bool Remove(Aisling aisling) { using var @lock = Sync.EnterScope(); @@ -267,10 +289,14 @@ public override string ToString() var groupString = "Group members"; foreach (var user in Members) + { + var name = user.Name.ReplaceI(" ", "_"); + if (user.Equals(Leader)) - groupString += '\n' + $"* {user.Name}"; + groupString += '\n' + $"* {name}"; else - groupString += '\n' + $" {user.Name}"; + groupString += '\n' + $" {name}"; + } groupString += '\n' + $"Total {Count}"; diff --git a/Chaos/Messaging/GroupInviteCommand.cs b/Chaos/Messaging/GroupInviteCommand.cs index a3f4486942..a05caab155 100644 --- a/Chaos/Messaging/GroupInviteCommand.cs +++ b/Chaos/Messaging/GroupInviteCommand.cs @@ -1,9 +1,11 @@ +#region using Chaos.Collections.Common; using Chaos.Extensions.Common; using Chaos.Messaging.Abstractions; using Chaos.Models.World; using Chaos.Networking.Abstractions; using Chaos.Services.Other.Abstractions; +#endregion namespace Chaos.Messaging; @@ -19,6 +21,8 @@ public ValueTask ExecuteAsync(Aisling source, ArgumentCollection args) if (!args.TryGetNext(out var targetName)) return default; + targetName = targetName.ReplaceI("_", " "); + var targetClient = ClientRegistry.FirstOrDefault(c => c.Aisling.Name.EqualsI(targetName)); if ((targetClient == null) || (source.IsAdmin != targetClient.Aisling.IsAdmin)) diff --git a/Chaos/Messaging/KickCommand.cs b/Chaos/Messaging/KickCommand.cs new file mode 100644 index 0000000000..bcc562cacb --- /dev/null +++ b/Chaos/Messaging/KickCommand.cs @@ -0,0 +1,39 @@ +#region +using Chaos.Collections.Common; +using Chaos.Extensions.Common; +using Chaos.Messaging.Abstractions; +using Chaos.Models.World; +using Chaos.Networking.Abstractions; +using Chaos.Services.Other.Abstractions; +#endregion + +namespace Chaos.Messaging; + +[Command("kick", false, "")] +public class KickCommand(IGroupService groupService, IClientRegistry clientRegistry) : ICommand +{ + private readonly IClientRegistry ClientRegistry = clientRegistry; + private readonly IGroupService GroupService = groupService; + + /// + public ValueTask ExecuteAsync(Aisling source, ArgumentCollection args) + { + if (!args.TryGetNext(out var targetName)) + return default; + + targetName = targetName.ReplaceI("_", " "); + + var targetClient = ClientRegistry.FirstOrDefault(c => c.Aisling.Name.EqualsI(targetName)); + + if ((targetClient == null) || (source.IsAdmin != targetClient.Aisling.IsAdmin)) + { + source.SendOrangeBarMessage($"{targetName} can not be found"); + + return default; + } + + GroupService.Kick(source, targetClient.Aisling); + + return default; + } +} \ No newline at end of file diff --git a/Chaos/Messaging/PromoteLeaderCommand.cs b/Chaos/Messaging/PromoteLeaderCommand.cs new file mode 100644 index 0000000000..19253ff2ad --- /dev/null +++ b/Chaos/Messaging/PromoteLeaderCommand.cs @@ -0,0 +1,39 @@ +#region +using Chaos.Collections.Common; +using Chaos.Extensions.Common; +using Chaos.Messaging.Abstractions; +using Chaos.Models.World; +using Chaos.Networking.Abstractions; +using Chaos.Services.Other.Abstractions; +#endregion + +namespace Chaos.Messaging; + +[Command("promote", false, "")] +public class PromoteLeaderCommand(IGroupService groupService, IClientRegistry clientRegistry) : ICommand +{ + private readonly IClientRegistry ClientRegistry = clientRegistry; + private readonly IGroupService GroupService = groupService; + + /// + public ValueTask ExecuteAsync(Aisling source, ArgumentCollection args) + { + if (!args.TryGetNext(out var targetName)) + return default; + + targetName = targetName.ReplaceI("_", " "); + + var targetClient = ClientRegistry.FirstOrDefault(c => c.Aisling.Name.EqualsI(targetName)); + + if ((targetClient == null) || (source.IsAdmin != targetClient.Aisling.IsAdmin)) + { + source.SendOrangeBarMessage($"{targetName} can not be found"); + + return default; + } + + GroupService.Promote(source, targetClient.Aisling); + + return default; + } +} \ No newline at end of file diff --git a/Chaos/Messaging/RequestGroupInviteCommand.cs b/Chaos/Messaging/RequestGroupInviteCommand.cs index 089152a24f..e2df343b6e 100644 --- a/Chaos/Messaging/RequestGroupInviteCommand.cs +++ b/Chaos/Messaging/RequestGroupInviteCommand.cs @@ -1,9 +1,11 @@ +#region using Chaos.Collections.Common; using Chaos.Extensions.Common; using Chaos.Messaging.Abstractions; using Chaos.Models.World; using Chaos.Networking.Abstractions; using Chaos.Services.Other.Abstractions; +#endregion namespace Chaos.Messaging; @@ -19,6 +21,8 @@ public ValueTask ExecuteAsync(Aisling source, ArgumentCollection args) if (!args.TryGetNext(out var targetName)) return default; + targetName = targetName.ReplaceI("_", " "); + var targetClient = ClientRegistry.FirstOrDefault(c => c.Aisling.Name.EqualsI(targetName)); if ((targetClient == null) || (source.IsAdmin != targetClient.Aisling.IsAdmin)) diff --git a/Chaos/Scripting/ReactorTileScripts/LeaderboardScript.cs b/Chaos/Scripting/ReactorTileScripts/LeaderboardScript.cs index 8674acfe28..0f0bec803a 100644 --- a/Chaos/Scripting/ReactorTileScripts/LeaderboardScript.cs +++ b/Chaos/Scripting/ReactorTileScripts/LeaderboardScript.cs @@ -15,7 +15,7 @@ public class LeaderboardScript : ReactorTileScriptBase /// public LeaderboardScript(ReactorTile subject, IStorage storage) : base(subject) - => Leaderboard = storage.GetInstance("test_leaderboard"); + => Leaderboard = storage; /// public override void OnClicked(Aisling source) @@ -42,6 +42,6 @@ public override void OnClicked(Aisling source) public sealed class LeaderboardObj { - public Dictionary Entries { get; } = new(StringComparer.OrdinalIgnoreCase); + public Dictionary Entries { get; set; } = new(StringComparer.OrdinalIgnoreCase); } } \ No newline at end of file diff --git a/Chaos/Services/Other/Abstractions/IGroupService.cs b/Chaos/Services/Other/Abstractions/IGroupService.cs index 3c030ede3c..784f7fa195 100644 --- a/Chaos/Services/Other/Abstractions/IGroupService.cs +++ b/Chaos/Services/Other/Abstractions/IGroupService.cs @@ -1,4 +1,6 @@ +#region using Chaos.Models.World; +#endregion namespace Chaos.Services.Other.Abstractions; @@ -14,5 +16,7 @@ enum RequestType void AcceptRequestToJoin(Aisling sender, Aisling receiver); RequestType? DetermineRequestType(Aisling sender, Aisling receiver); void Invite(Aisling sender, Aisling receiver); + void Kick(Aisling sender, Aisling receiver); + void Promote(Aisling sender, Aisling receiver); void RequestToJoin(Aisling sender, Aisling receiver); } \ No newline at end of file diff --git a/Chaos/Services/Other/GroupService.cs b/Chaos/Services/Other/GroupService.cs index b41a8501a9..d1867a2b70 100644 --- a/Chaos/Services/Other/GroupService.cs +++ b/Chaos/Services/Other/GroupService.cs @@ -219,6 +219,64 @@ public void Invite(Aisling sender, Aisling receiver) } } + /// + public void Kick(Aisling sender, Aisling receiver) + { + var group = sender.Group; + + if (group is null) + { + sender.SendActiveMessage("You are not in a group"); + + return; + } + + if (group != receiver.Group) + { + sender.SendActiveMessage("You are not in the same group"); + + return; + } + + if (!group.Leader.Equals(sender)) + { + sender.SendActiveMessage("You are not the group leader"); + + return; + } + + group.Kick(receiver); + } + + /// + public void Promote(Aisling sender, Aisling receiver) + { + var group = sender.Group; + + if (group is null) + { + sender.SendActiveMessage("You are not in a group"); + + return; + } + + if (group != receiver.Group) + { + sender.SendActiveMessage("You are not in the same group"); + + return; + } + + if (!group.Leader.Equals(sender)) + { + sender.SendActiveMessage("You are not the group leader"); + + return; + } + + group.Promote(receiver); + } + public void RequestToJoin(Aisling sender, Aisling receiver) { using var @lock = Sync.EnterScope(); diff --git a/Chaos/Services/Servers/WorldServer.cs b/Chaos/Services/Servers/WorldServer.cs index 8818ba3937..7e91ae4430 100644 --- a/Chaos/Services/Servers/WorldServer.cs +++ b/Chaos/Services/Servers/WorldServer.cs @@ -742,6 +742,8 @@ public ValueTask OnGroupInvite(IChaosWorldClient client, in Packet packet) ValueTask InnerOnGroupInvite(IChaosWorldClient localClient, GroupInviteArgs localArgs) { + localArgs.TargetName = localArgs.TargetName.ReplaceI("_", " "); + var target = Aislings.FirstOrDefault(user => user.Name.EqualsI(localArgs.TargetName)); if (target == null) diff --git a/Data/LocalStorage/LeaderboardObj.json b/Data/LocalStorage/LeaderboardObj.json new file mode 100644 index 0000000000..11e56101d8 --- /dev/null +++ b/Data/LocalStorage/LeaderboardObj.json @@ -0,0 +1,7 @@ +{ + "default": { + "entries": { + "mink": 4 + } + } +} \ No newline at end of file diff --git a/Data/LocalStorage/LeaderboardObj.json.bak b/Data/LocalStorage/LeaderboardObj.json.bak new file mode 100644 index 0000000000..e921633aad --- /dev/null +++ b/Data/LocalStorage/LeaderboardObj.json.bak @@ -0,0 +1,7 @@ +{ + "default": { + "entries": { + "mink": 3 + } + } +} \ No newline at end of file diff --git a/Tools/SeqConfigurator/Program.cs b/Tools/SeqConfigurator/Program.cs index d2cf362ecd..49e4ab5ee0 100644 --- a/Tools/SeqConfigurator/Program.cs +++ b/Tools/SeqConfigurator/Program.cs @@ -1,4 +1,5 @@ -using System.Reflection; +#region +using System.Reflection; using Chaos.Extensions.Common; using Chaos.NLog.Logging.Definitions; using NLog; @@ -6,6 +7,7 @@ using Seq.Api.Model.Dashboarding; using Seq.Api.Model.Signals; using SeqConfigurator.Builders; +#endregion using var seq = new SeqConnection("http://localhost:5341", "AdminGuestSeqToken"); await seq.EnsureConnectedAsync(TimeSpan.FromSeconds(30)); @@ -114,6 +116,7 @@ await DashboardBuilder.Create(seq) .WithCharts( BuildMapCountChart, BuildAislingCountChart, + BuildUniqueIpAddressesChart, BuildDeltasChart, BuildAverageDeltasChart, BuildUpperDeltasChart) @@ -161,6 +164,14 @@ static void BuildAislingCountChart(ChartBuilder chartBuilder) .WithWhere("Has(AislingName)") .WithDisplayStyle(MeasurementDisplayType.Line, false, true)); +static void BuildUniqueIpAddressesChart(ChartBuilder chartBuilder) + => chartBuilder.WithTitle("Unique Ip Addresses") + .WithDimensions(12, 2) + .WithQuery( + queryBuilder => queryBuilder.WithSelect(("UniqueIpAddresses", "count(distinct(Aisling.IpAddress))")) + .WithWhere("Has(Aisling)") + .WithDisplayStyle(MeasurementDisplayType.Line, false, true)); + static void BuildMapCountChart(ChartBuilder chartBuilder) => chartBuilder.WithTitle("MapCount") .WithSignalExpression("DeltaMonitor")