feat: hook group leave/kick to proactively cancel pending actions with a reason
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user