fix: guard claim-link entries against stale indices and dead groups

This commit is contained in:
2026-07-20 23:28:37 +02:00
parent fc7e601f5b
commit 2e4cc25b20
4 changed files with 33 additions and 16 deletions
+9 -4
View File
@@ -326,9 +326,12 @@ public static class ClaimLinkChatCommand
$"{claimDesc} will be linked into '{groupName}'.", $"{claimDesc} will be linked into '{groupName}'.",
() => () =>
{ {
ClaimLinkModSystem.Registry.AddEntry(playerUid, groupId, claimIndex); bool success = ClaimLinkModSystem.Registry.AddEntry(playerUid, groupId, claimIndex);
return success
return TextCommandResult.Success($"Linked {claimDesc} to '{groupName}'."); ? TextCommandResult.Success($"Linked {claimDesc} to '{groupName}'.")
: TextCommandResult.Error(
$"Unable to link {claimIndex} to '{groupName}' it is currently being modified."
);
} }
); );
} }
@@ -546,7 +549,9 @@ public static class ClaimLinkChatCommand
public static TextCommandResult List(TextCommandCallingArgs args) public static TextCommandResult List(TextCommandCallingArgs args)
{ {
List<int> groupIds = ClaimLinkModSystem List<int> groupIds = ClaimLinkModSystem
.Registry.All.OrderByDescending(id => ClaimLinkModSystem.Registry.MemberCountForGroup(id)) .Registry.All.OrderByDescending(id =>
ClaimLinkModSystem.Registry.MemberCountForGroup(id)
)
.ToList(); .ToList();
if (groupIds.Count == 0) if (groupIds.Count == 0)
+2 -2
View File
@@ -19,10 +19,10 @@ public class ClaimLinkModSystem : ModSystem
public override void StartServerSide(ICoreServerAPI api) public override void StartServerSide(ICoreServerAPI api)
{ {
LandClaimAPI = api.World.Claims; LandClaimAPI = api.World.Claims;
World = api.World;
Groups = api.Groups;
Logger = api.Logger; Logger = api.Logger;
Registry = new ClaimLinkRegistry(api.WorldManager.SaveGame); Registry = new ClaimLinkRegistry(api.WorldManager.SaveGame);
Groups = api.Groups;
World = api.World;
CmdListener = new ClaimLinkCommandListener(); CmdListener = new ClaimLinkCommandListener();
CommandHookModSystem.Register(CmdListener); CommandHookModSystem.Register(CmdListener);
+17 -10
View File
@@ -63,14 +63,19 @@ public class ClaimLinkRegistry
return null; return null;
} }
public void AddEntry(string uid, int groupId, int claimIndex) public bool AddEntry(string uid, int groupId, int claimIndex)
{ {
if (ClaimLinkCommandListener.PendingLoads.ContainsKey(uid))
return false;
if (!Exists(groupId))
return false;
if (!entries.TryGetValue(uid, out var groups)) if (!entries.TryGetValue(uid, out var groups))
entries[uid] = groups = new(); entries[uid] = groups = new();
if (!groups.TryGetValue(groupId, out var claims)) if (!groups.TryGetValue(groupId, out var claims))
groups[groupId] = claims = new(); groups[groupId] = claims = new();
claims.Add(claimIndex); claims.Add(claimIndex);
Save(); Save();
return true;
} }
public void RemoveEntry(string uid, int groupId, int claimIndex) public void RemoveEntry(string uid, int groupId, int claimIndex)
@@ -93,6 +98,7 @@ public class ClaimLinkRegistry
if (claims[i] > removedIndex) if (claims[i] > removedIndex)
claims[i]--; claims[i]--;
} }
Prune(); Prune();
Save(); Save();
} }
@@ -119,6 +125,7 @@ public class ClaimLinkRegistry
if (i >= 0) if (i >= 0)
claims[i] = newIndex; claims[i] = newIndex;
} }
Save(); Save();
} }
@@ -170,15 +177,15 @@ public class ClaimLinkRegistry
{ {
var entryList = new List<ClaimLinkEntrySaveData>(); var entryList = new List<ClaimLinkEntrySaveData>();
foreach (var (uid, groups) in entries) foreach (var (uid, groups) in entries)
foreach (var (groupId, claims) in groups) foreach (var (groupId, claims) in groups)
entryList.Add( entryList.Add(
new ClaimLinkEntrySaveData new ClaimLinkEntrySaveData
{ {
OwnerPlayerUid = uid, OwnerPlayerUid = uid,
GroupId = groupId, GroupId = groupId,
ClaimIndicies = new(claims), ClaimIndicies = new(claims),
} }
); );
saveGame.StoreData( saveGame.StoreData(
SaveKey, SaveKey,
+5
View File
@@ -83,6 +83,7 @@ public class ClaimLinkCommandListener : ICommandHookListener
ClaimLinkModSystem.Registry.ClaimSaved(uid, pendingIndex); ClaimLinkModSystem.Registry.ClaimSaved(uid, pendingIndex);
PendingLoads.Remove(uid); PendingLoads.Remove(uid);
ClaimLinkChatCommand.PendingActions.Remove(uid);
} }
private static void ClaimLoad(Caller caller, CmdArgs args) private static void ClaimLoad(Caller caller, CmdArgs args)
@@ -119,6 +120,7 @@ public class ClaimLinkCommandListener : ICommandHookListener
return; return;
ClaimLinkModSystem.Registry.ClaimRemoved(uid, (int)claimIndex); ClaimLinkModSystem.Registry.ClaimRemoved(uid, (int)claimIndex);
ClaimLinkChatCommand.PendingActions.Remove(uid);
} }
private static void AdminFree(Caller caller, CmdArgs args) private static void AdminFree(Caller caller, CmdArgs args)
@@ -132,7 +134,10 @@ public class ClaimLinkCommandListener : ICommandHookListener
foreach (LandClaim c in claims) foreach (LandClaim c in claims)
if (ClaimLinkModSystem.TryResolveClaimIndex(c.OwnedByPlayerUid, c, out int claimIndex)) if (ClaimLinkModSystem.TryResolveClaimIndex(c.OwnedByPlayerUid, c, out int claimIndex))
{
ClaimLinkModSystem.Registry.ClaimRemoved(c.OwnedByPlayerUid, claimIndex); ClaimLinkModSystem.Registry.ClaimRemoved(c.OwnedByPlayerUid, claimIndex);
ClaimLinkChatCommand.PendingActions.Remove(c.OwnedByPlayerUid);
}
} }
internal static void OnPlayerDisconnect(IServerPlayer player) internal static void OnPlayerDisconnect(IServerPlayer player)