fvtt-types
Version:
TypeScript type definitions for Foundry VTT
675 lines (576 loc) • 23 kB
text/typescript
import type { AnyObject, InexactPartial, FixedInstanceType, EmptyObject, Identity } from "#utils";
import type { RollParseNode } from "./_types.d.mts";
import type DiceTerm from "./terms/dice.d.mts";
import type PoolTerm from "./terms/pool.d.mts";
import type RollTerm from "./terms/term.d.mts";
import type RollResolver from "../applications/dice/roll-resolver.d.mts";
/**
* An interface and API for constructing and evaluating dice rolls.
* The basic structure for a dice roll is a string formula and an object of data against which to parse it.
*
* @template D - the type of data object against which to parse attributes within the formula
*
* @example Attack with advantage!
* ```typescript
* let r = new Roll("2d20kh + @prof + @strMod", {prof: 2, strMod: 4});
*
* // The parsed terms of the roll formula
* console.log(r.terms); // [Die, OperatorTerm, NumericTerm, OperatorTerm, NumericTerm]
*
* // Execute the roll
* await r.evaluate();
*
* // The resulting equation after it was rolled
* console.log(r.result); // 16 + 2 + 4
*
* // The total resulting from the roll
* console.log(r.total); // 22
* ```
*/
declare class Roll<D extends AnyObject = EmptyObject> {
/**
* @param formula - The string formula to parse
* @param data - The data object against which to parse attributes within the formula
* (default: `{}`)
* @param options - (default: `{}`)
*/
constructor(formula: string, data?: D, options?: Roll.Options);
/**
* The original provided data object which substitutes into attributes of the roll formula
*/
data: D;
/**
* Options which modify or describe the Roll
*/
options: Roll.Options;
/**
* The identified terms of the Roll
*/
terms: RollTerm[];
/**
* An array of inner DiceTerms which were evaluated as part of the Roll evaluation
* @defaultValue `[]`
*/
protected _dice: DiceTerm[];
/**
* Store the original cleaned formula for the Roll, prior to any internal evaluation or simplification
*/
protected _formula: string;
/**
* Track whether this Roll instance has been evaluated or not. Once evaluated the Roll is immutable.
* @defaultValue `false`
*/
protected _evaluated: boolean;
/**
* Cache the numeric total generated through evaluation of the Roll.
* @defaultValue `undefined`
*/
protected _total: number | undefined;
/**
* A reference to the Roll at the root of the evaluation tree.
* @defaultValue `undefined`
*/
protected _root: Roll | undefined;
/**
* A reference to the RollResolver app being used to externally resolve this Roll.
*/
protected _resolver: RollResolver; // TODO: Fix this
/** A Proxy environment for safely evaluating a string using only available Math functions */
static MATH_PROXY: Math;
/**
* The HTML template path used to render a complete Roll object to the chat log
* @defaultValue `"templates/dice/roll.html"`
*/
static CHAT_TEMPLATE: string;
/**
* The HTML template used to render an expanded Roll tooltip to the chat log
* @defaultValue `"templates/dice/tooltip.html"`
*/
static TOOLTIP_TEMPLATE: string;
/**
* A mapping of Roll instances to currently-active resolvers.
*/
static RESOLVERS: Map<Roll, RollResolver>; // TODO: Fix this
/**
* Prepare the data structure used for the Roll.
* This is factored out to allow for custom Roll classes to do special data preparation using provided input.
* @param data - Provided roll data
* @returns The prepared data object
*/
protected _prepareData(data: D): D;
/* -------------------------------------------- */
/* Roll Attributes */
/* -------------------------------------------- */
/**
* Return an Array of the individual DiceTerm instances contained within this Roll.
*/
get dice(): DiceTerm[];
/**
* Return a standardized representation for the displayed formula associated with this Roll.
*/
get formula(): string;
/**
* The resulting arithmetic expression after rolls have been evaluated
*/
get result(): string;
/**
* Return the total result of the Roll expression if it has been evaluated.
*/
get total(): number | undefined;
/**
* Return the arbitrary product of evaluating this Roll.
*/
get product(): number | undefined;
/** Whether this Roll contains entirely deterministic terms or whether there is some randomness. */
get isDeterministic(): boolean;
/* -------------------------------------------- */
/* Roll Instance Methods */
/* -------------------------------------------- */
/**
* Alter the Roll expression by adding or multiplying the number of dice which are rolled
* @param multiply - A factor to multiply. Dice are multiplied before any additions.
* @param add - A number of dice to add. Dice are added after multiplication.
* @param multiplyNumeric - Apply multiplication factor to numeric scalar terms
* (default: `false`)
* @returns The altered Roll expression
*/
alter(multiply: number, add: number, { multiplyNumeric }?: { multiplyNumeric: boolean }): this;
/**
* Clone the Roll instance, returning a new Roll instance that has not yet been evaluated.
*/
clone(): this;
/**
* Execute the Roll, replacing dice and evaluating the total result
* @param options - Options which inform how the Roll is evaluated
* (default: `{}`)
* @returns The evaluated Roll instance
*
* @example Evaluate a Roll expression
* ```typescript
* let r = new Roll("2d6 + 4 + 1d4");
* await r.evaluate();
* console.log(r.result); // 5 + 4 + 2
* console.log(r.total); // 11
* ```
*/
evaluate({
minimize,
maximize,
allowStrings,
allowInteractive,
...options
}?: Roll.Options): Promise<Roll.Evaluated<this>>;
/**
* Execute the Roll synchronously, replacing dice and evaluating the total result.
* @param options - Options which inform how the Roll is evaluated
* (default: `{}`)
*
* @returns The evaluated Roll instance.
*/
evaluateSync({ minimize, maximize, allowStrings, strict }?: Roll.Options): Roll.Evaluated<this>;
/**
* Evaluate the roll asynchronously.
* A temporary helper method used to migrate behavior from 0.7.x (sync by default) to 0.9.x (async by default).
* @param options - Options which inform how evaluation is performed
* @internal
*/
protected _evaluate(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
/**
* Evaluate an AST asynchronously.
* @param node - The root node or term.
* @param options - Options which inform how evaluation is performed
* (default: `{}`)
*/
protected _evaluateASTAsync(node: RollParseNode | RollTerm, options?: Roll.Options): Promise<string | number>;
/**
* Evaluate the roll synchronously.
* @param options - Options which inform how evaluation is performed
* (default: `{}`)
*/
protected _evaluateSync(options?: Roll.Options): Roll.Evaluated<this>;
/**
* Evaluate an AST synchronously.
* @param node - The root node or term.
* @param options - Options which inform how evaluation is performed
* (default: `{}`)
*/
protected _evaluateASTSync(node: RollParseNode | RollTerm, options?: Roll.Options): string | number;
/**
* Safely evaluate the final total result for the Roll using its component terms.
* @returns The evaluated total
*/
protected _evaluateTotal(): number;
/**
* Alias for evaluate.
* @see {@link Roll.evaluate | `Roll#evaluate`}
* @param options - Options passed to {@link Roll.evaluate | `Roll#evaluate`}.
*/
roll(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
/**
* Create a new Roll object using the original provided formula and data.
* Each roll is immutable, so this method returns a new Roll instance using the same data.
* @param options - Evaluation options passed to {@link Roll.evaluate | `Roll#evaluate`}
* @returns A new Roll object, rolled using the same formula and data
*/
reroll(options?: Roll.Options): Promise<Roll.Evaluated<this>>;
/**
* Recompile the formula string that represents this Roll instance from its component terms.
* @returns The re-compiled formula
*/
resetFormula(): string;
/**
* Propagate flavor text across all terms that do not have any.
* @param flavor -The flavor text.
*/
propagateFlavor(flavor: string): void;
/** @override */
toString(): string;
/* -------------------------------------------- */
/* Static Class Methods */
/* -------------------------------------------- */
/**
* A factory method which constructs a Roll instance using the default configured Roll class.
* @template D - the type of data object against which to parse attributes within the formula
* @param formula - The formula used to create the Roll instance
* @param data - The data object which provides component data for the formula
* @param options - Additional options which modify or describe this Roll
* @returns The constructed Roll instance
*/
static create<D extends AnyObject = EmptyObject>(
formula: string,
data?: D,
options?: Roll.Options,
): typeof CONFIG.Dice.rolls extends [infer T] ? T : Roll<D>;
/**
* Get the default configured Roll class.
*/
static get defaultImplementation(): typeof Roll;
/**
* Retrieve the appropriate resolver implementation based on the user's configuration.
*/
static get resolverImplementation(): typeof RollResolver;
/**
* Transform an array of RollTerm objects into a cleaned string formula representation.
* @param terms - An array of terms to represent as a formula
* @returns The string representation of the formula
*/
static getFormula(terms: RollTerm[]): string;
/**
* A sandbox-safe evaluation function to execute user-input code with access to scoped Math methods.
* @param expression - The input string expression
* @returns The numeric evaluated result
*/
static safeEval(expression: string): number;
/**
* After parenthetical and arithmetic terms have been resolved, we need to simplify the remaining expression.
* Any remaining string terms need to be combined with adjacent non-operators in order to construct parsable terms.
* @param terms - An array of terms which is eligible for simplification
* @returns An array of simplified terms
*/
static simplifyTerms(terms: RollTerm[]): RollTerm[];
/**
* Simulate a roll and evaluate the distribution of returned results
* @param formula - The Roll expression to simulate
* @param n - The number of simulations
* (default: `10000`)
* @returns The rolled totals
*/
static simulate(formula: string, n?: number): Promise<number[]>;
/**
* Register an externally-fulfilled result with an active RollResolver.
* @param method - The fulfillment method.
* @param denomination - The die denomination being fulfilled.
* @param result - The obtained result.
*/
static registerResult(method: string, denomination: string, result: number): boolean | void;
/* -------------------------------------------- */
/* Roll Formula Parsing */
/* -------------------------------------------- */
/**
* Parse a formula expression using the compiled peggy grammar.
*
* @param formula - The original string expression to parse
* @param data - A data object used to substitute for attributes in the formula
* @returns A parsed array of RollTerm instances
*/
static parse(formula: string, data: Record<string, unknown>): RollTerm[];
/**
* Instantiate the nodes in an AST sub-tree into RollTerm instances.
* @param ast - The root of the AST sub-tree.
*/
static instantiateAST(ast: RollParseNode): RollTerm[];
/**
* Replace referenced data attributes in the roll formula with values from the provided data.
* Data references in the formula use the \@attr syntax and would reference the corresponding attr key.
*
* @param formula - The original formula within which to replace
* @param data - The data object which provides replacements
* @param options - Options which modify formula replacement
*/
static replaceFormulaData<D extends Record<string, unknown>>(
formula: string,
data: D,
options?: {
/**
* The value that should be assigned to any unmatched keys.
* If null, the unmatched key is left as-is.
*/
missing?: string;
/**
* Display a warning notification when encountering an un-matched key.
* (default: `false`)
*/
warn?: boolean;
},
): string;
/**
* Validate that a provided roll formula can represent a valid
* @param formula - A candidate formula to validate
* @returns Is the provided input a valid dice formula?
*/
static validate(formula: string): boolean;
/**
* Determine which of the given terms require external fulfillment.
* @param terms - The terms.
*/
static identifyFulfillableTerms(terms: RollTerm[]): DiceTerm[];
/**
* Classify a remaining string term into a recognized RollTerm class
* @param term - A remaining un-classified string
* @param options - Options which customize classification
* (default: `{}`)
* @returns A classified RollTerm instance
*/
static _classifyStringTerm(
term: string,
options?: Roll.ClassifyStringTermOptions, // not: null (destructured)
): RollTerm;
/* -------------------------------------------- */
/* Chat Messages */
/* -------------------------------------------- */
/**
* Render the tooltip HTML for a Roll instance
* @returns The rendered HTML tooltip as a string
*/
getTooltip(): Promise<string>;
/**
* Render a Roll instance to HTML
* @param options - Options which affect how the Roll is rendered
* (default: `{}`)
* @returns The rendered HTML template as a string
*/
render(
options?: InexactPartial<{
/**
* Flavor text to include
* @defaultValue `undefined`
*/
flavor: string;
/**
* A custom HTML template path
* @defaultValue `this.constructor.CHAT_TEMPLATE`
*/
template: string;
/**
* Is the Roll displayed privately?
* @defaultValue `false`
*/
isPrivate: boolean;
}>,
): Promise<string>;
/**
* Transform a Roll instance into a ChatMessage, displaying the roll result.
* This function can either create the ChatMessage directly, or return the data object that will be used to create.
*
* @param messageData - The data object to use when creating the message
* (default: `{}`)
* @param options - Additional options which modify the created message.
* (default: `{}`)
* @param rollMode - The template roll mode to use for the message from CONFIG.Dice.rollModes
* @param create - Whether to automatically create the chat message, or only return the
* prepared chatData object.
* (default: `true`)
* @returns A promise which resolves to the created ChatMessage entity, if create is true
* or the Object of prepared chatData otherwise.
*/
// options: not null (destructured)
toMessage<const Create extends boolean | null | undefined = undefined>(
messageData?: Roll.MessageData | null,
options?: Roll.ToMessageOptions<Create>,
): Promise<Roll.ToMessageReturn<Create>>;
/* -------------------------------------------- */
/* Interface Helpers */
/* -------------------------------------------- */
/**
* Expand an inline roll element to display its contained dice result as a tooltip.
* @param a - The inline-roll button
*/
static expandInlineResult(a: HTMLAnchorElement): Promise<void>;
/**
* Collapse an expanded inline roll to conceal its tooltip.
* @param a - The inline-roll button
*/
static collapseInlineResult(a: HTMLAnchorElement): void;
/**
* Construct an inline roll link for this Roll.
* @param object - Additional options to configure how the link is constructed.
*/
toAnchor(options?: InexactPartial<Roll.ToAnchorOptions>): HTMLAnchorElement;
/**
* Represent the data of the Roll as an object suitable for JSON serialization.
* @returns Structured data which can be serialized into JSON
*/
toJSON(): {
class: string;
options: Roll.Options;
dice: DiceTerm[];
formula: string;
terms: RollTerm[];
total: number | undefined;
evaluated: boolean;
};
/**
* Recreate a Roll instance using a provided data object
* @param data - Unpacked data representing the Roll
* @returns A reconstructed Roll instance
*/
static fromData<T extends Roll.Internal.AnyConstructor>(this: T, data: Roll.Data): FixedInstanceType<T>;
/**
* Recreate a Roll instance using a provided JSON string
* @param json - Serialized JSON data representing the Roll
* @returns A reconstructed Roll instance
*/
static fromJSON<T extends Roll.Internal.AnyConstructor>(this: T, json: string): FixedInstanceType<T>;
/**
* Manually construct a Roll object by providing an explicit set of input terms
* @param terms -The array of terms to use as the basis for the Roll
* @param options - Additional options passed to the Roll constructor
* @returns The constructed Roll instance
*
* @example Construct a Roll instance from an array of component terms
* ```typescript
* const t1 = new Die({number: 4, faces: 8};
* const plus = new OperatorTerm({operator: "+"});
* const t2 = new NumericTerm({number: 8});
* const roll = Roll.fromTerms([t1, plus, t2]);
* roll.formula; // 4d8 + 8
* ```
*/
static fromTerms<T extends Roll.Internal.AnyConstructor>(
this: T,
terms: RollTerm[],
options?: Roll.Options,
): FixedInstanceType<T>;
}
declare namespace Roll {
/** @deprecated There should only be a single implementation of this class in use at one time, use {@linkcode Implementation} instead */
type Any = Internal.Any;
/** @deprecated There should only be a single implementation of this class in use at one time, use {@linkcode ImplementationClass} instead */
type AnyConstructor = Internal.AnyConstructor;
namespace Internal {
interface Any extends AnyRoll {}
interface AnyConstructor extends Identity<typeof AnyRoll> {}
}
/** @deprecated Use {@linkcode foundry.dice.Roll.Mode} instead */
type ConfiguredRollModes = Mode;
type Mode = keyof CONFIG.Dice.RollModes;
// TODO: Make this actually configurable
interface ImplementationClass extends Identity<CONFIG["Dice"]["rolls"][0]> {}
interface Implementation extends FixedInstanceType<ImplementationClass> {}
interface _Options extends RollTerm.EvaluationOptions {
/**
* If false, force the use of non-interactive rolls and do not prompt the user to make manual rolls.
* @defaultValue `true`
*/
allowInteractive?: boolean | undefined;
/**
* Throw an Error if the Roll contains non-deterministic terms that cannot be evaluated synchronously.
* If this is set to false, non-deterministic terms will be ignored.
*/
strict?: boolean | undefined;
}
interface Options extends InexactPartial<_Options> {}
interface SplitGroupOptions {
openRegexp: RegExp | string;
closeRegexp: RegExp | string;
openSymbol: string;
closeSymbol: string;
onClose: (group: { open: string; terms: string[]; close: string }) => string[];
}
/** Additional options to configure how the link is constructed. */
interface ToAnchorOptions {
/** A custom label for the total. */
label: string;
/** Attributes to set on the link. (default: `{}`) */
attrs: Record<string, string>;
/** Custom data attributes to set on the link. (default: `{}`) */
dataset: Record<string, string | undefined>;
/**
* Additional Classes to add to the link. (default: `[]`)
* The classes `inline-roll` and `inline-result` are added by default.
*/
classes: string[];
/** A font-awesome icon class to use as the icon instead of a d20. */
icon: string;
}
interface Data {
formula: string;
results: Array<number | string>;
terms: Array<PoolTerm.TermData | DiceTerm.Data>;
total: number | null;
}
type _ClassifyStringTermOptions = InexactPartial<{
/**
* Allow intermediate terms
* @defaultValue `true`
*/
intermediate: boolean | null;
/** The prior classified term */
prior: RollTerm | string | null;
/** The next term to classify */
next: RollTerm | string | null;
}>;
interface ClassifyStringTermOptions extends _ClassifyStringTermOptions {}
/** @internal */
// TODO(LukeAbby): When shims are added then `"user"` should also be added here #3065. Specifically `user` should be added as partial.
//
// This is `IntentionalPartial` because Foundry merges in defaults with `mergeObject`.
interface _MessageData extends InexactPartial<ChatMessage.CreateData> {
/**
* The HTML content of this chat message
* @defaultValue `String(this.total)`
*/
content?: ChatMessage.CreateData["content"] | undefined;
/**
* The URL of an audio file which plays when this message is received
* @defaultValue `CONFIG.sounds.dice`
*/
sound?: ChatMessage.CreateData["sound"] | undefined;
/**
* @deprecated In `Roll.MessageData`, Foundry always overrides `rolls` to `[this]`.
* This makes it useless to set. Do not use.
*/
rolls?: ChatMessage.CreateData["rolls"] | undefined;
}
interface MessageData extends _MessageData {}
type Evaluated<T extends Roll<any>> = T & { _evaluated: true; _total: number; get total(): number };
interface ToMessageOptions<Create extends boolean | null | undefined> {
/**
* The template roll mode to use for the message from CONFIG.Dice.rollModes
* @remarks "roll" equivalent to explicit undefined
*/
rollMode?: ChatMessage.PassableRollMode | null | undefined;
/**
* Whether to automatically create the chat message, or only return the prepared chatData object.
* @defaultValue `true`
*/
create?: Create;
}
type ToMessageReturn<Create extends boolean | null | undefined> =
| (Create extends true | undefined ? ChatMessage.Implementation | undefined : never)
| (Create extends false | null ? ChatMessage.CreateData : never);
}
declare abstract class AnyRoll extends Roll<any> {
constructor(...args: never);
}
export default Roll;