Integration modes
| Mode | What it does | Use when |
|---|---|---|
| Drop-in | Ship anticheat.dll, anticheat.lic, and anticheat.ini; load the DLL once at startup. | You want baseline sensors and local logs with minimal game changes. |
| Cooperative API | Call the public C exports or an engine wrapper for context, telemetry tokens, ValueGuard, SaveGame protection, and aim reports. | You need player/session attribution, protected values, protected saves, or behavior reports. |
Package layout
sdk/include/anticheat.h Public C API
sdk/bin/anticheat.dll Runtime DLL and drop-in entry
sdk/lib/anticheat.lib MSVC import library
sdk/anticheat.ini.example Example config
backend-kit/ Schemas and endpoint examples
samples/ue5/ Unreal wrapper
samples/unity/ Unity wrapper
tools/KorvayneConfigurator Config UI
tools/KorvayneDropper File placement helper
Lifecycle
AC_Init verifies the license, adopts the callback and flags, then starts the background sensor threads. It is idempotent and safe to call early.
ac_config cfg = {0};
cfg.cb = OnKorvayneDetection;
cfg.user = MyContext;
cfg.scan_interval_ms = 500;
cfg.flags = AC_FLAG_VALUEGUARD_RESTORE;
cfg.license = NULL; // load anticheat.lic next to the game executable
int rc = AC_Init(&cfg);
| Function | Purpose |
|---|---|
AC_Init(const ac_config*) | Arms sensors and starts the scan thread. |
AC_Tick() | Optional cheap per-frame checks. Useful for cooperative integrations. |
AC_Shutdown() | Stops SDK threads before process shutdown or controlled unload. |
AC_Version() | Returns the runtime version string for support and logs. |
Detection callback
The callback runs on an SDK background thread, not your game thread. Keep it cheap and thread-safe.
typedef void (*ac_detection_cb)(const ac_detection* det, void* user);
typedef struct {
const char* sensor;
ac_severity severity;
float confidence;
const char* message;
unsigned long long detail;
} ac_detection;
- Copy strings if you need to keep them. Pointers are valid only during the callback.
- Do not perform file or network I/O directly inside the callback.
- Do not call
AC_*functions from inside the callback. - Queue evidence to your game thread or telemetry worker.
| Severity | Meaning |
|---|---|
AC_SEV_INFO | Startup, license, or status event. |
AC_SEV_LOW | Weak signal. Log only. |
AC_SEV_MED | Corroborating signal. Review with context. |
AC_SEV_HIGH | High-confidence tamper evidence. |
AC_SEV_CRIT | Enforcement event. |
Runtime context
Context setters copy non-secret game/session data used by telemetry and access checks. Set them after login or session creation, and rotate the telemetry token when your backend issues a new one.
| Function | Use |
|---|---|
AC_SetGameId | Stable game identifier. |
AC_SetEnvironment | production, staging, or similar. |
AC_SetIdentityProvider | Platform or account source, such as steam. |
AC_SetPlayerId | Studio player/account ID. |
AC_SetSessionId | Login, match, or server session ID. |
AC_SetPlatformUserId | Platform user identifier. |
AC_SetGameBuild | Build/version string. |
AC_SetTelemetryToken | Short-lived backend-issued token. Not a static secret. |
The backend JSON contract is documented in Telemetry event payload, including required fields, optional fields, and schema files.
ValueGuard API
ValueGuard protects stable 4-byte values owned by the game. Legitimate writes should go through the write-through setter so the runtime value and shadow value stay in sync.
AC_GuardFloat("player.health", &CurrentHP);
AC_SetGuardedFloat(&CurrentHP, NewHP);
AC_UnguardFloat(&CurrentHP);
| Function group | Purpose |
|---|---|
AC_GuardU32, AC_GuardI32, AC_GuardFloat | Register a value address and display name. |
AC_SetGuardedU32, AC_SetGuardedI32, AC_SetGuardedFloat | Preferred legitimate write path. Updates value and shadow together. |
AC_NoteLegit, AC_NoteLegitI32, AC_NoteLegitFloat | Fallback after legacy direct writes. Prefer setters when possible. |
AC_Unguard, AC_UnguardI32, AC_UnguardFloat | Stop guarding before the address becomes invalid. |
SaveGame API
SaveGame protection wraps serialized save bytes with a signed envelope before writing and verifies that envelope before loading. The game owns serialization and recovery behavior.
const char* ctx = "player=studio-123;slot=campaign-1;schema=2";
int rc = AC_ProtectSaveFile("profile.ksave", saveBytes, saveLen, ctx);
unsigned outLen = 0;
unsigned char out[1024 * 1024];
int rc = AC_VerifySaveFile("profile.ksave", ctx, out, sizeof(out), &outLen);
if (rc == AC_SAVE_OK) {
Deserialize(out, outLen);
}
| Function group | Purpose |
|---|---|
AC_ProtectSaveBuffer, AC_VerifySaveBuffer | Protect or verify save bytes when the engine handles file I/O. |
AC_ProtectSaveFile, AC_VerifySaveFile | Protect or verify a save file on disk. |
AC_SaveResultName | Convert SaveGame return codes into readable names for logs and wrappers. |
| Return | Meaning |
|---|---|
AC_SAVE_OK | Protection or verification succeeded. |
AC_SAVE_BUFFER_TOO_SMALL | Output buffer is too small for the verified plain payload. |
AC_SAVE_TAMPERED | Envelope, payload, or context verification failed. Reject the load. |
AC_SAVE_UNLICENSED | The runtime is not armed under a valid license. |
AC_SAVE_DISABLED | [SaveGameProtection] enabled = 0. |
See SaveGame protection for context-binding, config, Unity, Unreal, and telemetry guidance.
Behavior API
Behavior reports are optional cooperative signals. Drop-in mode cannot know where a player aimed, when a target became visible, or whether a shot had line of sight. The SDK does not read mouse input, target positions, or visibility state by itself. The game must send that context after a local human player's shot.
AC_ReportAim(
aimSpeedPerMs,
reactionMs,
hadLineOfSight ? 1 : 0,
hit ? 1 : 0
);
| Argument | Meaning |
|---|---|
aimSpeedPerMs | Crosshair or view-angle movement speed immediately before the shot. Use one consistent unit across your game. |
reactionMs | Approximate milliseconds between target acquisition/visibility and firing. |
hadLineOfSight | 1 if the local player had valid line of sight when the shot was resolved. |
hit | 1 if the shot hit a player or protected target. |
How to produce the values
| Value | Simple integration source | Notes |
|---|---|---|
aimSpeedPerMs | Store the local camera/control rotation from the previous weapon tick and compare it to the rotation at shot time. | Approximate is fine. Keep the same unit and calculation across builds so baselines stay comparable. |
reactionMs | When a valid enemy first becomes visible or targetable, store a timestamp. On shot, subtract that timestamp. | If the game does not track acquisition yet, pass a conservative large value until it does. |
hadLineOfSight | Reuse the same line trace, raycast, or server hit-validation result your weapon already uses. | Do not invent a second visibility system only for the SDK; mismatches create noisy reports. |
hit | Use the final local hit result after the weapon has resolved the shot. | Only report shots fired by the local human player. |
Safe fallback: if a game cannot calculate one of these values yet, leave shot reports disabled instead of sending guesses every frame. The other anti-cheat sensors still work without this API.
- Call it once per resolved shot, not every frame.
- Only report the local human player. Do not report bots, remote replicated players, spectators, or replay playback.
- Start with
behavior_response = reportuntil normal gameplay has been observed. - Correlate behavior events with server-side match data before strong punishment.
What the runtime checks
The built-in checks are intentionally simple advisory heuristics, not automatic full-match aim analysis. They only run when the game calls AC_ReportAim.
| Evidence | Current condition | Severity |
|---|---|---|
AimSnap | hit = 1 and aimSpeedPerMs > 8.0 | medium |
Triggerbot | Three hit shots with 0 < reactionMs < 60. The counter resets after a normal reaction above 120ms. | medium |
Wallhack | hit = 1 and hadLineOfSight = 0 | high |
Telemetry categorizes those events as aim_behavior, controlled by [TelemetryEvents] aim_behavior and [Enforcement] behavior_response. Keep them report-only until the studio has compared the events with normal gameplay and server-side match data.
Engine wrappers
Unreal and Unity teams should normally use wrapper code instead of calling raw C exports directly from gameplay scripts.
- Unreal: startup plugin/module loads the DLL and exposes Blueprint-friendly nodes.
- Unity:
KorvayneManager,KorvayneProtectedFloat, andKorvayneProtectedIntwrap native calls safely.
Return codes and flags
| Return | Meaning |
|---|---|
0 | SDK armed successfully. |
-1 | Bad arguments. |
-2 | Thread startup failed. |
-3 | Unlicensed, expired, malformed, or invalid license. SDK does not arm. |
| Flag | Meaning |
|---|---|
AC_FLAG_VALUEGUARD_RESTORE | Restore guarded values on out-of-band writes. |
AC_FLAG_TERMINATE_ON_TAMPER | Allow local termination on confirmed high-confidence evidence. |
AC_FLAG_EJECT_ON_READER | Separate aggressive reader-only override. With the reader entitlement, unsigned read-only external readers can close the protected game even without AC_FLAG_TERMINATE_ON_TAMPER. |
