feat: hook group leave/kick to proactively cancel pending actions with a reason

This commit is contained in:
2026-07-26 10:33:46 +02:00
parent 1c079b7e44
commit 99238c4744
2 changed files with 122 additions and 18 deletions
+23 -3
View File
@@ -195,6 +195,8 @@ public static class ClaimLinkChatCommand
(int GroupId, Func<TextCommandResult> Action)
> PendingActions = new();
internal static readonly Dictionary<string, string> LastCancelReason = new();
private static TextCommandResult Stage(
string playerUid,
int groupId,
@@ -203,12 +205,13 @@ public static class ClaimLinkChatCommand
)
{
PendingActions[playerUid] = (groupId, action);
LastCancelReason.Remove(playerUid);
return TextCommandResult.Success(
$"{prompt} Use /claimlink confirm to proceed, or /claimlink cancel to cancel."
);
}
internal static void RemovePendingActionsForGroup(int groupId)
internal static void RemovePendingActionsForGroup(int groupId, string reason)
{
List<string>? toRemove = null;
foreach (var (uid, entry) in PendingActions)
@@ -219,7 +222,19 @@ public static class ClaimLinkChatCommand
return;
foreach (string uid in toRemove)
{
PendingActions.Remove(uid);
LastCancelReason[uid] = reason;
}
}
internal static void CancelPendingAction(string uid, int groupId, string reason)
{
if (!PendingActions.TryGetValue(uid, out var pending) || pending.GroupId != groupId)
return;
PendingActions.Remove(uid);
LastCancelReason[uid] = reason;
}
private static TextCommandResult? TryResolveGroup(string groupName, out PlayerGroup group)
@@ -299,9 +314,14 @@ public static class ClaimLinkChatCommand
string playerUid = args.Caller.Player.PlayerUID;
if (!PendingActions.TryGetValue(playerUid, out var pending))
{
if (LastCancelReason.Remove(playerUid, out string? reason))
return TextCommandResult.Error($"You do not have a pending action ({reason}).");
return TextCommandResult.Error("You do not have a pending action.");
}
PendingActions.Remove(playerUid);
LastCancelReason.Remove(playerUid);
return pending.Action();
}
@@ -458,7 +478,7 @@ public static class ClaimLinkChatCommand
$"'{groupName}' will be deleted as a claim link.",
() =>
{
RemovePendingActionsForGroup(groupId);
RemovePendingActionsForGroup(groupId, "claim link was deleted");
ClaimLinkModSystem.Registry.Remove(groupId);
return TextCommandResult.Success($"'{groupName}' is no longer a claim link.");
}
@@ -608,7 +628,7 @@ public static class ClaimLinkChatCommand
)
)
{
RemovePendingActionsForGroup(groupId);
RemovePendingActionsForGroup(groupId, "group no longer exists");
ClaimLinkModSystem.Registry.Remove(groupId);
continue;
}
+99 -15
View File
@@ -173,27 +173,89 @@ public class GroupCommandListener : ICommandHookListener
public CommandRegistration Registration => new(Before, After);
internal static Dictionary<string, int> PendingDisbands = new Dictionary<string, int>();
internal static Dictionary<string, (string AffectedUid, int GroupId)> PendingMembershipChecks =
new Dictionary<string, (string, int)>();
private TextCommandResult? Before(TextCommandCallingArgs args)
{
if (args.Caller.Player == null)
return null;
string callerUid = args.Caller.Player.PlayerUID;
CmdArgs rawArgs = args.RawArgs.Clone();
if (rawArgs.PopWord() != "confirmdisband")
return null;
string? word = rawArgs.PopWord();
switch (word)
{
case "confirmdisband":
ConfirmDisband(args, callerUid, rawArgs);
break;
case "leave":
Leave(args, callerUid, rawArgs);
break;
case "kick":
Kick(args, callerUid, rawArgs);
break;
}
return null;
}
private static void ConfirmDisband(
TextCommandCallingArgs args,
string callerUid,
CmdArgs rawArgs
)
{
string? name = rawArgs.PopWord();
int? groupId =
name != null
? ClaimLinkModSystem.Groups.GetPlayerGroupByName(name)?.Uid
: args.Caller.FromChatGroupId;
if (groupId == null)
return null;
if (groupId != null)
PendingDisbands[callerUid] = (int)groupId;
}
PendingDisbands[args.Caller.Player.PlayerUID] = (int)groupId;
return null;
private static void Leave(TextCommandCallingArgs args, string callerUid, CmdArgs rawArgs)
{
string? name = rawArgs.PopWord();
int? groupId =
name != null
? ClaimLinkModSystem.Groups.GetPlayerGroupByName(name)?.Uid
: args.Caller.FromChatGroupId;
if (groupId != null)
PendingMembershipChecks[callerUid] = (callerUid, (int)groupId);
}
private static void Kick(TextCommandCallingArgs args, string callerUid, CmdArgs rawArgs)
{
string? word1 = rawArgs.PopWord();
string? word2 = rawArgs.PopWord();
string? targetName;
int? groupId;
if (word2 != null)
{
groupId =
word1 != null ? ClaimLinkModSystem.Groups.GetPlayerGroupByName(word1)?.Uid : null;
targetName = word2;
}
else
{
targetName = word1;
groupId = args.Caller.FromChatGroupId;
}
if (targetName == null || groupId == null)
return;
string? targetUid = ClaimLinkModSystem
.PlayerData.GetPlayerDataByLastKnownName(targetName)
?.PlayerUID;
if (targetUid != null)
PendingMembershipChecks[callerUid] = (targetUid, (int)groupId);
}
private void After(TextCommandCallingArgs args, TextCommandResult result)
@@ -201,23 +263,45 @@ public class GroupCommandListener : ICommandHookListener
if (args.Caller.Player == null)
return;
string uid = args.Caller.Player.PlayerUID;
if (!PendingDisbands.TryGetValue(uid, out int groupId))
return;
string callerUid = args.Caller.Player.PlayerUID;
PendingDisbands.Remove(uid);
if (PendingDisbands.TryGetValue(callerUid, out int disbandedGroupId))
{
PendingDisbands.Remove(callerUid);
if (ClaimLinkModSystem.Groups.PlayerGroupsById.ContainsKey(groupId))
return;
if (!ClaimLinkModSystem.Groups.PlayerGroupsById.ContainsKey(disbandedGroupId))
{
ClaimLinkChatCommand.RemovePendingActionsForGroup(
disbandedGroupId,
"group no longer exists"
);
ClaimLinkChatCommand.RemovePendingActionsForGroup(groupId);
if (ClaimLinkModSystem.Registry.Exists(disbandedGroupId))
ClaimLinkModSystem.Registry.Remove(disbandedGroupId);
}
}
if (ClaimLinkModSystem.Registry.Exists(groupId))
ClaimLinkModSystem.Registry.Remove(groupId);
if (PendingMembershipChecks.TryGetValue(callerUid, out var check))
{
PendingMembershipChecks.Remove(callerUid);
bool stillMember =
ClaimLinkModSystem
.PlayerData.GetPlayerDataByUid(check.AffectedUid)
?.PlayerGroupMemberships.ContainsKey(check.GroupId) == true;
if (!stillMember)
ClaimLinkChatCommand.CancelPendingAction(
check.AffectedUid,
check.GroupId,
"you are no longer a member of the group"
);
}
}
internal static void OnPlayerDisconnect(IServerPlayer player)
{
PendingDisbands.Remove(player.PlayerUID);
PendingMembershipChecks.Remove(player.PlayerUID);
}
}