# Hovermate Game Events SDK — protocol v1 Goal: any game or mod can send gameplay events to Hovermate. Hovermate turns them into timeline markers and automatic highlights exactly like built-in game cards. Three transports cover every mod environment: network, file-only and log-only. ## 1. Connection discovery Engine writes `%LOCALAPPDATA%\Hovermate\Sdk\connection.json` while the SDK is enabled (Settings › Clips › Game events SDK, on by default): ```json { "version": 1, "url": "http://local.hovermate.gg/hovermate/v1/events", "token": "", "inbox": "C:\\Users\\\\AppData\\Local\\Hovermate\\Sdk\\Inbox" } ``` - `url` is where events are sent. Read it from this file and use it exactly as written; never hard-code or change the host, port or path. Hovermate currently writes `http://local.hovermate.gg/hovermate/v1/events`; the SDK mock server writes its own test address. - Clients read this file at start-up and again after any `401` response. The token may rotate. - `HOVERMATE_SDK_CONNECTION=` overrides the file location (tests, tools, isolated data folders). Clients always take the inbox path from the file's `inbox` field and never derive it themselves. - When the file is missing, Hovermate is not installed or the SDK is off. Clients stay silent and never throw into the game. ## 2. Transports ### 2.1 HTTP (mods with networking: C#, C++, Java, Python, JS) - `POST {url}`; headers `Authorization: Bearer `, `Content-Type: application/json`. - Requests that carry an `Origin` header are rejected with `403`, so browsers cannot post. - Body: one event object, or `{ "events": [ ... ] }` with at most 100 events. Maximum body size is 64 KB. - A batch is all-or-nothing. Hovermate validates every event first. If one is invalid, nothing is accepted and the `400` body names its position: `{ "error": "", "detail": "...", "index": 3 }`. For a game that is new in this session, `game.name` must appear in the first event of the batch that mentions it. - Responses: - `202` accepted; - `400` invalid, with body `{ "error": "", "detail": "...", "index": }`; - `401` bad or missing token; - `403` the request has an `Origin` header; - `413` body too large. A body of up to 1 MB is read and discarded first, so the client sees the status; larger bodies may be refused before they are read, and the connection is closed; - `429` more than 20 events/s per game; - `405`, `411`, `415` wrong method, missing length or wrong content type. - Clients send fire-and-forget from a background worker. They never block the game thread, use timeouts of 250 ms or less, keep a bounded queue (drop oldest) and retry at most once. ### 2.2 JSONL inbox (mods that can write files but cannot use the network) - Append UTF-8 lines to `{inbox}\.jsonl`, one event object per line, no BOM. - No token is needed: the folder belongs to the user. - Engine tails every `*.jsonl` file in the inbox from its end at start-up. A mod may truncate its file when a session starts. ### 2.3 Log-line convention (script mods that can only write to the game's own log) - Any line containing the marker `[HOVERMATE] ` followed by one JSON event object. Everything before the marker is ignored (timestamps, channel names). - The SDK card has a "Read events from a file" list where the user adds a log path. A `hello` event (see §4) that arrives over another transport can also propose one. Engine reads the file with the existing log-tail adapter. - For games whose script log has a known location, Hovermate watches it automatically while the game runs. The list lives in the game catalog (`sdkLogs`), for example `Documents\The Witcher 3\scriptslog.txt` and the Skyrim/Fallout Papyrus logs. Mods for these games need no user setup beyond enabling the game's script logging. ### 2.4 Mod-folder event file (sandboxes that can write only inside the mod's own folder) - Some mod frameworks allow writing only inside the mod's folder, for example Cyber Engine Tweaks Lua mods. Such a mod appends JSONL lines (the format of §2.2) to `hovermate-events.jsonl` in its own folder. - The user adds that file in the SDK card's "Read events from a file" list. The mod's README should tell them where it is. Hovermate tails it like an inbox file. - A mod may also print its own path once as a `[HOVERMATE]` log line or send it in `hello.files` (an array of paths) when another transport is available. Hovermate then offers to add it. ## 3. Event object ```json { "v": 1, "game": { "id": "com.example.mygame", "name": "My Game", "exe": "MyGame.exe" }, "type": "kill", "label": "Double kill", "tags": ["headshot"], "context": "Act 2 · The City", "time": "2026-11-09T21:15:03.120Z" } ``` - `v` — required, `1`. - `game.id` — required, `[a-z0-9._-]{3,64}`. Reverse-DNS or a slug. Stable across versions of the mod. - `game.name` — required in the first event or `hello` per session; at most 64 characters. - `game.exe` — optional, a file name only. It ties events to the detected game folder and lets that exe start the replay buffer. - `type` — required. Either a standard type (the shared vocabulary in `Docs/CLIPS.md`: kill, death, assist, multikill, roundWon, roundLost, matchWon, matchLost, mvp, objective, lap, bestLap, position, crash, incident, levelUp, bossKill, zone, achievement, goal, save, mission, fightWon, penalty, pit, finish, raceWon, landing, takeoff) or `"custom"`. The list in `Docs/CLIPS.md` is authoritative and only grows. An unknown standard type is rejected with `400`. - `customType` / `customLabel` — required when `type` is `"custom"`. `customType` matches `[a-z0-9_.-]{1,32}`; `customLabel` is at most 40 characters and is the toggle name shown in the card. - `label` — optional display text for this one event (marker tooltip, clip title), at most 80 characters. - `tags` — optional, at most 8 tags, each matching `[a-z0-9_-]{1,24}`. - `context` — optional map, level or area used in highlight titles, at most 64 characters. - `time` — optional ISO-8601 UTC. Engine stamps the arrival time. A `time` within ±5 s of arrival refines that stamp; anything else is ignored. - Unknown fields are ignored, so future versions only add fields. - Character limits count UTF-16 code units, as JavaScript `length` and .NET `string.Length` do. Patterns must match the whole value: a trailing newline is invalid. Strings that are empty or only whitespace count as missing. - Do not send personal data. Labels and contexts can appear in clip titles and file names. ## 4. `hello` (optional, recommended) ```json { "v": 1, "game": { "id": "com.example.mygame", "name": "My Game", "exe": "MyGame.exe" }, "type": "hello", "offers": ["kill", "death", "bossKill", { "customType": "parry", "customLabel": "Parry" }], "log": "%LOCALAPPDATA%\\MyGame\\Saved\\Logs\\MyGame.log" } ``` - Lets Hovermate create the game's card with its highlight toggles before the first real event arrives. - `offers` lists standard types and/or custom type objects. - `log` (optional) proposes a log file for the log-line convention; `files` (optional) proposes mod-folder event files (§2.4). Hovermate asks the user before it starts reading any proposed path. - `hello` is accepted over every transport, including a `[HOVERMATE]` log line. ## 5. Hovermate behaviour - The first valid event or `hello` from a new `game.id` creates an "SDK" game card. It uses the name, the exe (game folder/cover when the exe matches an installed game), a highlight toggle per offered or seen type, and before/after settings. It is off for highlights until the user turns types on; markers are always written. - Events go through the same pipeline as built-in cards: journal, markers in clips and sessions, the highlight window, notifications. - The game is attributed to the detected foreground game when `game.exe` matches it. Otherwise events are accepted only while a recording or buffer is running, and are tagged with the SDK game. - Limits: - 20 events/s per game; - 200 custom types per game; - inbox lines over 4 KB are dropped; - malformed lines are counted and shown in the card's status ("N invalid events"), never logged raw.