The game’s settings
phantom.aj.settingsThe screen and sound
The client's settings.
Scripts and plugins
A script has all of it, as phantom.aj.settings, and so does a plugin, from ctx.phantom(): the SDK runs in the plugin's own frame. Each call is marked with what it needs: game:read for what the area knows and hears, which "game": "read" in the manifest grants, and game:act for doing things in it as the player, which needs "game": "act" (see Permissions).
Overview
| Member | What it does | Plugins |
|---|---|---|
all() | Every toggle as the Settings screen shows it, read from the account's field in one message, or null before login. | game:read |
cursor() | The pointer the player chose, kept on this computer: custom (the game's) when none. | game:read |
get() | One toggle as the screen shows it, or null before login. | game:read |
isChatPredictionAnswered() | Whether the player ever answered the chat prediction question (hasChatSettingBeenSet). | game:read |
names() | Every toggle's name, for a tool that walks them. | game:read |
quality() | The quality the client goes back to (gMainFrame.currStageQuality) after a room join, a minigame or Jammer Central, or null before it set one. | game:read |
saved() | Everything the client keeps on this computer (GuiManager.sharedObj.data), in one read: the pointer, the last Jam-a-gram colour and pattern, the player wall's choices and stickers, and where the Settings screen's music slider was left. | game:read |
set() | Turns a toggle on or off as the Settings screen does: one bit of the account's field, through the client's own requestSetUserVar, so the account keeps it. | game:act |
setCursor() | Switches the pointer as the Settings screen's buttons do (CursorManager.switchToCursor), keeping the choice on this computer. | game:act |
setQuality() | Sets the quality the client goes back to, and puts it on the stage as the client does (MainFrame.handleResize), so it holds through the next room join. | game:act |
setSaved() | Keeps one of those on this computer, through the client's own setSharedObj, which writes the file. | game:act |
showTextCursor() | Shows the text pointer (CursorManager.showICursor) as the client's text fields do, until the handle puts the one before back. | game:act |
toggle() | Turns a toggle the other way, and resolves with every toggle afterwards. | game:act |
onChange() | Hears the toggles change, whoever changed them (the Settings screen, set), from the server's answer with the field: every toggle as it now stands. | game:read |
onCursorChange() | Hears the pointer switch, by the client's name for it (custom_cursor, ibeam…). | game:read |
onQualityChange() | Hears the quality the client goes back to change, whoever changed it. | game:read |
onSavedChange() | Hears the client keep one of those choices, whoever asked, by its key and value. | game:read |
Methods
all
all() => Promise<ClientSettings | null>Every toggle as the Settings screen shows it, read from the account's field in one message, or null before login. An account with no field yet reads each toggle's default.
Returns
Promise<ClientSettings \| null>
Types
cursor
cursor() => Promise<CursorKind>The pointer the player chose, kept on this computer: custom (the game's) when none.
Returns
Promise<CursorKind>
Types
get
get(name: "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge") => Promise<boolean | null>One toggle as the screen shows it, or null before login.
Parameters
| Name | Type | |
|---|---|---|
name | "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge" |
Returns
Promise<boolean \| null>
isChatPredictionAnswered
isChatPredictionAnswered() => Promise<boolean>Whether the player ever answered the chat prediction question (hasChatSettingBeenSet). Until they do, a player on safe chat has prediction off whatever its toggle says.
Returns
Promise<boolean>
names
names() => ("denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge")[]Every toggle's name, for a tool that walks them.
Returns
("denPlayerIcon" \| "doorBell" \| "gameInvites" \| "jammerWallIcon" \| "autoServerTravel" \| "buddyRequests" \| "chatPrediction" \| "usernameBadge")[]
quality
quality() => Promise<GraphicsQuality | null>The quality the client goes back to (gMainFrame.currStageQuality) after a room join, a minigame or Jammer Central, or null before it set one.
Returns
Promise<GraphicsQuality \| null>
saved
saved() => Promise<SavedSettings>Everything the client keeps on this computer (GuiManager.sharedObj.data), in one read: the pointer, the last Jam-a-gram colour and pattern, the player wall's choices and stickers, and where the Settings screen's music slider was left. Null for what it was never given, and for everything before the client opened its file.
Returns
Promise<SavedSettings>
Types
SavedSettings · FlashData · FlashPlace · FlashRead · FlashWrite · HoldOptions · FlashArgumentLike · FlashValue · FlashArgument · AnyFlash · FlashMethod · TypedFlash · FlashConstructor
set
set(name: "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge", on: boolean, options?: ActOptions) => Promise<ClientSettings>Turns a toggle on or off as the Settings screen does: one bit of the account's field, through the client's own requestSetUserVar, so the account keeps it. Resolves with every toggle once the server has answered with the field. REFUSED while the player is invisible (the client sends nothing then) or when the server's field does not have it; TIMEOUT with no answer. An open Settings screen is not redrawn, and the Jammer Wall's HUD button follows at the next HUD build.
Parameters
| Name | Type | |
|---|---|---|
name | "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge" | |
on | boolean | |
options optional | ActOptions |
Returns
Promise<ClientSettings>
Types
setCursor
setCursor(kind: CursorKind, options?: ActOptions) => Promise<CursorKind>Switches the pointer as the Settings screen's buttons do (CursorManager.switchToCursor), keeping the choice on this computer. Resolves once the game draws it; NOT_READY before the client has made its pointer.
Parameters
| Name | Type | |
|---|---|---|
kind | CursorKind | |
options optional | ActOptions |
Returns
Promise<CursorKind>
Types
setQuality
setQuality(quality: GraphicsQuality, options?: ActOptions) => Promise<GraphicsQuality>Sets the quality the client goes back to, and puts it on the stage as the client does (MainFrame.handleResize), so it holds through the next room join. The client works one out again when the window is resized: phantom.aj.render keeps one against it. On this screen only, and not kept once the game closes.
Parameters
| Name | Type | |
|---|---|---|
quality | GraphicsQuality | |
options optional | ActOptions |
Returns
Promise<GraphicsQuality>
Types
setSaved
setSaved(name: "volume" | "cursor" | "decorId" | "expiration" | "msgColor" | "msgPattern" | "reportedPosts" | "stickerPositions", value: FlashData, options?: ActOptions) => Promise<FlashData>Keeps one of those on this computer, through the client's own setSharedObj, which writes the file. Resolves with what is kept; NOT_READY before the client opened its file.
Parameters
| Name | Type | |
|---|---|---|
name | "volume" | "cursor" | "decorId" | "expiration" | "msgColor" | "msgPattern" | "reportedPosts" | "stickerPositions" | |
value | FlashData | |
options optional | ActOptions |
Returns
Promise<FlashData>
Types
showTextCursor
showTextCursor(options?: ActOptions) => Promise<() => Promise<void>>Shows the text pointer (CursorManager.showICursor) as the client's text fields do, until the handle puts the one before back. REFUSED while the system pointer is drawn, which the client leaves alone.
Parameters
| Name | Type | |
|---|---|---|
options optional | ActOptions |
Returns
Promise<() => Promise<void>>
Types
toggle
toggle(name: "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge", options?: ActOptions) => Promise<ClientSettings>Turns a toggle the other way, and resolves with every toggle afterwards.
Parameters
| Name | Type | |
|---|---|---|
name | "denPlayerIcon" | "doorBell" | "gameInvites" | "jammerWallIcon" | "autoServerTravel" | "buddyRequests" | "chatPrediction" | "usernameBadge" | |
options optional | ActOptions |
Returns
Promise<ClientSettings>
Types
Events
onChange
onChange(listener: (settings: ClientSettings) => void) => () => voidHears the toggles change, whoever changed them (the Settings screen, set), from the server's answer with the field: every toggle as it now stands.
Parameters
| Name | Type | |
|---|---|---|
listener | (settings: ClientSettings) => void |
Returns
() => void. Call it to stop listening.
Types
onCursorChange
onCursorChange(listener: (change: { cursor: string; }) => void) => () => voidHears the pointer switch, by the client's name for it (custom_cursor, ibeam…).
Parameters
| Name | Type | |
|---|---|---|
listener | (change: { cursor: string; }) => void |
Returns
() => void. Call it to stop listening.
onQualityChange
onQualityChange(listener: (quality: GraphicsQuality, previous: GraphicsQuality | null) => void) => () => voidHears the quality the client goes back to change, whoever changed it.
Parameters
| Name | Type | |
|---|---|---|
listener | (quality: GraphicsQuality, previous: GraphicsQuality | null) => void |
Returns
() => void. Call it to stop listening.
Types
onSavedChange
onSavedChange(listener: (change: SavedChange) => void) => () => voidHears the client keep one of those choices, whoever asked, by its key and value.
Parameters
| Name | Type | |
|---|---|---|
listener | (change: SavedChange) => void |
Returns
() => void. Call it to stop listening.
Types
Types
The types the calls above take and give, with every field. Import any of them in a plugin from @phantomclient/plugin/sdk, or use them as they are in a script.
ClientSettings
Every toggle on the game's Settings screen, as the screen shows it.
| Field | Type | |
|---|---|---|
denPlayerIcon | boolean | |
doorBell | boolean | |
gameInvites | boolean | |
jammerWallIcon | boolean | |
autoServerTravel | boolean | |
buddyRequests | boolean | |
chatPrediction | boolean | |
usernameBadge | boolean |
ActOptions
How long something that acts may take, and what may end it first.
| Field | Type | |
|---|---|---|
timeoutMs optional | number | undefined | 10 seconds by default. |
signal optional | AbortSignal | undefined |
CursorKind
Which pointer the game draws: its own wooden one, or the system's.
type CursorKind = 'custom' | 'default'GraphicsQuality
How finely Flash draws, from cheapest to best.
type GraphicsQuality = 'low' | 'medium' | 'high' | 'best'SavedSettings
Everything the client keeps on this computer, with null for what it was never given.
| Field | Type | |
|---|---|---|
volume | FlashData | |
cursor | FlashData | |
decorId | FlashData | |
expiration | FlashData | |
msgColor | FlashData | |
msgPattern | FlashData | |
reportedPosts | FlashData | |
stickerPositions | FlashData |
FlashData
Plain data read from Flash, with objects that live there as typed places.
type FlashData = | null
| undefined
| boolean
| number
| string
| FlashData[]
| { [key: string]: FlashData }
| TypedFlash<unknown>FlashPlace
The operations every place has, whatever its type.
| Field | Type | |
|---|---|---|
$get | () => Promise<FlashRead<T>> | Reads the value here: plain data as it is, an object as a typed place held by handle. |
$set | (value: FlashWrite<T>) => Promise<void> | Writes the value here, once. The client may put its own back a frame later: a member it sets every frame, or on every redraw, or an object it builds again for the next room. For a change that has to stay, use $keep. |
$keep | (value: FlashWrite<T>, options?: HoldOptions | undefined) => Promise<() => Promise<void>> | Writes the value here and keeps it here, until the function it gives back is called, which puts back what was there. It is $set for a change that has to last. The game writes it itself, every frame, so a value the client puts back is overwritten before Flash draws it. The place is followed rather than pinned: nothing is lost when the object is not there yet (it is written as soon as it is) or when the client builds it again (the new one is written too). It is phantom.flash.hold on this place, and takes the same options. ts const hud = phantom.flash.use('gui.GuiManager').mainHud; const faded = await hud.alpha.$keep(0.5); |
$call | (...args: FlashArgumentLike[]) => Promise<FlashData> | Calls what is here, whatever the declarations say is at this place. A place is callable in its own right (avatars.createAvatar(id, x, y, name)), which is how to write a call the declarations describe: the arguments and the answer are both checked. This is the same call for the places they cannot describe, and it saves casting one to reach it: - a class whose instance side declares nothing, because every member of it is static (gui.EmoticonUtility), so $as and a hook's self give a place with no members; - an object the client typed as Object or *, or one reached with $at; - a member holding a function, such as a callback the client keeps in a field. It answers FlashData, since there is no declared return to read it as. ts const emotes = phantom.flash.use('gui.EmoticonUtility'); console.log(await emotes.stringForId(3)); console.log(await emotes.$at('stringForId').$call(3)); |
$listen | (event: string, listener: (event: FlashData, keep: <Kept>(value: Kept) => Kept) => void, options?: { read?: readonly (readonly string[])[] | undefined; capture?: boolean | undefined; } | undefined) => Promise<() => Promise<void>> | Listens for an event on the object here. Resolves with what stops listening. Without read, the event is its readable members, objects among them as typed places held by handle, and every one of them is released once the listener returns, except those passed to keep before then (release those with $release when done). read names the paths to read as the event is dispatched instead: the event is then { className, type, read } with the values in that order, and nothing is held. A listener that ignores the event passes read: []. capture listens on the way down. Both are FlashBridge.listen's options. ts await stage.$listen('mouseMove', (event) => console.log((event as { read: number[] }).read), { read: [['stageX'], ['stageY']], }); |
$describe | () => Promise<FlashValue> | The public members of what is here, as Flash's describeType lists them. |
$at | (...path: string[]) => AnyFlash | Further along, by names the types do not know: untyped from here on. |
$as | { <Name extends keyof ClientInstances & string>(name: Name): TypedFlash<ClientInstances[Name]>; (name: string): AnyFlash; } | The same place, read as the client's name from here on. Nothing is sent and nothing is checked in the game: it says what the object here is, so the editor completes and checks its members again after a step the declarations could not follow ($at, a hook's capture, anything the client typed as Object or *). Naming the wrong class is not caught here; the read or call that follows is what fails. ts const grid = phantom.flash .use('gui.AvatarEditor') .$at('_colorTableColor1') .$as('gui.ColorTable'); console.log(await grid._numCols.$get(), 'by', await grid._numRows.$get()); |
$release | () => Promise<void> | Releases the object this place is held by, when it is one; nothing otherwise. |
$reference | FlashReference | The untyped reference underneath. |
FlashRead
What reading a place of type T resolves with.
type FlashRead<T> = unknown extends T
? FlashData
: T extends Primitive
? T
: T extends readonly (infer Item)[]
? FlashRead<Item>[]
: T extends (...args: never[]) => unknown
? TypedFlash<unknown>
: TypedFlash<T>FlashWrite
What may be given where Flash expects T.
type FlashWrite<T> = unknown extends T
? FlashArgumentLike
: T extends Primitive
? T
: T extends readonly (infer Item)[]
? FlashWrite<Item>[]
: T extends (...args: never[]) => unknown
? ((...args: FlashData[]) => void) | FlashCallback
: TypedFlash<T> | FlashHandle | FlashArgumentLikeHoldOptions
How a hold behaves.
| Field | Type | |
|---|---|---|
everyFrames optional | number | undefined | Write on every nth frame. Every frame by default, which is what a value the client resets needs. |
when optional | "enter" | "exit" | undefined | Which half of the frame to write in. 'enter' by default, before the frame is read. Use 'exit' for a member the game writes every frame of its own, such as a thing it pins to the pointer. Two objects' enter-frame listeners have no order between them, so an ordinary hold on one of those stands only on the frames the loader happens to run second, and the value flickers or never takes at all. Exit-frame work runs after every enter-frame listener, so what is held is what is drawn and what the next frame reads. |
while optional | HookWhen | undefined | Only while this holds, in the same rules as a hook's when, read between calls. |
once optional | boolean | undefined | Write once, on the first frame the condition holds, then stop. |
restore optional | boolean | undefined | Put back what was there before the first write when the hold ends. On by default. |
onFailed optional | ((error: string) => void) | undefined | Called if the game turns the hold off because a write failed. |
FlashArgumentLike
Anything the bridge carries, typed places included.
type FlashArgumentLike = FlashArgument | TypedFlash<unknown> | FlashArgumentLike[] | { [key: string]: FlashArgumentLike }FlashValue
A value on the TypeScript side: plain data, undefined, or a handle to an object in Flash.
type FlashValue = | null
| undefined
| boolean
| number
| string
| FlashValue[]
| { [key: string]: FlashValue }
| FlashHandleFlashArgument
What may be passed to Flash: a value, a function Flash may call, or an object to make there.
type FlashArgument = | FlashValue
| FlashArgument[]
| { [key: string]: FlashArgument }
| ((...args: FlashValue[]) => void)
| FlashNewAnyFlash
A place whose class the declarations do not describe: phantom.flash.use('a.Class') for a class the client has no declaration for, $at, $as with a name, or anything read back from one.
Every member is another place of the same kind, and every place can be called, which is what reflection allows and what a place does at run time. Nothing is checked, because there is nothing to check it against: a name the game does not have fails when it is used, not here. then is left out, so awaiting a place is still the mistake it always was.
type AnyFlash = FlashPlace<unknown> &
FlashMethod<unknown[], unknown> & {
readonly [member: string]: AnyFlash;
} & { then?: undefined }FlashMethod
A method of the client, called with checked arguments.
type FlashMethod<Args extends readonly unknown[], Result> = (
...args: { [Index in keyof Args]: FlashWrite<Args[Index]> }
) => Promise<FlashRead<Result>>TypedFlash
A place in Flash whose declared type is T.
type TypedFlash<T> = FlashPlace<T> &
FlashConstructor<T> &
(unknown extends T
? unknown
: {
readonly [Key in keyof T as Key extends `$${string}` ? never : Key]: T[Key] extends (
...args: infer Args
) => infer Result
? FlashMethod<Args, Result>
: TypedFlash<T[Key]>;
})FlashConstructor
A class's constructor, from its declared $new.
type FlashConstructor<T> = T extends { $new(...args: infer Args): infer Instance }
? { $new: FlashMethod<Args, Instance> }
: unknownSavedChange
One of those being kept, as the client's setSharedObj is called.
| Field | Type | |
|---|---|---|
name | string | |
value | FlashData |