Preview documentation
This page has not completed release review. Its SDK or protocol version is not yet a confirmed public release.
GameLink C++ Events and Subscriptions¶
GameLink events are callback collections owned by gamelink::SDK. This reference is pinned to public commit 16c6b97, which has no public release tag.
Callback model¶
Event<T>::Add registers a persistent std::function<void(const T&)> and returns a uint32_t handle. Remove the callback through the same event:
auto& updates = sdk.OnStateUpdate();
const std::uint32_t handle = updates.Add(
[](const gamelink::schema::SubscribeStateUpdateResponse<nlohmann::json>& response) {
if (const auto* error = gamelink::FirstError(response)) {
report(error->number, error->title.c_str(), error->detail.c_str());
return;
}
useState(response.data.state);
});
sdk.SubscribeToStateUpdates(gamelink::StateTarget::Channel);
// When the listener is no longer needed:
sdk.UnsubscribeFromStateUpdates(gamelink::StateTarget::Channel);
updates.Remove(handle);
AddUnique(name, callback) replaces any callback with the same name. RemoveByName(name) removes a named callback.
Callbacks run synchronously in the thread calling SDK::ReceiveMessage. Response references and their nested data are borrowed and valid only until the callback returns. Copy data before deferring work, and never invoke ReceiveMessage recursively.
Most event streams require both a local callback and a server subscription:
| Event accessor and response type | Required request |
|---|---|
OnAuthenticate() → schema::AuthenticateResponse |
None; authentication responses dispatch automatically. |
OnStateUpdate() → schema::SubscribeStateUpdateResponse<nlohmann::json> |
SubscribeToStateUpdates(StateTarget) |
OnConfigUpdate() → schema::ConfigUpdateResponse |
SubscribeToConfigurationChanges(ConfigTarget) |
OnDatastreamUpdate() → schema::DatastreamUpdate |
SubscribeToDatastream() |
OnPollUpdate() → schema::PollUpdateResponse |
SubscribeToPoll(pollId) |
OnTransaction() → schema::TransactionResponse |
SubscribeToSKU(sku) or SubscribeToAllPurchases() |
Duplicate subscription calls are suppressed by the pinned SDK and generally return ANY_REQUEST_ID while emitting a debug message.
Debug messages and response errors¶
OnDebugMessage is a single diagnostic callback, not an Event<T>:
sdk.OnDebugMessage([](const gamelink::string& message) {
log(message.c_str());
});
// Replaces the existing debug callback if called again.
sdk.DetachOnDebugMessage();
With a debug callback attached, the pinned implementation logs complete outbound and inbound protocol payloads. Treat those logs as potentially sensitive. Server failures remain in each response envelope's errors vector; check FirstError(response) before reading data.
Datastream events¶
The datastream delivers batches of events. Each schema::DatastreamEvent has an arbitrary JSON event and a Unix-seconds timestamp.
sdk.OnDatastreamUpdate().Add(
[](const gamelink::schema::DatastreamUpdate& response) {
if (!response.errors.empty()) {
return;
}
for (const auto& item : response.data.events) {
consume(item.event, item.timestamp);
}
});
sdk.SubscribeToDatastream();
Broadcasts are outbound messages to viewers on the channel using the extension. topic is the frontend filter key.
nlohmann::json message = {{"kind", "round-start"}, {"round", 4}};
sdk.SendBroadcast("game-events", message);
The overloads are:
template<typename T>
gamelink::RequestId SendBroadcast(const gamelink::string& topic, const T& value);
gamelink::RequestId SendBroadcast(
const gamelink::string& topic,
const nlohmann::json& object);
gamelink::RequestId SendBroadcast(const gamelink::string& topic);
The serialized message must be under 8 KiB. The JSON overload requires an object, not a primitive or array. Stop delivery with UnsubscribeFromDatastream().
State and configuration updates¶
Register one event callback for each update family, then subscribe separately for each target you need:
sdk.OnConfigUpdate().Add(
[](const gamelink::schema::ConfigUpdateResponse& response) {
if (response.errors.empty()) {
applyConfig(response.data.config, response.data.topicId);
}
});
sdk.SubscribeToConfigurationChanges(gamelink::ConfigTarget::Channel);
sdk.SubscribeToConfigurationChanges(gamelink::ConfigTarget::Extension);
All callbacks attached to an event receive all updates dispatched to that event. Inspect response metadata and data fields when one callback needs to filter a particular target. See state and configuration operations for read and write APIs.
Polls¶
The core poll API uses C++ containers and callbacks:
gamelink::RequestId CreatePoll(
const gamelink::string& pollId,
const gamelink::string& prompt,
const std::vector<gamelink::string>& options);
gamelink::RequestId GetPoll(
const gamelink::string& pollId,
std::function<void(const gamelink::schema::GetPollResponse&)> callback);
gamelink::RequestId SubscribeToPoll(const gamelink::string& pollId);
gamelink::RequestId UnsubscribeFromPoll(const gamelink::string& pollId);
gamelink::RequestId DeletePoll(const gamelink::string& pollId);
Attach OnPollUpdate() before subscribing. Every callback receives updates for every subscribed poll, so filter on response.data.poll.pollId when necessary. GetPoll has a one-shot callback overload and returns results in response.data.results alongside the poll, mean, sum, and count.
The SDK also provides CreatePollWithConfiguration, RunPoll, StopPoll, and SetPollDisabled. RunPoll coordinates delete/create/subscribe behavior and accepts update and finish callbacks. Use StopPoll, not DeletePoll, when you need a RunPoll finish callback.
Local validation limits at the pinned commit are 256 characters for the prompt, 10 options, and 128 characters per option. A local limit failure returns REJECTED_REQUEST_ID and emits a debug message.
Purchase transactions¶
auto& purchases = sdk.OnTransaction();
purchases.Add([](const gamelink::schema::TransactionResponse& response) {
if (const auto* error = gamelink::FirstError(response)) {
report(error->number, error->title.c_str(), error->detail.c_str());
return;
}
const auto& transaction = response.data;
grantOnce(transaction.muxyId, transaction.sku, transaction.userId);
});
sdk.SubscribeToSKU("coins-100");
OnTransaction receives all subscribed SKUs; filter response.data.sku inside the callback. Available operations are:
| C++ API | Purpose |
|---|---|
SubscribeToSKU(sku) / UnsubscribeFromSKU(sku) |
Manage one SKU subscription. |
SubscribeToAllPurchases() / UnsubscribeFromAllPurchases() |
Manage the all-purchases subscription. |
GetOutstandingTransactions(sku, callback) |
Return up to 10 unvalidated transactions, oldest first; use "*" for all SKUs. |
ValidateTransaction(txid, details) |
Mark a Muxy transaction ID as validated. |
RefundTransactionByID(txid, userId) |
Refund by Muxy transaction ID and user ID. |
RefundTransactionBySKU(sku, userId) |
Refund by SKU and user ID. |
Grant and durably record an entitlement before validation, and make grants idempotent by muxyId.