From 42ec5db2f351ca39962e396cdb35f8f6f9f60fe7 Mon Sep 17 00:00:00 2001 From: AriusII <35581726+AriusII@users.noreply.github.com> Date: Mon, 21 Sep 2026 22:42:26 +0200 Subject: [PATCH] Expose structured capability evidence reason code --- docs/adr/0004-capability-matrix.md | 3 + .../PublicAPI.Unshipped.txt | 8 + .../CheatEngine.Client.Abstractions/README.md | 4 + .../Runtime/ClientCapabilityEvidence.cs | 61 ++++-- .../ClientCapabilityEvidenceReasonCode.cs | 23 ++ .../Runtime/ClientCapabilityEvidenceTests.cs | 206 ++++++++++++++++++ tests/CheatEngine.Client.AotProbe/Program.cs | 15 ++ 7 files changed, 300 insertions(+), 20 deletions(-) create mode 100644 libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidenceReasonCode.cs create mode 100644 tests/CheatEngine.Client.Abstractions.Tests/Runtime/ClientCapabilityEvidenceTests.cs diff --git a/docs/adr/0004-capability-matrix.md b/docs/adr/0004-capability-matrix.md index f767687..ff29f2d 100644 --- a/docs/adr/0004-capability-matrix.md +++ b/docs/adr/0004-capability-matrix.md @@ -65,6 +65,9 @@ been live-qualified. or host-side behavior that ordinary CI has not established. - The matrix gives reviewers one place to distinguish a deliberate product gate from a missing implementation, keeping package release claims honest as SDK evidence changes. +- Capability evidence exposes the stable `EffectiveReasonCode` of the gate that supplied its display reason. Consumers + use that code with the gate's independently observed state rather than parsing text or reproducing the Client's + priority order; it does not promote an unknown, faulted, malformed, or unqualified capability to `Available`. ## Current template boundary diff --git a/libs/CheatEngine.Client.Abstractions/PublicAPI.Unshipped.txt b/libs/CheatEngine.Client.Abstractions/PublicAPI.Unshipped.txt index 4e36c4c..2ada242 100644 --- a/libs/CheatEngine.Client.Abstractions/PublicAPI.Unshipped.txt +++ b/libs/CheatEngine.Client.Abstractions/PublicAPI.Unshipped.txt @@ -37,6 +37,7 @@ CheatEngine.Client.Runtime.ClientCapabilityEvidence.ClientCapabilityEvidence() - CheatEngine.Client.Runtime.ClientCapabilityEvidence.ClientCapabilityEvidence(CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate implementation, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate package, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate host, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate liveQualification, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate policy, CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate lifetime) -> void CheatEngine.Client.Runtime.ClientCapabilityEvidence.AvailabilityState.get -> CheatEngine.Client.Runtime.ClientCapabilityAvailabilityState CheatEngine.Client.Runtime.ClientCapabilityEvidence.EffectiveReason.get -> string! +CheatEngine.Client.Runtime.ClientCapabilityEvidence.EffectiveReasonCode.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode CheatEngine.Client.Runtime.ClientCapabilityEvidence.Host.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate CheatEngine.Client.Runtime.ClientCapabilityEvidence.Implementation.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate CheatEngine.Client.Runtime.ClientCapabilityEvidence.IsExecutable.get -> bool @@ -52,6 +53,13 @@ CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.IsSatisfied.get -> bool CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.Reason.get -> string! CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.State.get -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate.Equals(CheatEngine.Client.Runtime.ClientCapabilityEvidenceGate other) -> bool +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Host = 2 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Implementation = 0 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Lifetime = 5 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.LiveQualification = 3 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Package = 1 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode +CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode.Policy = 4 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceReasonCode CheatEngine.Client.Runtime.ClientCapabilityEvidenceState CheatEngine.Client.Runtime.ClientCapabilityEvidenceState.Faulted = 3 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState CheatEngine.Client.Runtime.ClientCapabilityEvidenceState.Malformed = 4 -> CheatEngine.Client.Runtime.ClientCapabilityEvidenceState diff --git a/libs/CheatEngine.Client.Abstractions/README.md b/libs/CheatEngine.Client.Abstractions/README.md index bb98602..64def6b 100644 --- a/libs/CheatEngine.Client.Abstractions/README.md +++ b/libs/CheatEngine.Client.Abstractions/README.md @@ -79,6 +79,10 @@ host observation, live qualification, policy, and activation lifetime are distin missing, faulted, and malformed host observations remain distinguishable instead of being collapsed into a generic unavailable result. +`Evidence.EffectiveReasonCode` is the stable, typed identity of the gate supplying `Evidence.EffectiveReason`; use it +with that gate's public state instead of parsing the human-readable reason text or duplicating the Client's deterministic +priority. The reason text remains available for display and diagnostics. + In particular, the value-scan contract and state model are published, but the Core implementation does **not** currently create a live `MemScan`/`FoundList` session. The next SDK line now contains a production owner factory with parent rollback and child-before-parent teardown, but Client diff --git a/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidence.cs b/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidence.cs index 8917c9d..a27f181 100644 --- a/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidence.cs +++ b/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidence.cs @@ -86,100 +86,121 @@ public ClientCapabilityAvailabilityState AvailabilityState public bool IsExecutable => AllSatisfied; /// Gets the reason for the highest-priority missing, faulted, malformed, or unknown prerequisite. - public string EffectiveReason => GetEffectiveGate().Reason; + public string EffectiveReason => GetGate(EffectiveReasonCode).Reason; + + /// + /// Gets the stable code for the evidence gate that supplies . Its state remains + /// available through the corresponding evidence-gate property. + /// + public ClientCapabilityEvidenceReasonCode EffectiveReasonCode => GetEffectiveReasonCode(); private bool AllSatisfied => Implementation.IsSatisfied && Package.IsSatisfied && Host.IsSatisfied && LiveQualification.IsSatisfied && Policy.IsSatisfied && Lifetime.IsSatisfied; - private ClientCapabilityEvidenceGate GetEffectiveGate() + private ClientCapabilityEvidenceReasonCode GetEffectiveReasonCode() { if (Lifetime.State == ClientCapabilityEvidenceState.Missing) { - return Lifetime; + return ClientCapabilityEvidenceReasonCode.Lifetime; } if (Policy.State == ClientCapabilityEvidenceState.Missing) { - return Policy; + return ClientCapabilityEvidenceReasonCode.Policy; } if (Implementation.State == ClientCapabilityEvidenceState.Missing) { - return Implementation; + return ClientCapabilityEvidenceReasonCode.Implementation; } if (Package.State == ClientCapabilityEvidenceState.Missing) { - return Package; + return ClientCapabilityEvidenceReasonCode.Package; } if (Host.State == ClientCapabilityEvidenceState.Missing) { - return Host; + return ClientCapabilityEvidenceReasonCode.Host; } if (LiveQualification.State == ClientCapabilityEvidenceState.Missing) { - return LiveQualification; + return ClientCapabilityEvidenceReasonCode.LiveQualification; } if (Host.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return Host; + return ClientCapabilityEvidenceReasonCode.Host; } if (Package.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return Package; + return ClientCapabilityEvidenceReasonCode.Package; } if (LiveQualification.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return LiveQualification; + return ClientCapabilityEvidenceReasonCode.LiveQualification; } if (Implementation.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return Implementation; + return ClientCapabilityEvidenceReasonCode.Implementation; } if (Policy.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return Policy; + return ClientCapabilityEvidenceReasonCode.Policy; } if (Lifetime.State is ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed) { - return Lifetime; + return ClientCapabilityEvidenceReasonCode.Lifetime; } if (Host.State == ClientCapabilityEvidenceState.Unknown) { - return Host; + return ClientCapabilityEvidenceReasonCode.Host; } if (Package.State == ClientCapabilityEvidenceState.Unknown) { - return Package; + return ClientCapabilityEvidenceReasonCode.Package; } if (LiveQualification.State == ClientCapabilityEvidenceState.Unknown) { - return LiveQualification; + return ClientCapabilityEvidenceReasonCode.LiveQualification; } if (Implementation.State == ClientCapabilityEvidenceState.Unknown) { - return Implementation; + return ClientCapabilityEvidenceReasonCode.Implementation; } if (Policy.State == ClientCapabilityEvidenceState.Unknown) { - return Policy; + return ClientCapabilityEvidenceReasonCode.Policy; } - return Lifetime; + return ClientCapabilityEvidenceReasonCode.Lifetime; + } + + private ClientCapabilityEvidenceGate GetGate(ClientCapabilityEvidenceReasonCode reasonCode) + { + return reasonCode switch + { + ClientCapabilityEvidenceReasonCode.Implementation => Implementation, + ClientCapabilityEvidenceReasonCode.Package => Package, + ClientCapabilityEvidenceReasonCode.Host => Host, + ClientCapabilityEvidenceReasonCode.LiveQualification => LiveQualification, + ClientCapabilityEvidenceReasonCode.Policy => Policy, + ClientCapabilityEvidenceReasonCode.Lifetime => Lifetime, + _ => throw new ArgumentOutOfRangeException(nameof(reasonCode), reasonCode, + "The Client capability evidence reason code is not defined.") + }; } private bool HasState(ClientCapabilityEvidenceState state) diff --git a/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidenceReasonCode.cs b/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidenceReasonCode.cs new file mode 100644 index 0000000..fa35b75 --- /dev/null +++ b/libs/CheatEngine.Client.Abstractions/Runtime/ClientCapabilityEvidenceReasonCode.cs @@ -0,0 +1,23 @@ +namespace CheatEngine.Client.Runtime; + +/// Identifies the evidence gate that supplies . +public enum ClientCapabilityEvidenceReasonCode : byte +{ + /// The operational Client adapter gate supplies the effective reason. + Implementation = 0, + + /// The consumed package artifact gate supplies the effective reason. + Package = 1, + + /// The Cheat Engine host observation gate supplies the effective reason. + Host = 2, + + /// The live host-qualification gate supplies the effective reason. + LiveQualification = 3, + + /// The Client policy gate supplies the effective reason. + Policy = 4, + + /// The activation-lifetime gate supplies the effective reason. + Lifetime = 5 +} diff --git a/tests/CheatEngine.Client.Abstractions.Tests/Runtime/ClientCapabilityEvidenceTests.cs b/tests/CheatEngine.Client.Abstractions.Tests/Runtime/ClientCapabilityEvidenceTests.cs new file mode 100644 index 0000000..5700d2e --- /dev/null +++ b/tests/CheatEngine.Client.Abstractions.Tests/Runtime/ClientCapabilityEvidenceTests.cs @@ -0,0 +1,206 @@ +using CheatEngine.Client.Runtime; + +namespace CheatEngine.Client.Abstractions.Tests.Runtime; + +public sealed class ClientCapabilityEvidenceTests +{ + [Theory] + [MemberData(nameof(EffectiveReasonPriorityCases))] + public void EffectiveReasonCodePreservesEveryGatePriority( + ClientCapabilityEvidenceState state, + ClientCapabilityEvidenceReasonCode expectedReasonCode, + ClientCapabilityAvailabilityState expectedAvailabilityState) + { + ClientCapabilityEvidence evidence = CreateEvidenceForPriority(state, expectedReasonCode); + ClientCapabilityAvailability availability = new(ClientCapabilityId.ProcessSelection, evidence); + + Assert.Equal(expectedReasonCode, evidence.EffectiveReasonCode); + Assert.Equal(ReasonFor(expectedReasonCode), evidence.EffectiveReason); + Assert.Equal(expectedAvailabilityState, evidence.AvailabilityState); + Assert.Equal(expectedAvailabilityState, availability.State); + Assert.Equal(evidence.EffectiveReason, availability.Reason); + } + + [Fact] + public void MissingReasonWinsOverFaultedMalformedAndUnknownReasons() + { + ClientCapabilityEvidence evidence = new( + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Unknown, ReasonFor( + ClientCapabilityEvidenceReasonCode.Implementation)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Malformed, ReasonFor( + ClientCapabilityEvidenceReasonCode.Package)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Faulted, ReasonFor( + ClientCapabilityEvidenceReasonCode.Host)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Missing, ReasonFor( + ClientCapabilityEvidenceReasonCode.LiveQualification)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Unknown, ReasonFor( + ClientCapabilityEvidenceReasonCode.Policy)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Satisfied, ReasonFor( + ClientCapabilityEvidenceReasonCode.Lifetime))); + + Assert.Equal(ClientCapabilityEvidenceReasonCode.LiveQualification, evidence.EffectiveReasonCode); + Assert.Equal(ReasonFor(ClientCapabilityEvidenceReasonCode.LiveQualification), evidence.EffectiveReason); + Assert.Equal(ClientCapabilityAvailabilityState.Unavailable, evidence.AvailabilityState); + } + + [Theory] + [InlineData(ClientCapabilityEvidenceState.Faulted)] + [InlineData(ClientCapabilityEvidenceState.Malformed)] + public void FaultedAndMalformedReasonsWinOverUnknownReasons(ClientCapabilityEvidenceState failedState) + { + ClientCapabilityEvidence evidence = new( + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Satisfied, ReasonFor( + ClientCapabilityEvidenceReasonCode.Implementation)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Satisfied, ReasonFor( + ClientCapabilityEvidenceReasonCode.Package)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Unknown, ReasonFor( + ClientCapabilityEvidenceReasonCode.Host)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Satisfied, ReasonFor( + ClientCapabilityEvidenceReasonCode.LiveQualification)), + new ClientCapabilityEvidenceGate(ClientCapabilityEvidenceState.Satisfied, ReasonFor( + ClientCapabilityEvidenceReasonCode.Policy)), + new ClientCapabilityEvidenceGate(failedState, ReasonFor(ClientCapabilityEvidenceReasonCode.Lifetime))); + + Assert.Equal(ClientCapabilityEvidenceReasonCode.Lifetime, evidence.EffectiveReasonCode); + Assert.Equal(ReasonFor(ClientCapabilityEvidenceReasonCode.Lifetime), evidence.EffectiveReason); + Assert.Equal(ClientCapabilityAvailabilityState.Unknown, evidence.AvailabilityState); + } + + [Fact] + public void AllSatisfiedEvidenceUsesTheLifetimeReasonCode() + { + ClientCapabilityEvidence evidence = CreateEvidenceForPriority( + ClientCapabilityEvidenceState.Satisfied, ClientCapabilityEvidenceReasonCode.Lifetime); + + Assert.Equal(ClientCapabilityEvidenceReasonCode.Lifetime, evidence.EffectiveReasonCode); + Assert.Equal(ReasonFor(ClientCapabilityEvidenceReasonCode.Lifetime), evidence.EffectiveReason); + Assert.True(evidence.IsExecutable); + Assert.Equal(ClientCapabilityAvailabilityState.Available, evidence.AvailabilityState); + } + + [Theory] + [InlineData(ClientCapabilityAvailabilityState.Available, ClientCapabilityEvidenceReasonCode.Lifetime)] + [InlineData(ClientCapabilityAvailabilityState.Unavailable, ClientCapabilityEvidenceReasonCode.Lifetime)] + [InlineData(ClientCapabilityAvailabilityState.Unknown, ClientCapabilityEvidenceReasonCode.Host)] + public void LegacyAvailabilityConstructionRetainsStateAndDisplayReason( + ClientCapabilityAvailabilityState state, + ClientCapabilityEvidenceReasonCode expectedReasonCode) + { + const string reason = "Legacy display reason."; + ClientCapabilityAvailability availability = new(ClientCapabilityId.ProcessSelection, state, reason); + + Assert.Equal(state, availability.State); + Assert.Equal(expectedReasonCode, availability.Evidence.EffectiveReasonCode); + Assert.Equal(reason, availability.Evidence.EffectiveReason); + Assert.Equal(reason, availability.Reason); + Assert.Equal(state == ClientCapabilityAvailabilityState.Available, availability.IsAvailable); + Assert.Equal(state != ClientCapabilityAvailabilityState.Unknown, availability.IsKnown); + } + + [Fact] + public void EffectiveReasonCodesUseStableUnderlyingValues() + { + Assert.Equal((byte) 0, (byte) ClientCapabilityEvidenceReasonCode.Implementation); + Assert.Equal((byte) 1, (byte) ClientCapabilityEvidenceReasonCode.Package); + Assert.Equal((byte) 2, (byte) ClientCapabilityEvidenceReasonCode.Host); + Assert.Equal((byte) 3, (byte) ClientCapabilityEvidenceReasonCode.LiveQualification); + Assert.Equal((byte) 4, (byte) ClientCapabilityEvidenceReasonCode.Policy); + Assert.Equal((byte) 5, (byte) ClientCapabilityEvidenceReasonCode.Lifetime); + } + + public static IEnumerable EffectiveReasonPriorityCases + { + get + { + foreach (ClientCapabilityEvidenceState state in new[] + { + ClientCapabilityEvidenceState.Missing, + ClientCapabilityEvidenceState.Faulted, + ClientCapabilityEvidenceState.Malformed, + ClientCapabilityEvidenceState.Unknown + }) + { + ClientCapabilityAvailabilityState expectedAvailabilityState = + state == ClientCapabilityEvidenceState.Missing + ? ClientCapabilityAvailabilityState.Unavailable + : ClientCapabilityAvailabilityState.Unknown; + + foreach (ClientCapabilityEvidenceReasonCode expectedReasonCode in GetPriority(state)) + { + yield return [state, expectedReasonCode, expectedAvailabilityState]; + } + } + } + } + + private static ClientCapabilityEvidence CreateEvidenceForPriority( + ClientCapabilityEvidenceState state, + ClientCapabilityEvidenceReasonCode expectedReasonCode) + { + ClientCapabilityEvidenceReasonCode[] priority = GetPriority(state); + int expectedPriorityIndex = Array.IndexOf(priority, expectedReasonCode); + + return new ClientCapabilityEvidence( + CreateGate(ClientCapabilityEvidenceReasonCode.Implementation, state, priority, expectedPriorityIndex), + CreateGate(ClientCapabilityEvidenceReasonCode.Package, state, priority, expectedPriorityIndex), + CreateGate(ClientCapabilityEvidenceReasonCode.Host, state, priority, expectedPriorityIndex), + CreateGate(ClientCapabilityEvidenceReasonCode.LiveQualification, state, priority, expectedPriorityIndex), + CreateGate(ClientCapabilityEvidenceReasonCode.Policy, state, priority, expectedPriorityIndex), + CreateGate(ClientCapabilityEvidenceReasonCode.Lifetime, state, priority, expectedPriorityIndex)); + } + + private static ClientCapabilityEvidenceGate CreateGate( + ClientCapabilityEvidenceReasonCode code, + ClientCapabilityEvidenceState state, + ClientCapabilityEvidenceReasonCode[] priority, + int expectedPriorityIndex) + { + ClientCapabilityEvidenceState gateState = state == ClientCapabilityEvidenceState.Satisfied || + Array.IndexOf(priority, code) < expectedPriorityIndex + ? ClientCapabilityEvidenceState.Satisfied + : state; + return new ClientCapabilityEvidenceGate(gateState, ReasonFor(code)); + } + + private static ClientCapabilityEvidenceReasonCode[] GetPriority(ClientCapabilityEvidenceState state) + { + return state switch + { + ClientCapabilityEvidenceState.Missing => + [ + ClientCapabilityEvidenceReasonCode.Lifetime, + ClientCapabilityEvidenceReasonCode.Policy, + ClientCapabilityEvidenceReasonCode.Implementation, + ClientCapabilityEvidenceReasonCode.Package, + ClientCapabilityEvidenceReasonCode.Host, + ClientCapabilityEvidenceReasonCode.LiveQualification + ], + ClientCapabilityEvidenceState.Faulted or ClientCapabilityEvidenceState.Malformed or + ClientCapabilityEvidenceState.Unknown => + [ + ClientCapabilityEvidenceReasonCode.Host, + ClientCapabilityEvidenceReasonCode.Package, + ClientCapabilityEvidenceReasonCode.LiveQualification, + ClientCapabilityEvidenceReasonCode.Implementation, + ClientCapabilityEvidenceReasonCode.Policy, + ClientCapabilityEvidenceReasonCode.Lifetime + ], + ClientCapabilityEvidenceState.Satisfied => + [ + ClientCapabilityEvidenceReasonCode.Lifetime, + ClientCapabilityEvidenceReasonCode.Policy, + ClientCapabilityEvidenceReasonCode.Implementation, + ClientCapabilityEvidenceReasonCode.Package, + ClientCapabilityEvidenceReasonCode.Host, + ClientCapabilityEvidenceReasonCode.LiveQualification + ], + _ => throw new ArgumentOutOfRangeException(nameof(state), state, + "The Client capability evidence state is not defined.") + }; + } + + private static string ReasonFor(ClientCapabilityEvidenceReasonCode code) + { + return $"{code} reason."; + } +} diff --git a/tests/CheatEngine.Client.AotProbe/Program.cs b/tests/CheatEngine.Client.AotProbe/Program.cs index 7c0aa94..512b5c9 100644 --- a/tests/CheatEngine.Client.AotProbe/Program.cs +++ b/tests/CheatEngine.Client.AotProbe/Program.cs @@ -12,6 +12,7 @@ using CheatEngine.Client.Lua; using CheatEngine.Client.Memory; using CheatEngine.Client.RemoteExecution; +using CheatEngine.Client.Runtime; using CheatEngine.Client.Scanning; using CheatEngine.Client.Speed; using CheatEngine.Client.Timers; @@ -68,4 +69,18 @@ _ = typeof(AssemblyInstructionRequest); _ = new AobPattern("90"); +const string evidenceReason = "Activation evidence is current."; +ClientCapabilityEvidenceGate satisfiedGate = new(ClientCapabilityEvidenceState.Satisfied, evidenceReason); +ClientCapabilityEvidence evidence = new( + satisfiedGate, satisfiedGate, satisfiedGate, satisfiedGate, satisfiedGate, satisfiedGate); +ClientCapabilityAvailability capabilityAvailability = new(ClientCapabilityId.ProcessSelection, evidence); +if (evidence.EffectiveReasonCode != ClientCapabilityEvidenceReasonCode.Lifetime || + evidence.EffectiveReason != evidenceReason || + capabilityAvailability.State != ClientCapabilityAvailabilityState.Available || + !capabilityAvailability.IsAvailable || !capabilityAvailability.IsKnown || + capabilityAvailability.Reason != evidenceReason) +{ + return 1; +} + return services.Count == 0 ? 1 : 0;