Files
ClaimLink/ClaimLink/ClaimLinkBufferProtection.cs
T
anth64 c1158d50c3 Actively protect claim link buffer zones from non-members
Adds a region-indexed lookup (ClaimLinkBufferIndex), keyed via the
game's own WorldManager.MapRegionIndex2D and rebuilt on every registry
mutation and on SaveGameLoaded, feeding a block break/place/use gate
(ClaimLinkBufferProtection) that denies players who aren't members of
the relevant claim link from modifying buffer-zone land. Any existing
vanilla claim access (owner, claim's group, explicit permission grant,
or AllowUseEveryone) always overrides the buffer check.

Bump to 0.4.0.
2026-08-06 19:36:21 +02:00

79 lines
2.2 KiB
C#

using Vintagestory.API.Common;
using Vintagestory.API.MathTools;
using Vintagestory.API.Server;
namespace ClaimLink;
internal static class ClaimLinkBufferProtection
{
internal static void Register(ICoreServerAPI api)
{
api.Event.CanPlaceOrBreakBlock += OnCanPlaceOrBreakBlock;
api.Event.CanUseBlock += OnCanUseBlock;
}
private static bool OnCanUseBlock(IServerPlayer byPlayer, BlockSelection blockSel) =>
IsAllowed(byPlayer, blockSel.Position, EnumBlockAccessFlags.Use);
private static bool OnCanPlaceOrBreakBlock(
IServerPlayer byPlayer,
BlockSelection blockSel,
out string claimant
)
{
bool allowed = IsAllowed(byPlayer, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak);
claimant = allowed ? null! : "custommessage-claimlink-buffer-zone";
return allowed;
}
private static bool IsAllowed(
IServerPlayer byPlayer,
BlockPos pos,
EnumBlockAccessFlags accessFlag
)
{
bool allowed = true;
foreach (int groupId in ClaimLinkBufferIndex.CandidateGroupIds(pos))
{
if (IsMember(byPlayer, groupId))
continue;
foreach (Cuboidi buffer in ClaimLinkBufferIndex.CachedBuffer(groupId))
if (buffer.Contains(pos))
allowed = false;
}
return allowed || HasClaimAccess(byPlayer, pos, accessFlag);
}
private static bool IsMember(IServerPlayer player, int groupId)
{
foreach (PlayerGroupMembership membership in player.Groups)
if (membership.GroupUid == groupId)
return true;
return false;
}
private static bool HasClaimAccess(
IServerPlayer player,
BlockPos pos,
EnumBlockAccessFlags accessFlag
)
{
LandClaim[]? claims = ClaimLinkModSystem.LandClaimAPI.Get(pos);
if (claims == null)
return false;
foreach (LandClaim claim in claims)
{
if (claim.TestPlayerAccess(player, accessFlag) != EnumPlayerAccessResult.Denied)
return true;
if (accessFlag == EnumBlockAccessFlags.Use && claim.AllowUseEveryone)
return true;
}
return false;
}
}