From 94b67234564ebae560b4ba5e425a712a11065405 Mon Sep 17 00:00:00 2001 From: anth64 Date: Sat, 18 Jul 2026 11:47:52 +0200 Subject: [PATCH] feat: sanity-check claim save/free against tracked ordering state --- ClaimLink/ClaimLinkModSystem.cs | 15 +++++++++++++ ClaimLink/LandCommandListener.cs | 37 ++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ClaimLink/ClaimLinkModSystem.cs b/ClaimLink/ClaimLinkModSystem.cs index bf22379..e7bcebb 100644 --- a/ClaimLink/ClaimLinkModSystem.cs +++ b/ClaimLink/ClaimLinkModSystem.cs @@ -66,4 +66,19 @@ public class ClaimLinkModSystem : ModSystem claim = null; return false; } + + internal static bool TryResolveClaimIndex(string ownerPlayerUid, LandClaim target, out int claimIndex) + { + foreach ((int index, LandClaim c) in EnumerateOwnedClaims(ownerPlayerUid)) + { + if (ReferenceEquals(c, target)) + { + claimIndex = index; + return true; + } + } + + claimIndex = -1; + return false; + } } diff --git a/ClaimLink/LandCommandListener.cs b/ClaimLink/LandCommandListener.cs index bda82f0..601d6ba 100644 --- a/ClaimLink/LandCommandListener.cs +++ b/ClaimLink/LandCommandListener.cs @@ -110,7 +110,26 @@ public class ClaimLinkCommandListener : ICommandHookListener PendingLoads.Remove(caller.Player.PlayerUID); } - private static void Free(Caller caller, CmdArgs args, TextCommandResult? result) { } + private static void Free(Caller caller, CmdArgs args, TextCommandResult? result) + { + if (result == null || result.Status != EnumCommandStatus.Success || caller.Player == null) + return; + + string uid = caller.Player.PlayerUID; + int? claimIndex = args.PopInt(); + if (claimIndex == null) + return; + + if (args.PopWord() != "confirm") + return; + + ClaimLink? link = ClaimLinkModSystem.Registry.FindLinkContaining(uid, (int)claimIndex); + ClaimLinkModSystem.Logger.Notification( + link != null + ? $"claimlink: freed claim {claimIndex} for {uid} was linked to group {link.GroupId}" + : $"claimlink: freed claim {claimIndex} for {uid} was not linked" + ); + } private static void Info(Caller caller, CmdArgs args, TextCommandResult? result) { } @@ -148,7 +167,21 @@ public class ClaimLinkCommandListener : ICommandHookListener private static void ClaimFullHeight(Caller caller, CmdArgs args, TextCommandResult? result) { } - private static void ClaimSave(Caller caller, CmdArgs args, TextCommandResult? result) { } + private static void ClaimSave(Caller caller, CmdArgs args, TextCommandResult? result) + { + if (result == null || result.Status != EnumCommandStatus.Success || caller.Player == null) + return; + + string uid = caller.Player.PlayerUID; + int? claimIndex = args.PopInt(); + + if (PendingLoads.TryGetValue(uid, out int pendingIndex) && claimIndex != pendingIndex) + ClaimLinkModSystem.Logger.Error( + $"claimlink: claim save index mismatch for {uid}: pending={pendingIndex} saved={claimIndex}" + ); + + PendingLoads.Remove(uid); + } private static void ClaimDownload(Caller caller, CmdArgs args, TextCommandResult? result) { }