The server now pushes buffer and permission state to clients continuously: a full sync when a player joins, and an incremental delta on every registry mutation, mirroring vanilla's own land claim sync model. ClaimLinkBufferIndex is now instantiable, so the client and server each get their own region-indexed lookup built from the same algorithm.
161 lines
5.2 KiB
C#
161 lines
5.2 KiB
C#
using System.Collections.Generic;
|
|
using Vintagestory.API.Client;
|
|
using Vintagestory.API.Common;
|
|
using Vintagestory.API.Server;
|
|
|
|
namespace ClaimLink;
|
|
|
|
public class ClaimLinkModSystem : ModSystem
|
|
{
|
|
internal static ILandClaimAPI LandClaimAPI = null!;
|
|
internal static ILogger Logger = null!;
|
|
internal static ClaimLinkRegistry Registry = null!;
|
|
internal static IGroupManager Groups = null!;
|
|
internal static IWorldAccessor World = null!;
|
|
internal static IWorldManagerAPI WorldManager = null!;
|
|
internal static IPlayerDataManager PlayerData = null!;
|
|
internal static ClaimLinkConfig Config = null!;
|
|
internal static ClaimLinkBufferIndex BufferIndex = null!;
|
|
private object? cmdListenerProxy;
|
|
private object? groupCmdListenerProxy;
|
|
|
|
public override void StartServerSide(ICoreServerAPI api)
|
|
{
|
|
LandClaimAPI = api.World.Claims;
|
|
World = api.World;
|
|
WorldManager = api.WorldManager;
|
|
Groups = api.Groups;
|
|
Logger = api.Logger;
|
|
PlayerData = api.PlayerData;
|
|
Config = api.LoadModConfig<ClaimLinkConfig>("claimlink.json") ?? new ClaimLinkConfig();
|
|
api.StoreModConfig(Config, "claimlink.json");
|
|
Registry = new ClaimLinkRegistry(api.WorldManager.SaveGame);
|
|
BufferIndex = new ClaimLinkBufferIndex(WorldManager.MapRegionIndex2D);
|
|
RebuildBufferIndex();
|
|
api.Event.SaveGameLoaded += RebuildBufferIndex;
|
|
|
|
if (api.ModLoader.IsModEnabled("commandhook"))
|
|
{
|
|
api.Event.SaveGameLoaded += () => RegisterCommandHooks(api);
|
|
}
|
|
else
|
|
{
|
|
api.Logger.Fatal(
|
|
"ClaimLink requires the CommandHook mod on the server for /land and /group integration. That integration is disabled; /claimlink commands and buffer protection still work."
|
|
);
|
|
}
|
|
|
|
ClaimLinkChatCommand.Register(api);
|
|
ClaimLinkVisualizerNetwork.Start(api);
|
|
ClaimLinkBufferProtection.Register(api);
|
|
api.Event.PlayerDisconnect += ClaimLinkChatCommand.OnPlayerDisconnect;
|
|
}
|
|
|
|
private void RegisterCommandHooks(ICoreServerAPI api)
|
|
{
|
|
CommandListener cmdListener = new();
|
|
CommandHook.ICommandHookListener cmdProxy = CommandHookListenerProxy.Create(
|
|
cmdListener.ModId,
|
|
cmdListener.Commands,
|
|
cmdListener.Before,
|
|
cmdListener.After
|
|
);
|
|
CommandHook.CommandHookModSystem.Register(cmdProxy);
|
|
cmdListenerProxy = cmdProxy;
|
|
|
|
GroupCommandListener groupListener = new();
|
|
CommandHook.ICommandHookListener groupProxy = CommandHookListenerProxy.Create(
|
|
groupListener.ModId,
|
|
groupListener.Commands,
|
|
groupListener.Before,
|
|
groupListener.After
|
|
);
|
|
CommandHook.CommandHookModSystem.Register(groupProxy);
|
|
groupCmdListenerProxy = groupProxy;
|
|
|
|
api.Event.PlayerDisconnect += CommandListener.OnPlayerDisconnect;
|
|
api.Event.PlayerDisconnect += GroupCommandListener.OnPlayerDisconnect;
|
|
}
|
|
|
|
internal static void RebuildBufferIndex()
|
|
{
|
|
List<(int groupId, List<Vintagestory.API.MathTools.Cuboidi> buffers)> source = new();
|
|
foreach (int groupId in Registry.All)
|
|
source.Add((groupId, ClaimLinkBuffer.GetBuffer(groupId)));
|
|
BufferIndex.Rebuild(source, WorldManager.RegionSize);
|
|
}
|
|
|
|
public override void StartClientSide(ICoreClientAPI api) => ClaimLinkVisualizerClient.Start(api);
|
|
|
|
public override void Dispose()
|
|
{
|
|
if (cmdListenerProxy != null || groupCmdListenerProxy != null)
|
|
UnregisterCommandHooks();
|
|
}
|
|
|
|
private void UnregisterCommandHooks()
|
|
{
|
|
if (cmdListenerProxy != null)
|
|
CommandHook.CommandHookModSystem.Unregister(
|
|
(CommandHook.ICommandHookListener)cmdListenerProxy
|
|
);
|
|
if (groupCmdListenerProxy != null)
|
|
CommandHook.CommandHookModSystem.Unregister(
|
|
(CommandHook.ICommandHookListener)groupCmdListenerProxy
|
|
);
|
|
}
|
|
|
|
private static IEnumerable<(int claimIndex, LandClaim claim)> EnumerateOwnedClaims(
|
|
string ownerPlayerUid
|
|
)
|
|
{
|
|
int index = 0;
|
|
foreach (LandClaim c in LandClaimAPI.All)
|
|
{
|
|
if (c.OwnedByPlayerUid != ownerPlayerUid)
|
|
continue;
|
|
|
|
yield return (index, c);
|
|
index++;
|
|
}
|
|
}
|
|
|
|
public static bool TryResolveOwnedClaim(
|
|
string ownerPlayerUid,
|
|
int claimIndex,
|
|
out LandClaim? claim
|
|
)
|
|
{
|
|
foreach ((int index, LandClaim c) in EnumerateOwnedClaims(ownerPlayerUid))
|
|
{
|
|
if (index == claimIndex)
|
|
{
|
|
claim = c;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|