Arcademia.Achievements.Cpp
1.1.0
dotnet add package Arcademia.Achievements.Cpp --version 1.1.0
NuGet\Install-Package Arcademia.Achievements.Cpp -Version 1.1.0
<PackageReference Include="Arcademia.Achievements.Cpp" Version="1.1.0" />
<PackageVersion Include="Arcademia.Achievements.Cpp" Version="1.1.0" />
<PackageReference Include="Arcademia.Achievements.Cpp" />
paket add Arcademia.Achievements.Cpp --version 1.1.0
#r "nuget: Arcademia.Achievements.Cpp, 1.1.0"
#:package Arcademia.Achievements.Cpp@1.1.0
#addin nuget:?package=Arcademia.Achievements.Cpp&version=1.1.0
#tool nuget:?package=Arcademia.Achievements.Cpp&version=1.1.0
Arcademia Achievements SDK (C++)
Unlock achievements from your game and let players collect them on their Arcademia account. You set the achievements up on the Arcademia manager, and your game only ever sends the achievement's API name.
This is the native build of the SDK: a flat C ABI shared library, for anything that isn't Unity or .NET, a custom C++ engine, or any other language with basic C FFI support (Python's ctypes, Go's cgo, Rust and so on). If you're building in Unity, use the Unity package. If you're on .NET (including Godot's C# scripting), use the NuGet package.
Full platform docs: https://manager.arcademia.ac/docs
Windows x64 only for now, since live mode is tied to the arcade cabinets' named-pipe transport.
Install
NuGet (Visual Studio / MSBuild C++ projects)
nuget install Arcademia.Achievements.Cpp
or add it through Visual Studio's NuGet Package Manager. This sets up the include path, library path and a post-build DLL copy for you.
Build from source
Requires CMake 3.20+ and a C++17 compiler targeting Windows (MSVC or MinGW-w64).
cmake -S . -B build
cmake --build build --config Release
Produces arcademia_achievements.dll (plus its import library) and a
quickstart sample executable.
This library is completely separate from the leaderboards library. Use one, the other, or both.
Setting up
- On the manager, open your game and click the trophy icon to get to Achievements.
- Request access. Once it's approved, generate an achievements API key. This is a different key from the leaderboards one.
- Pick who competes (see "Scopes" below) and add your achievements. The API
name is what your code uses, for example
FIRST_BLOOD. - Put the key in an
arcademia.jsonfile next to your built executable:
{
"apiBase": "https://manager.arcademia.ac",
"achievementsKey": "arc_xxxxxxxx_..."
}
If you also use the leaderboards SDK, keep its apiKey in the same file.
Each SDK only reads its own key. You can also call
arcademia_achievements_configure(api_base, achievements_key). Pass NULL
for either argument to keep the current value.
Quick start
#include <arcademia_achievements.h>
void OnLevelTenCleared()
{
arcademia_achievements_free(arcademia_achievements_unlock("FIRST_BLOOD"));
}
On a cabinet that's all you need. The launcher shows the toast over your game and offers the player a QR code to claim it when the game closes. On your own PC nothing appears on screen until your game draws the toasts (see Drawing toasts yourself). Unlocking the same achievement again in the same playthrough does nothing, so you don't need to track it yourself.
Every call that returns data gives you a JSON string. Parse it with
whatever JSON library you already use, then release it with
arcademia_achievements_free, never your own free or delete. Calls
block while they talk to the launcher or the server, so run them off your
render thread if a short stall matters.
Two modes, one API
| Launcher (Live) | Sandbox | |
|---|---|---|
| When | The game was started by the Arcademia launcher on a cabinet | Anywhere else: your dev machine, a build you're testing |
| Auth | Nothing you set. The launcher and the cabinet handle it | Your achievements key |
| Unlocks land on | The live achievements for that cabinet's team | A private test area only you can see |
| Toasts | Drawn by the launcher on top of your game | Passed to your toast callback for you to draw |
| Claiming | A QR code on the cabinet after the game closes | arcademia_achievements_request_sandbox_claim gives you a link |
arcademia_achievements_mode() returns ARCADEMIA_ACHIEVEMENTS_MODE_LAUNCHER
or ARCADEMIA_ACHIEVEMENTS_MODE_SANDBOX. The SDK picks the mode itself by
checking for environment variables the launcher sets.
Scopes
You choose one scope per game on the manager:
- Sessional: every playthrough starts fresh. Players always claim achievements for themselves.
- Local: each arcade machine competes on its own.
- Institutional: each site competes as a team.
- National: each country competes as a team.
For the team scopes, the first time a team unlocks an achievement it's recorded against the team straight away, even if nobody claims it. A player who claims it afterwards is named as the team's claimer. Each achievement also has a "personal claims" switch. When it's on, players can add the achievement to their own collection too (once per team, so they can collect it again at another site).
API
void arcademia_achievements_init(void);
void arcademia_achievements_shutdown(void);
int arcademia_achievements_mode(void);
void arcademia_achievements_configure(const char* api_base, const char* achievements_key);
const char* arcademia_achievements_ping(void);
const char* arcademia_achievements_get(void);
const char* arcademia_achievements_unlock(const char* api_name);
const char* arcademia_achievements_open_overlay(void);
const char* arcademia_achievements_poll_toast(void);
const char* arcademia_achievements_icon_file(const char* icon_url_or_path);
void arcademia_achievements_set_toast_callback(arcademia_achievements_toast_callback cb, void* user_data);
void arcademia_achievements_set_claim_link_callback(arcademia_achievements_claim_link_callback cb, void* user_data);
void arcademia_achievements_new_sandbox_session(void);
const char* arcademia_achievements_request_sandbox_claim(void);
void arcademia_achievements_free(const char* ptr);
init is optional, every call initialises the SDK on first use.
arcademia_achievements_unlock
{
"Success": true,
"Status": "unlocked",
"ApiName": "FIRST_BLOOD",
"Name": "First Blood",
"Description": "Win your first round",
"IconUrl": "https://manager.arcademia.ac/api/Achievements/Icons/default",
"IconPath": null,
"AllowPersonal": true,
"TeamHadIt": false,
"TeamLabel": "University of Lincoln",
"TeamClaimedBy": null,
"Scope": "Institutional",
"Offline": false,
"ShowToastInGame": false,
"Message": null,
"Mode": "Launcher"
}
Status is one of:
unlocked: first time this playthrough.alreadyUnlocked: already unlocked this playthrough. Nothing happens, and the result only hasSuccess,Status,ApiNameandMode.unknown: no achievement with that API name exists for your game.rejectedorerror: something went wrong, seeMessage.
TeamHadIt, TeamLabel and TeamClaimedBy tell you whether the player's
team already had the achievement. Offline is true when the cabinet has
no connection and the unlock was queued to send later.
arcademia_achievements_get
{
"Success": true,
"Mode": "Launcher",
"Offline": false,
"GameName": "My Game",
"Scope": "Institutional",
"TeamLabel": "University of Lincoln",
"Achievements": [
{
"ApiName": "FIRST_BLOOD",
"Name": "First Blood",
"Description": "Win your first round",
"IconUrl": "https://manager.arcademia.ac/api/Achievements/Icons/default",
"IconPath": "C:\\...\\Achievements\\Icons\\b1258....png",
"Hidden": false,
"AllowPersonal": true,
"SortOrder": 0,
"UnlockedThisSession": true,
"HeldByTeam": true,
"Unlocked": true,
"TeamUnlockedAt": "2026-09-25T00:21:53.132Z",
"TeamClaimedBy": null
}
]
}
Achievements with Hidden set are secret. Hide their name and description
in your own screens until Unlocked is true.
Drawing toasts yourself
The launcher draws toasts on a cabinet, so you usually don't need to. Your toast callback is called when your game should draw one instead:
- in sandbox mode, so you can see unlocks while testing, and
- on a cabinet when the launcher can't draw over your game (true exclusive fullscreen, see below).
The simplest way is to ask for toasts once a frame from your main loop. It
returns NULL when nothing is waiting:
while (const char* toast_json = arcademia_achievements_poll_toast())
{
MyHud::QueueToast(toast_json);
arcademia_achievements_free(toast_json);
}
Or set a callback. It runs on the thread that called
arcademia_achievements_unlock, and the string is only valid during the
callback, so copy it if you need it later. Once a callback is set, toasts go
to it instead of the poll queue, so using both never shows a toast twice:
static void OnToast(const char* toast_json, void* user_data)
{
MyHud::QueueToast(toast_json);
}
arcademia_achievements_set_toast_callback(OnToast, nullptr);
If neither is set up, the library writes a warning to stderr and the debugger output each time a toast is dropped.
The JSON has Title and Subtitle as ready-made text, plus Name,
Description, IconUrl, IconPath, TeamHadIt, TeamLabel and
AllowPersonal. TeamHadIt is true when the player's team already held
the achievement, which is worth styling differently. IconPath is a local
image file whenever the icon could be loaded: the launcher's copy on a
cabinet, or one the library downloaded in sandbox mode, so you can load it
the same way as any other texture.
arcademia_achievements_icon_file(icon_url) gives you the same for any
icon in arcademia_achievements_get, for your own achievements screen.
Free its result with arcademia_achievements_free.
Achievements screen
Call arcademia_achievements_open_overlay from a menu button to show a
Steam-style list of every achievement over your game. On a cabinet the
launcher draws the list and the call blocks until the player closes it with
Exit, so call it from a worker thread and pause your game until it returns.
Your game still receives controller input while the list is open, so make
sure a paused game ignores it.
{ "Success": true, "Status": "closed", "DrawInGame": false, "Message": null, "Mode": "Launcher" }
DrawInGame is true (with Status set to renderInGame) in sandbox mode,
where there's no launcher, and when the launcher can't draw over your game.
Draw your own screen from arcademia_achievements_get in that case.
Fullscreen
On a cabinet the launcher draws toasts and the list in a window on top of
your game. That works with windowed and borderless fullscreen, and with
normal fullscreen on Windows 10 and 11. It can't draw over a game in true
exclusive fullscreen, so prefer borderless. If the launcher detects
exclusive fullscreen anyway, unlocks come back with ShowToastInGame set,
your toast callback is called, and the overlay call returns DrawInGame.
Testing
Everything works on your own PC in sandbox mode. Unlocks go to a test area that only you can see.
arcademia_achievements_new_sandbox_session()simulates a new playthrough.arcademia_achievements_request_sandbox_claim()creates a claim link for the current sandbox playthrough, so you can try the claim page yourself. The link is written to stderr and the debugger output, and passed to the callback set witharcademia_achievements_set_claim_link_callback. The call blocks until the link is used or expires after 5 minutes. Only the game's owners can claim sandbox playthroughs.- The manager's Achievements page has a Sandbox tab showing your test unlocks, with a Reset button.
Sample
samples/quickstart/main.cpp is a console app with a menu that exercises
every call. It's built along with the library.
License
MIT, see LICENSE.md.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| native | native is compatible. |
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.