@league-of-foundry-developers/foundry-vtt-types
Version:
TypeScript type definitions for Foundry VTT
757 lines (640 loc) • 24.4 kB
text/typescript
import type { Socket } from "socket.io-client";
import type {
ConfiguredModule,
GetKey,
EmptyObject,
ValueOf,
FixedInstanceType,
InitializationHook,
InitializedOn,
} from "#utils";
import type BasePackage from "../common/packages/base-package.d.mts";
import type { Document } from "../common/abstract/module.d.mts";
// Must be called with all hooks in a union.
// Do not increase the complexity of this type. If you do Game related types may get complex enough to complain about not being statically known.
type SimpleInitializedOn<
InitializedTo,
MustRun extends InitializationHook,
RunHooks extends InitializationHook,
BeforeInitialization = undefined,
> = Extract<RunHooks, MustRun> extends never ? BeforeInitialization : InitializedTo;
/**
* @privateRemarks In v12 many of these properties were mistakenly stripped of their readonly quality;
* This is preserved in the types despite them being technically writable.
* See https://github.com/foundryvtt/foundryvtt/issues/11813
*/
declare class InternalGame<RunEvents extends InitializationHook> {
/**
* @param view - The named view which is active for this game instance.
* @param data - An object of all the World data vended by the server when the client first connects
* @param sessionId - The ID of the currently active client session retrieved from the browser cookie
* @param socket - The open web-socket which should be used to transact game-state data
*/
constructor(view: Game["view"], data: Game.Data, sessionId: Game["sessionId"], socket: Game["socket"]);
/**
* The named view which is currently active.
* @remarks The full type includes `"join"|"setup"|"players"|"license"` but these views do not run package code.
*/
readonly view: Game.View;
/**
* The object of world data passed from the server
*/
readonly data: Game.Data;
/**
* The client session id which is currently active.
*/
readonly sessionId: string;
/**
* A reference to the open Socket.io connection
*/
readonly socket: io.Socket;
/**
* The id of the active World user, if any
*/
readonly userId: string | null;
/**
* The game World which is currently active.
*/
readonly world: World;
/**
* The System which is used to power this game World.
*/
readonly system: System;
/**
* A Map of active Modules which are currently eligible to be enabled in this World.
* The subset of Modules which are designated as active are currently enabled.
*/
readonly modules: Game.ModuleCollection;
/**
* A mapping of CompendiumCollection instances, one per Compendium pack.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
readonly packs: SimpleInitializedOn<CompendiumPacks, "setup", RunEvents>;
/**
* A registry of document sub-types and their respective data models.
*/
get model(): Game.Data["model"];
/**
* @deprecated since v12, will be removed in v14
* @remarks "Game#template is deprecated and will be removed in Version 14. Use cases for Game#template should be refactored to instead use System#documentTypes or Game#model"
*/
get template(): Game.Data["template"];
/**
* A registry of document types supported by the active world.
*/
get documentTypes(): {
[K in Document.Type]: Game.Model.TypeNames<K>[];
};
/**
* The global document index.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
readonly documentIndex: SimpleInitializedOn<DocumentIndex, "setup", RunEvents>;
/**
* The UUID redirects tree.
* @remarks Initialized just before the `"ready"` hook event is called.
*/
readonly compendiumUUIDRedirects: foundry.utils.StringTree<string[]>;
/**
* A mapping of WorldCollection instances, one per primary Document type.
* @remarks Initialized just before the `"setup"` hook event is called.
*/
readonly collections: SimpleInitializedOn<
foundry.utils.Collection<WorldCollection<Document.AnyConstructor, string>>,
"setup",
RunEvents
>;
/**
* The collection of Actor documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly actors: SimpleInitializedOn<ConfiguredCollectionClassForName<"Actor">, "setup", RunEvents>;
/**
* The collection of Cards documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly cards: SimpleInitializedOn<ConfiguredCollectionClassForName<"Cards">, "setup", RunEvents>;
/**
* The collection of Combat documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly combats: SimpleInitializedOn<ConfiguredCollectionClassForName<"Combat">, "setup", RunEvents>;
/**
* The collection of Folder documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly folders: SimpleInitializedOn<ConfiguredCollectionClassForName<"Folder">, "setup", RunEvents>;
/**
* The collection of Item documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly items: SimpleInitializedOn<ConfiguredCollectionClassForName<"Item">, "setup", RunEvents>;
/**
* The collection of JournalEntry documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly journal: SimpleInitializedOn<ConfiguredCollectionClassForName<"JournalEntry">, "setup", RunEvents>;
/**
* The collection of Macro documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly macros: SimpleInitializedOn<ConfiguredCollectionClassForName<"Macro">, "setup", RunEvents>;
/**
* The collection of ChatMessage documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly messages: SimpleInitializedOn<ConfiguredCollectionClassForName<"ChatMessage">, "setup", RunEvents>;
/**
* The collection of Playlist documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly playlists: SimpleInitializedOn<ConfiguredCollectionClassForName<"Playlist">, "setup", RunEvents>;
/**
* The collection of Scene documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly scenes: SimpleInitializedOn<ConfiguredCollectionClassForName<"Scene">, "setup", RunEvents>;
/**
* The collection of RollTable documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly tables: SimpleInitializedOn<ConfiguredCollectionClassForName<"RollTable">, "setup", RunEvents>;
/**
* The collection of User documents which exists in the World.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly users: SimpleInitializedOn<ConfiguredCollectionClassForName<"User">, "setup", RunEvents>;
/**
* The Release data for this version of Foundry
*/
readonly release: foundry.config.ReleaseData;
/**
* Returns the current version of the Release, usable for comparisons using isNewerVersion
*/
get version(): string;
/**
* Whether the Game is running in debug mode
* @defaultValue `false`
*/
readonly debug: boolean;
/**
* A flag for whether texture assets for the game canvas are currently loading
* @defaultValue `false`
*/
readonly loading: boolean;
/**
* The user role permissions setting
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly permissions: SimpleInitializedOn<Game.Permissions, "setup", RunEvents>;
/**
* A flag for whether the Game has successfully reached the "ready" hook
* @defaultValue `false`
*/
readonly ready: SimpleInitializedOn<true, "ready", RunEvents, false>;
/**
* The singleton compendium art manager.
* @remarks Initialized just before the `"setup"` hook event.
*/
readonly compendiumArt: foundry.helpers.CompendiumArt;
/**
* A singleton instance of the Audio Helper class
*/
readonly audio: foundry.audio.AudioHelper;
/**
* A singleton reference to the Canvas object which may be used.
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly canvas: SimpleInitializedOn<Canvas, "ready", RunEvents>;
/**
* The singleton Clipboard Helper.
*/
readonly clipboard: ClipboardHelper;
/**
* Localization support
* @remarks Initialized just before the `"i18nInit"` hook event.
*/
readonly i18n: SimpleInitializedOn<Localization, "i18nInit", RunEvents>;
/**
* The singleton instance of the ClientIssues manager.
*/
readonly issues: ClientIssues;
/**
* The Gamepad Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly gamepad: SimpleInitializedOn<GamepadManager, "ready", RunEvents>;
/**
* The Keyboard Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly keyboard: SimpleInitializedOn<KeyboardManager, "ready", RunEvents>;
/**
* Client keybindings which are used to configure application behavior
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly keybindings: SimpleInitializedOn<ClientKeybindings, "ready", RunEvents>;
/**
* The Mouse Manager
* @remarks Initialized just before the `"ready"` hook event.
*/
readonly mouse: SimpleInitializedOn<MouseManager, "ready", RunEvents>;
/**
* The New User Experience manager.
* @remarks Initialized just after the `"ready"` hook event.
*/
readonly nue: NewUserExperience;
/**
* Client settings which are used to configure application behavior
* @remarks Settings are registered between `"init"` and `"i18nInit"` hook events.
*/
readonly settings: ClientSettings;
/**
* A singleton GameTime instance which manages the progression of time within the game world.
*/
readonly time: GameTime;
/**
* A singleton instance of the TooltipManager class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly tooltip: SimpleInitializedOn<TooltipManager, "setup", RunEvents>;
/**
* A singleton instance of the Tour collection class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly tours: SimpleInitializedOn<Tours, "setup", RunEvents>;
/**
* A singleton instance of the Video Helper class
* @remarks Initialized just before the `"setup"` hook events is called.
*/
readonly video: SimpleInitializedOn<VideoHelper, "setup", RunEvents>;
/**
* A singleton web Worker manager.
*/
readonly workers: WorkerManager;
/**
* Fetch World data and return a Game instance
* @param view - The named view being created
* @param sessionId - The current sessionId of the connecting client
* @returns A Promise which resolves to the created Game instance
*/
static create(view: string, sessionId: string | null): Promise<Game>;
/**
* Establish a live connection to the game server through the socket.io URL
* @param sessionId - The client session ID with which to establish the connection
* @returns A promise which resolves to the connected socket, if successful
*/
static connect(sessionId: string): Promise<io.Socket>;
/**
* Retrieve the cookies which are attached to the client session
* @returns The session cookies
*/
static getCookies(): Record<string, string>;
/**
* Request World data from server and return it
* @param socket - The active socket connection
* @param view - The view for which data is being requested
*/
static getData(socket: Socket, view: string): Promise<unknown>;
/**
* Request World data from server and return it
*/
static getWorldData(socket: io.Socket): Promise<Game.Data>;
/**
* Get the current World status upon initial connection.
*/
static getWorldStatus(socket: io.Socket): Promise<boolean>;
/**
* Configure package data that is currently enabled for this world
*/
setupPackages(data: Game.Data): void;
// Following three fields are initialized in setupPackages
/**
* Return the named scopes which can exist for packages.
* Scopes are returned in the prioritization order that their content is loaded.
* @returns An array of string package scopes
*/
getPackageScopes(): string[];
/**
* Initialize the Game for the current window location
*/
initialize(): void;
/**
* Shut down the currently active Game. Requires GameMaster user permission.
*/
shutDown(): Promise<void>;
/**
* Fully set up the game state, initializing Documents, UI applications, and the Canvas
*/
setupGame(): Promise<void>;
/**
* Initialize configuration state.
*/
initializeConfig(): void;
/**
* Initialize game state data by creating WorldCollection instances for every primary Document type
*/
initializeDocuments(): void;
/**
* Initialize the Compendium packs which are present within this Game
* Create a Collection which maps each Compendium pack using it's collection ID
*/
initializePacks(): Promise<this["packs"]>;
/**
* Initialize the WebRTC implementation
*/
initializeRTC(): Promise<boolean>;
/**
* @remarks Initialized just before the `"ready"` hook event.
*/
webrtc: SimpleInitializedOn<AVMaster, "ready", RunEvents>;
/**
* Initialize core UI elements
*/
initializeUI(): void;
/**
* Initialize the game Canvas
*/
initializeCanvas(): Promise<void>;
/**
* Initialize Keyboard controls
*/
initializeKeyboard(): void;
/**
* Initialize Mouse controls
*/
initializeMouse(): void;
/**
* Initialize Gamepad controls
*/
initializeGamepads(): void;
/**
* Register core game settings
*/
registerSettings(): void;
/**
* Register core Tours
*/
registerTours(): Promise<void>;
/**
* Is the current session user authenticated as an application administrator?
*/
get isAdmin(): boolean;
/**
* The currently connected User entity, or null if Users is not yet initialized
*
* @remarks Initialized just before the `"setup"` hook event.
*/
get user(): SimpleInitializedOn<User.Stored, "setup", RunEvents, null>;
/**
* A convenience accessor for the currently viewed Combat encounter
*/
get combat(): CombatEncounters["viewed"];
/**
* A state variable which tracks whether the game session is currently paused
*/
get paused(): boolean;
/**
* A convenient reference to the currently active canvas tool
*/
get activeTool(): string;
/**
* Toggle the pause state of the game
* Trigger the `pauseGame` Hook when the paused state changes
* @param pause - The desired pause state; true for paused, false for un-paused
* @param push - Push the pause state change to other connected clients? Requires an GM user.
* (default: `false`)
* @returns The new paused state
*/
togglePause(pause: boolean, push?: boolean): void;
/**
* Open Character sheet for current token or controlled actor
* @returns The ActorSheet which was toggled, or null if the User has no character
*/
toggleCharacterSheet(): ActorSheet | null;
/**
* Log out of the game session by returning to the Join screen
*/
logOut(): void;
/**
* Scale the base font size according to the user's settings.
* @param index - Optionally supply a font size index to use, otherwise use the user's setting.
* Available font sizes, starting at index 1, are: 8, 10, 12, 14, 16, 18, 20, 24, 28, and 32.
*/
scaleFonts(index?: number): void;
/**
* Activate Socket event listeners which are used to transact game state data with the server
*/
activateSocketListeners(): void;
/**
* Activate Event Listeners which apply to every Game View
*/
activateListeners(): void;
/**
* Support mousewheel control for range type input elements
* @param event - A Mouse Wheel scroll event
*/
protected static _handleMouseWheelInputChange(event: WheelEvent): void;
/**
* On left mouse clicks, check if the element is contained in a valid hyperlink and open it in a new tab.
*/
protected _onClickHyperlink(event: MouseEvent): void;
/**
* Prevent starting a drag and drop workflow on elements within the document unless the element has the draggable
* attribute explicitly defined or overrides the dragstart handler.
* @param event - The initiating drag start event
*/
protected _onPreventDragstart(event: DragEvent): boolean;
/**
* Disallow dragging of external content onto anything but a file input element
* @param event - The requested drag event
*/
protected _onPreventDragover(event: DragEvent): void;
/**
* Disallow dropping of external content onto anything but a file input element
* @param event - The requested drag event
*/
protected _onPreventDrop(event: DragEvent): void;
/**
* On a left-click event, remove any currently displayed inline roll tooltip
* @param event - The mousedown pointer event
*/
protected _onPointerDown(event: PointerEvent): void;
/**
* Fallback handling for mouse-up events which aren't handled further upstream.
* @param event - The mouseup pointer event
*/
protected _onPointerUp(event: PointerEvent): void;
/**
* Handle resizing of the game window by adjusting the canvas and repositioning active interface applications.
* @param event - The window resize event which has occurred
* @internal
*/
protected _onWindowResize(event: UIEvent): void;
/**
* Handle window unload operations to clean up any data which may be pending a final save
* @param event - The window unload event which is about to occur
*/
protected _onWindowBeforeUnload(event: Event): Promise<void>;
/**
* Handle cases where the browser window loses focus to reset detection of currently pressed keys
* @param event - The originating window.blur event
*/
protected _onWindowBlur(event: FocusEvent): void;
protected _onWindowPopState(event: PopStateEvent): void;
/**
* Initialize elements required for the current view
*/
protected _initializeView(): Promise<void>;
/**
* Initialization steps for the primary Game view
*/
protected _initializeGameView(): Promise<void>;
/**
* Initialization steps for the Stream helper view
*/
protected _initializeStreamView(): Promise<void>;
}
type _InitGame = Game & InternalGame<"init">;
type _I18nInitGame = Game & InternalGame<"init" | "i18nInit">;
type _SetupGame = Game & InternalGame<"init" | "i18nInit" | "setup">;
type _ReadyGame = Game & InternalGame<"init" | "i18nInit" | "setup" | "ready">;
declare global {
/**
* The core Game instance which encapsulates the data, settings, and states relevant for managing the game experience.
* The singleton instance of the Game class is available as the global variable game.
*/
class Game extends InternalGame<any> {}
// These helper types show `Game` at different points in its life cycle.
// They're merged with `Game` to preserve the invariant `XYZGame instanceof Game`.
// They're interfaces for easier user declaration merges as well as to give intellisense better names to use as the expanded type is intimidating.
interface InitGame extends _InitGame {}
interface I18nInitGame extends _I18nInitGame {}
interface SetupGame extends _SetupGame {}
interface ReadyGame extends _ReadyGame {}
/** @deprecated {@link Hooks.HotReloadData | `HotReloadData`} */
type HotReloadData = Hooks.HotReloadData;
namespace Game {
interface ModuleCollection extends Collection<Module> {
/**
* Gets the module requested for by ID
* @see {@link ModuleConfig | `ModuleConfig`} to add custom properties to modules like APIs.
* @see {@link RequiredModules | `RequiredModules`} to remove `undefined` from the return type for a given module
* @param id - The module ID to look up
*/
get<T extends string>(id: T): Module & ConfiguredModule<T>;
}
namespace Model {
/**
* Get the configured core and system type names for a specific document type.
*
* Because of module subtypes, extra types of the form `${moduleName}.${subtype}` are
* possible when `hasTypeData` is true.
*
* @typeParam DocumentName - the type of the Document this data is for
*/
type TypeNames<DocumentType extends Document.Type> = Document.SubTypesOf<DocumentType>;
}
type _Model = {
[DocumentType in Document.Type]: {
// The `& string` is helpful even though there should never be any numeric/symbol keys.
// This is because when `keyof Config<...>` is deferred then TypeScript does a bunch of proofs under the assumption that `SystemTypeNames` could be a `string | number` until proven otherwise.
// This causes issues where there shouldn't be, for example it has been observed to obstruct the resolution of the `Actor` class.
[SubType in Model.TypeNames<DocumentType>]: GetKey<GetKey<SourceConfig, DocumentType>, SubType, EmptyObject>;
};
};
interface Model extends _Model {}
type Data = {
activeUsers: string[];
addresses: {
local: string;
remote?: string | undefined;
remoteIsAccessible: boolean | null;
};
coreUpdate: {
channel: string | null;
couldReachWebsite: boolean;
hasUpdate: boolean;
slowResponse: boolean;
version: string | null;
willDisableModules: boolean;
};
demoMode: boolean;
files: {
s3?: {
endpoint: {
protocol: string;
host: string;
port: number;
hostname: string;
pathname: string;
path: string;
href: string;
};
buckets: string[];
} | null;
storages: ("public" | "data" | "s3")[];
};
modules: Module["_source"][];
options: {
language: string;
port: number;
routePrefix: string | null;
updateChannel: string;
};
packageWarnings: Record<string, unknown>;
packs: Array<
PackageCompendiumData & {
/** @deprecated since v11 */
private?: boolean;
system?: string | undefined;
type: foundry.CONST.COMPENDIUM_DOCUMENT_TYPES;
packageName: BasePackage["_source"]["id"];
packageType: BasePackage["type"];
id: string;
}
>;
paused: boolean;
release: foundry.config.ReleaseData["_source"];
system: System["_source"];
systemUpdate: {
hasUpdate: boolean;
version: string;
};
// TODO: I think this is only for configurable types
template: Record<Document.Type, DocumentTemplate> | null;
// TODO: This is also inheriting the configured types,
// but is only filled in if there's `template.json`
model: Model;
userId: string;
world: World["_source"];
} & {
[DocumentType in // eslint-disable-next-line @typescript-eslint/no-deprecated
| foundry.CONST.DOCUMENT_TYPES
| "Setting" as Document.ImplementationClassFor<DocumentType>["metadata"]["collection"]]?: FixedInstanceType<
Document.ImplementationClassFor<DocumentType>
>["_source"][];
};
type Permissions = {
[Key in keyof typeof foundry.CONST.USER_PERMISSIONS]: foundry.CONST.USER_ROLES[];
};
type View = ValueOf<typeof foundry.CONST.GAME_VIEWS>;
}
/**
* @defaultValue `undefined`
* Initialized just before the `"init"` hook event.
*/
let canvas: InitializedOn<Canvas, "init">;
/**
* @defaultValue `undefined`
* Initialized just before the `"ready"` hook event.
*/
let keyboard: InitializedOn<KeyboardManager, "ready">;
}
type ConfiguredCollectionClassForName<Name extends foundry.CONST.WORLD_DOCUMENT_TYPES> = FixedInstanceType<
CONFIG[Name]["collection"]
>;
interface DocumentTemplate {
htmlFields: string[];
types: string[];
}