@ferret/accounts
The player's account in the game's own process: sign-in, session, balances, a gateway for net.
Classes
AccountService class
class AccountService implements ServiceThe player's account in the game's own process: what a local helper app (SquirrelCraft's arbiter) used to do for the original. Sign-in (user:verify), keeping and checking the session, signing out, the rewards balances. A guest is a player nobody is signed in as; the game plays on, and a later sign-in upgrades it. The Camerlengo calls all go through @ferret/net's client. Events: account:login { user }, account:logout, account:guest, account:expired, account:balance { currency, balance }.
readonly name: "account" | |
constructor(readonly opts: AccountOptions) | |
init(world: World) | |
dispose() | |
get signedIn(): boolean | |
session(): string | null | the session token for calls that need one (voice); null for a guest |
user(): AccountUser | null | |
async signIn(user: string, password: string): Promise<void> | |
signOut() | |
async valid(session = this.tok): Promise<boolean> | Is a session still good? (user:getSessionUser.) A backend that cannot be reached is "not known to be bad": true. |
async autoLoginOrGuest(): Promise<boolean> | At the start: take the session that was given or stored if it is still good, else play as a guest. Resolves with whether the player is signed in. Never throws: a backend that is down leaves a stored session in place (checked again later) or a guest. |
async check(): Promise<void> | One session check now; an expired session is renewed with the kept password, else the player is a guest again. |
async rewards(query: string, params: Record<string, unknown> = {}): Promise<Record<string, any>> | One rewards query for the signed-in player: plugin:call with the scoped key and the session. |
async balance(currency = 'PIA'): Promise<number> | |
async balances(): Promise<Record<string, number>> | every currency the account holds, as plain numbers |
async adjust(delta: number, reason: string, currency = 'PIA'): Promise<number> | earn (positive) or spend (negative); resolves with the new balance |
gateway(currency = 'PIA'): AccountGateway | The @ferret/net account gateway over this service: a guest has no name and 0 balance; spending needs a sign-in. |
packages/accounts/src/account.ts:32
HelperStubs class
class HelperStubs implements ServiceThe two calls the original's local helper app (SquirrelCraft's arbiter) accepted and only wrote to its log, because the thing behind them was never built: the shared "AI teacher" bot of a voice room, and a player coming near to or leaving an artifact. They are kept as calls with the same names and arguments, so a game that makes them does not change when the real thing exists; for now each is logged (log) and announced as an event, which a game or a backend adapter can listen to:
`teacher:start` / `teacher:stop` { room, identity } identity is "npc:<Name>"; one bot per room serves everybody in it
`artifact:near` / `artifact:far` { artifactId }readonly name: "helper-stubs" | |
readonly log: string[] | what was asked, in order (<event> <json>), for tests and for looking at what a game does |
constructor(private opts: { sink?: (line: string) => void } = {}) | |
init(world: World) | |
teacherAgent(action: 'start' | 'stop', room: string, identity: string) | Ask for the shared teacher bot of a voice room to start or stop (not a voice join: that is for a player's own presence). |
artifactNear(artifactId: string) | |
artifactFar(artifactId: string) |
packages/accounts/src/helper-stubs.ts:11
Functions
signInCard function
function signInCard(account: AccountService, opts: { document?: Document; strings?: Partial<SignInStrings> } = {}): Promise<boolean>A card over the game that asks for the account (the helper app's login dialog, in the page). Resolves when the player has signed in (true) or chose to play as a guest or closed the card (false); the level keeps running underneath either way.
packages/accounts/src/sign-in.ts:32
Interfaces
AccountOptions interface
interface AccountOptionsclient: CamerlengoClient | the backend client; its appKey is the key for user:verify / user:getSessionUser |
path?: string | the user namespace of the sign-in (default "/users") |
rewardsKey?: string | a key scoped to plugin:call on the rewards plugin only; without it there are no balances |
rewardsPlugin?: string | the rewards plugin (default "GameRewards") |
checkMinutes?: number | minutes between session checks while signed in (default 30); an expired session is renewed with the password kept in memory |
store?: KeyValueStore | |
storeKey?: string | |
session?: string | a session obtained elsewhere (a launcher, a link); checked like a stored one |
packages/accounts/src/account.ts:7
AccountUser interface
interface AccountUserid: string | |
name: string |
packages/accounts/src/account.ts:24
KeyValueStore interface
interface KeyValueStoreWhere the session is kept between page loads (a Storage: localStorage; tests pass a Map-backed stand-in).
getItem(k: string): string | null | |
setItem(k: string, v: string): void | |
removeItem(k: string): void |
packages/accounts/src/account.ts:5
SignInStrings interface
interface SignInStringsText of the sign-in card; a game can translate it.
title: string | |
email: string | |
password: string | |
signIn: string | |
guest: string | |
close: string | |
busy: string | |
wrong: string | |
down: string |
packages/accounts/src/sign-in.ts:4
Constants
defaultStrings const
const defaultStrings: SignInStringspackages/accounts/src/sign-in.ts:5