Quick start
import asyncio
import crowdypy
API = "https://ck.prod.crowdedkingdoms.com"
async def main() -> None:
# The identity client: sign-in, account and studio calls, minting.
async with crowdypy.AsyncCrowdyClient(http_url=API) as identity:
await identity.auth.login("player@example.com", "correct-horse-battery")
minted = await identity.portal.mint_app_token("42")
# The game client: one per app, at the app's own datacenter.
async with crowdypy.AsyncCrowdyClient(
http_url=minted.game_api_url or API, discovery_url=minted.discovery_url
) as game:
game.set_app_token(minted)
await game.udp.connect(minted) # assign a server, open the UDP socket
print(await game.users.me())
asyncio.run(main())
Without an event loop, crowdypy.sync.CrowdyClient has the same methods
without await.
Two tokens, two clients
- Signing in yields an identity session token, for account, studio administration and minting. It is not accepted for gameplay.
- Gameplay needs a short-lived app token per app
(
portal.mint_app_token(app_id)), which is also the HMAC key for native UDP.client.refresh_gameplay_token()refreshes it, and concurrent callers share one refresh. A live UDP connection keeps its replication server across the refresh. - Build one identity client and one client per game. The game client points
at the app's datacenter (
game_api_url), anddiscovery_urllets it find the app again if that instance stops answering.
Persist sessions with crowdypy.FileTokenStore:
FileTokenStore.session_path(directory, api_origin) names the identity session
file, and FileTokenStore.app_path(directory, app_id) an app token's.
CrowdyPy sends no Origin header, so direct sign-in (auth.login,
auth.register) is available to it. A game running in a browser on its own
domain signs players in through the hosted /authorize page instead, using
CrowdyJS.
Errors
Every error is a crowdypy.CrowdyError. A GraphQL refusal is a
CrowdyGraphQLError carrying the server's stable code
(error.code == "FORBIDDEN") and its extensions. HTTP, network and timeout
failures have their own classes. A WRONG_DATACENTER refusal moves the client
to the app's datacenter and retries once, without your code doing anything.