63 lines
2.8 KiB
C#
63 lines
2.8 KiB
C#
using System.Collections.Frozen;
|
|
using System.Collections.Generic;
|
|
|
|
namespace AcDream.Core.Items;
|
|
|
|
/// <summary>
|
|
/// AP-129 (Campaign P Slice P4 review fix, 2026-07-30). Retail
|
|
/// <c>RestrictionDB</c> — the access-control list carried on a house/dwelling
|
|
/// object's <c>PublicWeenieDesc</c> (<c>WeenieHeaderFlag.HouseRestrictions</c>,
|
|
/// 0x04000000) and refreshed live via <c>House_UpdateRestrictions (0x0248)</c>.
|
|
/// Wire shape confirmed verbatim against
|
|
/// <c>references/Chorizite.ACProtocol/Chorizite.ACProtocol/Types/RestrictionDB.generated.cs</c>
|
|
/// and <c>protocol.xml:6270-6275</c>: <c>uint Version, uint Flags (0=private,
|
|
/// 1=open), ObjectId MonarchId, PHashTable<ObjectId,uint> Permissions</c>.
|
|
/// </summary>
|
|
/// <param name="OpenToPublic">Wire <c>Flags != 0</c> — retail's <c>_bitmask
|
|
/// & 1</c>. When true, every mover is admitted regardless of the guest
|
|
/// list.</param>
|
|
/// <param name="AllegianceMonarchId">Wire <c>MonarchId</c> — retail
|
|
/// <c>_monarch_iid</c>. A mover whose own monarch matches this id is admitted
|
|
/// (allegiance-wide access), independent of the guest list.</param>
|
|
/// <param name="Guests">Wire <c>Permissions</c> — guid to permission value
|
|
/// (0 = dwelling access only, 1 = storage access also). Retail's
|
|
/// <c>IsAllowedIn</c> only consults key membership for entry; the permission
|
|
/// value is preserved for wire fidelity but not consulted here.</param>
|
|
public sealed record HouseRestrictionRecord
|
|
{
|
|
public HouseRestrictionRecord(
|
|
bool OpenToPublic,
|
|
uint AllegianceMonarchId,
|
|
IReadOnlyDictionary<uint, uint> Guests)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(Guests);
|
|
this.OpenToPublic = OpenToPublic;
|
|
this.AllegianceMonarchId = AllegianceMonarchId;
|
|
this.Guests = Guests.ToFrozenDictionary();
|
|
}
|
|
|
|
public bool OpenToPublic { get; }
|
|
public uint AllegianceMonarchId { get; }
|
|
|
|
/// <summary>
|
|
/// Immutable snapshot of the wire permission table. The parser's mutable
|
|
/// dictionary must never remain an untracked mutation path into live
|
|
/// collision-entry authority.
|
|
/// </summary>
|
|
public IReadOnlyDictionary<uint, uint> Guests { get; }
|
|
|
|
/// <summary>
|
|
/// Verbatim port of retail <c>RestrictionDB::IsAllowedIn</c>
|
|
/// (named-retail pc:444493-444516, 0x005ae8f0):
|
|
/// <c>if ((_bitmask & 1) == 0) { if (_monarch_iid == 0 || arg3 !=
|
|
/// _monarch_iid) { if (arg2 == 0) return 0; if (!table.find(arg2)) return
|
|
/// 0; } } return 1;</c> — open bit set, OR mover shares the house's
|
|
/// allegiance monarch, OR mover's own guid is a table member.
|
|
/// </summary>
|
|
public bool IsAllowedIn(uint moverId, uint moverMonarchId)
|
|
{
|
|
if (OpenToPublic) return true;
|
|
if (AllegianceMonarchId != 0 && moverMonarchId == AllegianceMonarchId) return true;
|
|
return moverId != 0 && Guests.ContainsKey(moverId);
|
|
}
|
|
}
|