Move character options and movement skills into the Runtime-owned character graph, expose borrowed inventory, character, and social views, and route retained UI state commands through generation-gated typed Runtime contracts. Preserve the existing synchronous wire path while deleting the App-owned option and skill mirrors and extending normalized parity checkpoints. Co-authored-by: Codex <codex@openai.com>
57 lines
1.6 KiB
C#
57 lines
1.6 KiB
C#
namespace AcDream.Core.Social;
|
|
|
|
/// <summary>Authoritative copy of retail's server-supplied <c>SquelchDB</c>.</summary>
|
|
public sealed class SquelchState
|
|
{
|
|
private readonly object _gate = new();
|
|
private SquelchDatabase _database = SquelchDatabase.Empty;
|
|
private long _revision;
|
|
|
|
public long Revision => Interlocked.Read(ref _revision);
|
|
|
|
public SquelchDatabase Snapshot()
|
|
{
|
|
lock (_gate) return _database;
|
|
}
|
|
|
|
public void Replace(SquelchDatabase database)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(database);
|
|
lock (_gate)
|
|
{
|
|
_database = database;
|
|
Interlocked.Increment(ref _revision);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drop the server-owned squelch database for the old session. Retail
|
|
/// <c>CPlayerSystem::LogOnCharacter @ 0x0055F890</c> calls
|
|
/// <c>gmCCommunicationSystem::ClearSquelchDB @ 0x00589240</c> before
|
|
/// entering the next character.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
lock (_gate)
|
|
{
|
|
_database = SquelchDatabase.Empty;
|
|
Interlocked.Increment(ref _revision);
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed record SquelchInfo(
|
|
string Name,
|
|
bool AccountWide,
|
|
IReadOnlySet<uint> MessageTypes);
|
|
|
|
public sealed record SquelchDatabase(
|
|
IReadOnlyDictionary<string, uint> Accounts,
|
|
IReadOnlyDictionary<uint, SquelchInfo> Characters,
|
|
SquelchInfo Global)
|
|
{
|
|
public static SquelchDatabase Empty { get; } = new(
|
|
new Dictionary<string, uint>(StringComparer.OrdinalIgnoreCase),
|
|
new Dictionary<uint, SquelchInfo>(),
|
|
new SquelchInfo(string.Empty, false, new HashSet<uint>()));
|
|
}
|