using System.Collections.Frozen; using System.Diagnostics; namespace ICRebuild.Core; public sealed record GameFrame(bool Ready, nint LocalAddress, bool IsPvP, bool IsSlowed, DungeonSnapshot Dungeon,nint ActionManagerAddress = 0,nint TargetAddress = 0,uint TargetEntityId = 0, nint LocalStatusManagerAddress = 0, uint LocalEntityId = 0, bool IsReplay = false) { public static readonly GameFrame Empty = new(false,0,false,false,DungeonSnapshot.Empty); } // Producers sample thread-affine services only on Framework.Update. Native workers read values only. public sealed class FrameStore(Func? clock = null, long? maximumAge = null) { private sealed record Published(GameFrame Frame,long Time); private readonly Func now = clock ?? Stopwatch.GetTimestamp; private readonly long ttl = maximumAge ?? Stopwatch.Frequency / 2; private Published? current; public void Publish(GameFrame frame) => Volatile.Write(ref current,new(frame,now())); public void Clear() => Volatile.Write(ref current,null); public GameFrame Read() { var value=Volatile.Read(ref current); if(value==null) return GameFrame.Empty; var age=now()-value.Time; return age<0 || age>ttl ? GameFrame.Empty : value.Frame; } } public sealed class SettingsSnapshot { private readonly float[] values=new float[44]; public FrozenSet Timelines { get; } public bool BlockListed { get; } public DashFilterMode DashMode { get; } public float KnockSeconds { get; } public FrozenSet BlockedStatuses { get; } public SettingsSnapshot(IReadOnlyDictionary source,IEnumerable timelines,bool blockListed,float knockSeconds,DashFilterMode dashMode = DashFilterMode.BlockListed, IEnumerable? blockedStatuses = null) { foreach(var f in Features.All) values[f.Id]=Policies.FiniteClamp(source.GetValueOrDefault(f.Id,f.Default),f.Min,f.Max,f.Default); Timelines=timelines.Where(x=>x>0).ToFrozenSet(); BlockListed=blockListed; KnockSeconds=Policies.FiniteClamp(knockSeconds,0,5); DashMode=dashMode; BlockedStatuses=(blockedStatuses ?? []).Where(StatusCatalog.AuditedBlockCandidates.Contains).ToFrozenSet(); } public float Value(int id) => (uint)id<(uint)values.Length ? values[id] : 0; } public static class AccelerationPolicy { // Audited in 2026.09.15 and 2026.10.06 executables: native routine consumes and updates +0x44. // The returned state belongs to the game and MUST NOT be restored to the value before the call. public const string AuditedVersion="2026.10.06.0000.0000"; public const string BaselineVersion="2026.09.15.0000.0000"; public static bool IsAuditedVersion(string? version) => version is AuditedVersion or BaselineVersion; public static bool ShouldPrime(GameFrame frame,nint owner,bool moving,float current) => frame.Ready && !frame.IsSlowed && frame.LocalAddress!=0 && owner==frame.LocalAddress && moving && float.IsFinite(current); public static void Run(ref float state,bool prime,Action original) { if(prime) state=100; original(); } }