CEEJAYDocs

Game kits

Small libraries that add CEEJAY's Connect with Discord button to a game made with Swift, Kotlin, Godot or Flutter.

A kit lets a game link its player to their Discord account in your community. It does Connect and nothing else: it starts a connect session, returns the link, the code and the QR image to the game, polls for the result, waits for the player's confirmation, keeps the player signed in, renews the player session, reads the member card and disconnects. It draws nothing: the game shows the button. Rewards and the shop are not in the kits.

Every kit does what the Connect client of the TypeScript SDK does, request for request, with the same timings (polling for the result every 3 seconds, a player session renewed a minute before it ends, two retries after a failure) and the same four states of the button.

Coming soon

The kits are not published yet. Each one is a folder of the CEEJAY repository, under sdk/kits, with its own README, and you add it to your game from that folder. Their names are not final until the first release.

The kits

KitForFolderStatus
Swift package CeejayConnectiPhone, iPad, Macsdk/kits/swiftBuilt and tested on a Mac. The parts that exist only on iPhone and iPad are written but not compiled
Kotlin library com.ceejay.connectAndroid, and Java games on a computersdk/kits/kotlinBuilt and tested (53 tests). The Android-only parts are written but not run
Godot 4 addon ceejay_connectGodot games on any platformsdk/kits/godotBuilt and tested on Godot 4.2 and 4.7 (63 tests)
Flutter package ceejay_connectFlutter gamessdk/kits/flutterBuilt and tested (56 tests). The phone's secure storage is written but not run
TypeScript, @communitystudios/ceejay/connectBrowser games, and games that run JavaScriptConnect clientBuilt and tested

Three more packages have pages of their own. The Unity package and the Unreal plugin are previews: their logic is tested, the Unreal plugin builds in Unreal Engine 5.8, and neither has been run in a game yet.

PackageForFolderStatus
C# and .NET, Ceejay.ConnectC# games, and a C# server with Ceejaysdk/dotnetPublished on NuGet (454 tests)
Unity, com.ceejay.connectUnity gamessdk/unity/com.ceejay.connectPreview. The core is the C# one above. The Unity layer is being checked in the editor
Unreal Engine, CeejayConnectUnreal gamessdk/unreal/CeejayConnectPreview. The logic is tested (203 cases). The engine layer is being checked in Unreal

A game made with another engine uses Connect for any engine, which gives the seven web requests with their exact headers and bodies.

How a player connects

The same in every kit:

The game starts the session for its player. The response has a link, a code and the URL of a QR image, and the kit stores the session on the device.

The game opens the link in a browser, or shows the code and the image on a screen with no browser. The player approves with their Discord account on CEEJAY's connect page.

The kit polls for the result every 3 seconds while the game is in the foreground, and immediately when the player returns. Once Discord returns the member's name, the kit passes it to the game. The game shows it with Confirm and Cancel, and the kit sends the player's choice. There is no default.

Both parties have approved. The kit stores the tokens in the device's secure store and moves to connected.

The connection is saved when both the Discord member and the game have approved. This confirmation matters: a code shown on a stream can be approved by anyone who reads it, so the player can reject a name that isn't theirs.

The same example in each kit

Swift
let connect = try CeejayConnect(publicKey: "ceejay_pk_…", storage: KeychainConnectStorage())
try await connect.restore()                                          // when the game starts

let session = try await connect.start(StartParams(playerId: "p_19"))
showWaiting(code: session.code, qr: session.qrURL)                   // always show the code too
Task { try? await connect.open(session, using: WebAuthenticationSessionOpener()) }

let outcome = try await connect.waitForResult { member, _ in         // asks every 3 seconds
    await askThePlayer("Connect to \(member.displayName ?? "this Discord account")?")
}

The same names in each kit

WhatSwiftKotlinGodotFlutter
Start a sessionstartstartstartstart
Start from a code generated in DiscordstartWithCodestartWithCodestart_with_codestartWithCode
Wait for the result and confirmationwaitForResultwaitForResultwait_for_resultwaitForResult
Poll once, send the confirmation, cancelgetResult, confirm, cancelgetResult, confirm, cancelget_result, confirm, cancelgetResult, confirm, cancel
Is this player connectedgetStatusgetStatusget_statusgetStatus
Restore state on launchrestorerestorerestorerestore
The player session for a requestplayerSessionplayerSessionplayer_sessionplayerSession
The member cardgetProfilegetProfileget_profilegetProfile
Disconnectdisconnectdisconnectdisconnect_playerdisconnect
The state of the buttonstate, attentionstate, attentionget_state, get_attentionstate, attention
Where to send the playerjoinUrl, manageUrljoinUrl, manageUrlget_join_url, get_manage_urljoinUrl, manageUrl
The open sessionsessionsessionget_sessionsession
Subscribe to changesonChange, stateUpdatesonChange, stateFlowstate_changedonChange, stateChanges
Poll immediatelypollNowpollNowpoll_nowpollNow

The four states are the same everywhere: not connected, waiting, connected and needs attention. Needs attention has four reasons: the Discord account never joined the server, it left the server, Discord's membership screening is still open, or the game shares something new since the player last gave consent.

Never open the link in a web view inside the game: Discord blocks sign-in there. The kit never reads the window or the sheet it opened. It polls for the result, so nothing depends on a phone switching back to the game.

DeviceOpen
iPhone, iPadThe system's web sign-in sheet (WebAuthenticationSessionOpener in the Swift kit), or Safari
AndroidA browser tab (CustomTabsLinkOpener in the Kotlin kit)
ComputerThe system browser
Browser gameA pop-up window opened by the player's own click
Console, televisionNothing. Show the code, the dashboard's URL followed by /connect, and the QR image

What a kit stores

Two things must persist after the game is closed, and both are private to the device: the refresh token, and the open session with the secret that reads its result. Every kit writes them as one JSON string under one key, ceejay.connect, in the device's secure store: the Keychain on Apple platforms, the Keystore on Android. The Godot addon cannot reach either, and says so: it stores an encrypted file, and has an interface for a store of your own.

What a kit sends

A kit communicates only with your community's CEEJAY instance. It sends the two headers Authorization and Content-Type, and these values:

  • the player ID your game gives it, and the player's name, language and age, if you pass them;
  • the device's sign-in: the refresh token and the player session that CEEJAY issued to this device, and, if you pass one, the Firebase or Unity token, the Steam ticket or the connect pass that proves the player.

It sends nothing else: no advertising ID, no device ID, no location, no contacts, no analytics and no crash reports. The Discord sign-in happens in the browser on CEEJAY's page, not in your game. As with any request, CEEJAY's server sees the device's IP address.

This is what to put on the store's privacy form for the kit. Your own declarations depend on everything else your game does.

StoreDeclare
App Store, App PrivacyIdentifiers, User ID: collected, linked to the user, used for App Functionality, not used for tracking. Contact Info, Name, if you pass the player name
Google Play, Data safetyPersonal info, User IDs: collected, not shared, required for app functionality. Name, if you pass the player name
  • Connect explains the flow, the confirmation from both the member and the game, and the proof levels.
  • Connect for any engine gives the seven requests as plain HTTP.
  • The Connect client of the TypeScript SDK is the reference every kit follows.
  • Errors lists every code of Connect.

On this page

Community StudiosPrivacyTerms