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)
|
(int GroupId, Func<TextCommandResult> Action)
|
||||||
> PendingActions = new();
|
> PendingActions = new();
|
||||||
|
|
||||||
|
internal static readonly Dictionary<string, string> LastCancelReason = new();
|
||||||
|
|
||||||
private static TextCommandResult Stage(
|
private static TextCommandResult Stage(
|
||||||
string playerUid,
|
string playerUid,
|
||||||
int groupId,
|
int groupId,
|
||||||
@@ -203,12 +205,13 @@ public static class ClaimLinkChatCommand
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
PendingActions[playerUid] = (groupId, action);
|
PendingActions[playerUid] = (groupId, action);
|
||||||
|
LastCancelReason.Remove(playerUid);
|
||||||
return TextCommandResult.Success(
|
return TextCommandResult.Success(
|
||||||
$"{prompt} Use /claimlink confirm to proceed, or /claimlink cancel to cancel."
|
$"{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;
|
List<string>? toRemove = null;
|
||||||
foreach (var (uid, entry) in PendingActions)
|
foreach (var (uid, entry) in PendingActions)
|
||||||
@@ -219,7 +222,19 @@ public static class ClaimLinkChatCommand
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (string uid in toRemove)
|
foreach (string uid in toRemove)
|
||||||
|
{
|
||||||
PendingActions.Remove(uid);
|
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)
|
private static TextCommandResult? TryResolveGroup(string groupName, out PlayerGroup group)
|
||||||
@@ -299,9 +314,14 @@ public static class ClaimLinkChatCommand
|
|||||||
string playerUid = args.Caller.Player.PlayerUID;
|
string playerUid = args.Caller.Player.PlayerUID;
|
||||||
|
|
||||||
if (!PendingActions.TryGetValue(playerUid, out var pending))
|
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.");
|
return TextCommandResult.Error("You do not have a pending action.");
|
||||||
|
}
|
||||||
|
|
||||||
PendingActions.Remove(playerUid);
|
PendingActions.Remove(playerUid);
|
||||||
|
LastCancelReason.Remove(playerUid);
|
||||||
return pending.Action();
|
return pending.Action();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +478,7 @@ public static class ClaimLinkChatCommand
|
|||||||
$"'{groupName}' will be deleted as a claim link.",
|
$"'{groupName}' will be deleted as a claim link.",
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
RemovePendingActionsForGroup(groupId);
|
RemovePendingActionsForGroup(groupId, "claim link was deleted");
|
||||||
ClaimLinkModSystem.Registry.Remove(groupId);
|
ClaimLinkModSystem.Registry.Remove(groupId);
|
||||||
return TextCommandResult.Success($"'{groupName}' is no longer a claim link.");
|
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);
|
ClaimLinkModSystem.Registry.Remove(groupId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,27 +173,89 @@ public class GroupCommandListener : ICommandHookListener
|
|||||||
public CommandRegistration Registration => new(Before, After);
|
public CommandRegistration Registration => new(Before, After);
|
||||||
|
|
||||||
internal static Dictionary<string, int> PendingDisbands = new Dictionary<string, int>();
|
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)
|
private TextCommandResult? Before(TextCommandCallingArgs args)
|
||||||
{
|
{
|
||||||
if (args.Caller.Player == null)
|
if (args.Caller.Player == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
string callerUid = args.Caller.Player.PlayerUID;
|
||||||
CmdArgs rawArgs = args.RawArgs.Clone();
|
CmdArgs rawArgs = args.RawArgs.Clone();
|
||||||
if (rawArgs.PopWord() != "confirmdisband")
|
string? word = rawArgs.PopWord();
|
||||||
return null;
|
|
||||||
|
|
||||||
|
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();
|
string? name = rawArgs.PopWord();
|
||||||
int? groupId =
|
int? groupId =
|
||||||
name != null
|
name != null
|
||||||
? ClaimLinkModSystem.Groups.GetPlayerGroupByName(name)?.Uid
|
? ClaimLinkModSystem.Groups.GetPlayerGroupByName(name)?.Uid
|
||||||
: args.Caller.FromChatGroupId;
|
: args.Caller.FromChatGroupId;
|
||||||
|
|
||||||
if (groupId == null)
|
if (groupId != null)
|
||||||
return null;
|
PendingDisbands[callerUid] = (int)groupId;
|
||||||
|
}
|
||||||
|
|
||||||
PendingDisbands[args.Caller.Player.PlayerUID] = (int)groupId;
|
private static void Leave(TextCommandCallingArgs args, string callerUid, CmdArgs rawArgs)
|
||||||
return null;
|
{
|
||||||
|
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)
|
private void After(TextCommandCallingArgs args, TextCommandResult result)
|
||||||
@@ -201,23 +263,45 @@ public class GroupCommandListener : ICommandHookListener
|
|||||||
if (args.Caller.Player == null)
|
if (args.Caller.Player == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string uid = args.Caller.Player.PlayerUID;
|
string callerUid = args.Caller.Player.PlayerUID;
|
||||||
if (!PendingDisbands.TryGetValue(uid, out int groupId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
PendingDisbands.Remove(uid);
|
if (PendingDisbands.TryGetValue(callerUid, out int disbandedGroupId))
|
||||||
|
{
|
||||||
|
PendingDisbands.Remove(callerUid);
|
||||||
|
|
||||||
if (ClaimLinkModSystem.Groups.PlayerGroupsById.ContainsKey(groupId))
|
if (!ClaimLinkModSystem.Groups.PlayerGroupsById.ContainsKey(disbandedGroupId))
|
||||||
return;
|
{
|
||||||
|
ClaimLinkChatCommand.RemovePendingActionsForGroup(
|
||||||
|
disbandedGroupId,
|
||||||
|
"group no longer exists"
|
||||||
|
);
|
||||||
|
|
||||||
ClaimLinkChatCommand.RemovePendingActionsForGroup(groupId);
|
if (ClaimLinkModSystem.Registry.Exists(disbandedGroupId))
|
||||||
|
ClaimLinkModSystem.Registry.Remove(disbandedGroupId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ClaimLinkModSystem.Registry.Exists(groupId))
|
if (PendingMembershipChecks.TryGetValue(callerUid, out var check))
|
||||||
ClaimLinkModSystem.Registry.Remove(groupId);
|
{
|
||||||
|
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)
|
internal static void OnPlayerDisconnect(IServerPlayer player)
|
||||||
{
|
{
|
||||||
PendingDisbands.Remove(player.PlayerUID);
|
PendingDisbands.Remove(player.PlayerUID);
|
||||||
|
PendingMembershipChecks.Remove(player.PlayerUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user