feat: hook /land claim load/cancel and dump claim info via admin info

Intercepts vanilla /land claim load|cancel to track a per-player
pending claim selection, and wires LandClaimAPI/Logger through
ModSystem so admin info can dump full claim state for debugging.
This commit is contained in:
2026-07-12 16:13:06 +02:00
parent 9206ecd6a9
commit 5c7fa58ea2
3 changed files with 118 additions and 3 deletions
+45 -1
View File
@@ -127,5 +127,49 @@ public static class ClaimLinkChatCommand
public static TextCommandResult AdminUnlink(TextCommandCallingArgs args) => TextCommandResult.Success("stub: claimlink admin unlink");
public static TextCommandResult AdminKick(TextCommandCallingArgs args) => TextCommandResult.Success("stub: claimlink admin kick");
public static TextCommandResult AdminTransferOwnership(TextCommandCallingArgs args) => TextCommandResult.Success("stub: claimlink admin transferownership");
public static TextCommandResult AdminInfo(TextCommandCallingArgs args) => TextCommandResult.Success("stub: claimlink admin info");
public static TextCommandResult AdminInfo(TextCommandCallingArgs args)
{
ClaimLinkModSystem.Logger.Notification("Number of Claims: {0}", ClaimLinkModSystem.LandClaimAPI.All.Count);
foreach (LandClaim claim in ClaimLinkModSystem.LandClaimAPI.All)
{
string padding = new string('-', claim.Description.Length);
ClaimLinkModSystem.Logger.Notification("---{0}---", claim.Description);
ClaimLinkModSystem.Logger.Notification("Owner (Entity ID): {0}", claim.OwnedByEntityId);
ClaimLinkModSystem.Logger.Notification("Owner (Player UID): {0}", claim.OwnedByPlayerUid);
ClaimLinkModSystem.Logger.Notification("Last Known Owner Name: {0}", claim.LastKnownOwnerName);
ClaimLinkModSystem.Logger.Notification("Permitted Player Group IDs({0})", claim.PermittedPlayerGroupIds.Count);
foreach (var groupId in claim.PermittedPlayerGroupIds)
{
ClaimLinkModSystem.Logger.Notification(" <{0},{1}>", groupId.Key, groupId.Value);
}
ClaimLinkModSystem.Logger.Notification("Permitted Player UIDs({0})", claim.PermittedPlayerUids.Count);
foreach (var permittedPlayerUid in claim.PermittedPlayerUids)
{
ClaimLinkModSystem.Logger.Notification(" <{0},{1}>", permittedPlayerUid.Key, permittedPlayerUid.Value);
}
ClaimLinkModSystem.Logger.Notification("Permitted Player Last Known Player Name({0})", claim.PermittedPlayerLastKnownPlayerName.Count);
foreach (var permittedPlayerLastKnownPlayerName in claim.PermittedPlayerLastKnownPlayerName)
{
ClaimLinkModSystem.Logger.Notification(" <{0},{1}>", permittedPlayerLastKnownPlayerName.Key, permittedPlayerLastKnownPlayerName.Value);
}
ClaimLinkModSystem.Logger.Notification("Owner (Player Group UID): {0}", claim.OwnedByPlayerGroupUid);
ClaimLinkModSystem.Logger.Notification("Protection Level: {0}", claim.ProtectionLevel);
ClaimLinkModSystem.Logger.Notification("Center: ({0}, {1}, {2})", claim.Center.X, claim.Center.Y, claim.Center.Z);
ClaimLinkModSystem.Logger.Notification("Size XYZ: ({0})", claim.SizeXYZ);
ClaimLinkModSystem.Logger.Notification("Size XZ: ({0})", claim.SizeXZ);
ClaimLinkModSystem.Logger.Notification("Areas ({0}):", claim.Areas.Count);
for (int i = 0; i < claim.Areas.Count; i++)
{
var area = claim.Areas[i];
ClaimLinkModSystem.Logger.Notification(
" [{0}] Min: ({1}, {2}, {3}) Max: ({4}, {5}, {6})",
i, area.X1, area.Y1, area.Z1, area.X2, area.Y2, area.Z2
);
}
ClaimLinkModSystem.Logger.Notification("---{0}---\n", padding);
}
return TextCommandResult.Success("stub: claimlink admin info");
}
}
+7 -1
View File
@@ -6,16 +6,22 @@ namespace ClaimLink;
public class ClaimLinkModSystem : ModSystem
{
internal static ILandClaimAPI LandClaimAPI;
internal static ILogger Logger;
internal ClaimLinkCommandListener? cmdListener;
public override bool ShouldLoad(EnumAppSide forSide) => forSide == EnumAppSide.Server;
public override void StartServerSide(ICoreServerAPI api)
{
LandClaimAPI = api.World.Claims;
Logger = api.Logger;
cmdListener = new ClaimLinkCommandListener();
CommandHookModSystem.Register(cmdListener);
ClaimLinkChatCommand.Register(api);
api.Event.PlayerDisconnect += ClaimLinkCommandListener.OnPlayerDisconnect;
}
public override void Dispose()
+65
View File
@@ -1,6 +1,7 @@
using Vintagestory.API.Common;
using System.Collections.Generic;
using CommandHook;
using Vintagestory.API.Server;
namespace ClaimLink;
@@ -12,13 +13,77 @@ public class ClaimLinkCommandListener : ICommandHookListener
public CommandRegistration Registration => new(Before, After);
private static Dictionary<string, int> pendingLoads = new Dictionary<string, int>();
private TextCommandResult? Before(TextCommandCallingArgs args)
{
CmdArgs rawArgs = args.RawArgs.Clone();
while (rawArgs.Length > 0)
{
switch (rawArgs.PeekWord())
{
case "claim":
rawArgs.PopWord();
handleClaim(args.Caller, rawArgs);
break;
default:
rawArgs.PopWord();
break;
}
}
return null;
}
private void After(TextCommandCallingArgs args, TextCommandResult result)
{
}
private void handleClaim(Caller caller, CmdArgs args)
{
switch (args.PeekWord())
{
case "load":
if (caller.Player == null)
break;
args.PopWord();
int? claimIndex = args.PopInt();
if (claimIndex == null || claimIndex < 0 || claimIndex > 999)
break;
List<LandClaim> claims = ClaimLinkModSystem.LandClaimAPI.All, ownedClaims = new List<LandClaim>();
List<int> globalIndex = new List<int>();
for (int i = 0; i < claims.Count; ++i)
{
if (claims[i].OwnedByPlayerUid != caller.Player.PlayerUID)
continue;
globalIndex.Add(i);
ownedClaims.Add(claims[i]);
}
if (claimIndex >= ownedClaims.Count)
break;
pendingLoads[caller.Player.PlayerUID] = globalIndex[(int)claimIndex];
break;
case "cancel":
if (caller.Player == null)
break;
args.PopWord();
pendingLoads.Remove(caller.Player.PlayerUID);
break;
default:
break;
}
}
internal static void OnPlayerDisconnect(IServerPlayer player)
{
pendingLoads.Remove(player.PlayerUID);
}
}