vn-engine
Version:
A powerful, flexible TypeScript library for creating visual novels and interactive narratives
516 lines (468 loc) • 17.5 kB
TypeScript
import { ChoiceRecord as ChoiceRecord_2 } from '../../../types';
import { createVNEngine } from './VNEngine';
import { GameState as GameState_2 } from '../../../types';
import { ParsedScene as ParsedScene_2 } from '../../../types';
import { SaveData } from './VNEngine';
import { SerializableGameState as SerializableGameState_2 } from '../../../types';
import { SourceLocation as SourceLocation_2 } from '../../../types';
import { TemplateEngineInfo } from './VNEngine';
import { UserAction as UserAction_2 } from '../../../types';
import { VNEngine } from './VNEngine';
import { VNEngineEvents } from './VNEngine';
export declare interface ActionInstruction extends ScriptInstruction {
type: 'action';
actions: UserAction[];
}
export declare class ActionValidationError extends VNEngineError {
invalidAction: UserAction_2;
suggestion: string;
sourceLocation?: SourceLocation_2 | undefined;
constructor(message: string, invalidAction: UserAction_2, suggestion: string, sourceLocation?: SourceLocation_2 | undefined);
}
export declare interface ArrayHelpers {
first<T>(arr: T[], n?: number): T | T[] | undefined;
last<T>(arr: T[], n?: number): T | T[] | undefined;
length(value: any): number;
includes<T>(arr: T[], item: T): boolean;
isEmpty(arr: any): boolean;
filter<T>(arr: T[], predicate: (item: T, index: number) => boolean): T[];
find<T>(arr: T[], predicate: (item: T, index: number) => boolean): T | undefined;
where<T>(arr: T[], properties: Partial<T>): T[];
map<T, U>(arr: T[], iteratee: (item: T, index: number) => U): U[];
pluck<T>(arr: T[], path: string): any[];
join<T>(arr: T[], separator?: string): string;
groupBy<T>(arr: T[], iteratee: string | ((item: T) => any)): Record<string, T[]>;
chunk<T>(arr: T[], size: number): T[][];
unique<T>(arr: T[]): T[];
shuffle<T>(arr: T[]): T[];
slice<T>(arr: T[], start: number, end?: number): T[];
take<T>(arr: T[], count: number): T[];
sample<T>(arr: T[]): T | undefined;
sampleSize<T>(arr: T[], n: number): T[];
flatten<T>(arr: any[]): T[];
reverse<T>(arr: T[]): T[];
concat<T>(...arrays: (T | T[])[]): T[];
compact<T>(arr: (T | null | undefined | false | 0 | '')[]): T[];
without<T>(arr: T[], ...values: T[]): T[];
randomChoice<T>(arr: T[]): T | undefined;
weightedChoice<T>(items: T[], weights: number[]): T | undefined;
cycleNext<T>(arr: T[], currentIndex: number): T;
findByProperty<T>(arr: T[], property: string, value: any): T | undefined;
}
export declare interface AssetHelpers {
hasAsset(assetKey: string, assets: any[]): boolean;
getAsset(assetKey: string, assets: any[]): any | null;
resolveAsset(assetKey: string, assets: any[]): string | null;
getMediaType(filename: string): 'image' | 'audio' | 'video' | 'unknown';
getAssetInfo(assetKey: string, assets: any[]): {
type: string;
size?: number;
name?: string;
} | null;
validateAsset(assetKey: string, assets: any[]): boolean;
assetCount(assets: any[]): number;
formatFileSize(bytes: number): string;
normalizeKey(input: string): string;
}
export declare interface ChoiceOption {
text: string;
condition?: string;
actions?: UserAction[];
goto?: string;
}
export declare interface ChoiceRecord {
scene: string;
instruction: number;
choiceIndex: number;
choiceText: string;
timestamp: number;
}
export declare interface ComparisonHelpers {
eq(a: any, b: any): boolean;
ne(a: any, b: any): boolean;
gt(a: any, b: any): boolean;
gte(a: any, b: any): boolean;
lt(a: any, b: any): boolean;
lte(a: any, b: any): boolean;
and(...args: any[]): boolean;
or(...args: any[]): boolean;
not(value: any): boolean;
contains(collection: any, value: any): boolean;
isEmpty(value: any): boolean;
isString(value: any): boolean;
isNumber(value: any): boolean;
isArray(value: any): boolean;
isObject(value: any): boolean;
isBoolean(value: any): boolean;
compare(a: any, operator: string, b: any): boolean;
between(value: number, min: number, max: number): boolean;
ifx(condition: any, truthyValue: any, falsyValue: any): any;
coalesce(...values: any[]): any;
defaultTo(value: any, defaultValue: any): any;
}
export declare interface ConditionalInstruction extends ScriptInstruction {
type: 'conditional';
condition: string;
then: ScriptInstruction[];
else?: ScriptInstruction[];
}
export { createVNEngine }
export declare interface DialogueInstruction extends ScriptInstruction {
type: 'dialogue';
speaker?: string;
text?: string;
actions?: UserAction[];
choices?: ChoiceOption[];
}
export declare interface GameState {
currentScene: string;
currentInstruction: number;
variables: Map<string, any>;
storyFlags: Set<string>;
choiceHistory: ChoiceRecord[];
}
export declare class GameStateManager {
private state;
constructor(initialState?: Partial<GameState_2>);
setCurrentScene(scene: string): void;
getCurrentScene(): string;
setCurrentInstruction(instruction: number): void;
getCurrentInstruction(): number;
setStoryFlag(flag: string): void;
clearStoryFlag(flag: string): void;
hasStoryFlag(flag: string): boolean;
setVariable(key: string, value: any): void;
getVariable(key: string): any;
addToVariable(key: string, value: number): void;
private getNestedProperty;
private setNestedProperty;
addChoice(record: ChoiceRecord_2): void;
getChoiceHistory(): ChoiceRecord_2[];
playerChose(choiceText: string, inScene?: string): boolean;
getList(listName: string): any[];
setList(listName: string, value: any[]): void;
addToList(listName: string, item: any): void;
addTime(minutes: number): void;
getCurrentTime(): number;
getState(): GameState_2;
serialize(): SerializableGameState_2;
deserialize(data: SerializableGameState_2): void;
setBulkVariables(variables: Record<string, any>): void;
setBulkFlags(flags: string[]): void;
reset(): void;
validateState(): {
valid: boolean;
errors: string[];
};
}
export declare function getAvailableHelpers(): {
handlebarsRequired: string[];
standalone: string[];
description: string;
};
export declare function getNestedValue(obj: any, path: string): any;
export declare const helpers: VNEngineHelpers;
export declare interface JumpInstruction extends ScriptInstruction {
type: 'jump';
target: string;
}
export declare interface MathHelpers {
add(a: number, b: number): number;
subtract(a: number, b: number): number;
multiply(a: number, b: number): number;
divide(a: number, b: number): number;
remainder(a: number, b: number): number;
abs(value: number): number;
min(...values: number[]): number;
max(...values: number[]): number;
round(value: number, precision?: number): number;
ceil(value: number): number;
floor(value: number): number;
random(min: number, max: number): number;
randomInt(min: number, max: number): number;
clamp(value: number, min: number, max: number): number;
sum(values: number[]): number;
average(values: number[]): number;
percentage(value: number, total: number): number;
statCheck(stat: number, difficulty: number): boolean;
rollDice(sides: number, count?: number): number;
lerp(start: number, end: number, factor: number): number;
normalizeValue(value: number, min: number, max: number): number;
formatNumber(value: number, decimals?: number): string;
}
export declare interface ParsedScene {
name: string;
instructions: ScriptInstruction[];
}
export declare type PrimitiveAction = {
type: 'setFlag';
flag: string;
} | {
type: 'clearFlag';
flag: string;
} | {
type: 'setVar';
key: string;
value: any;
} | {
type: 'addVar';
key: string;
value: number;
} | {
type: 'addToList';
list: string;
item: any;
} | {
type: 'addTime';
minutes: number;
};
export declare function registerAllHelpers(handlebars: any): void;
export declare interface RenderableState {
storyFlags: string[];
variables: Record<string, any>;
choiceHistory: ChoiceRecord[];
computed: {
gameTime: string;
hasFlag: (flag: string) => boolean;
getVar: (key: string) => any;
playerChose: (choiceText: string, inScene?: string) => boolean;
};
}
export declare function safeRegisterHelpers(handlebars?: any): {
registered: boolean;
engine: 'handlebars' | 'simple';
message: string;
};
export { SaveData }
export declare class ScriptEngine {
private gameState;
private templateManager;
private scenes;
private currentScene;
private currentInstructionIndex;
private pendingChoices;
constructor(gameState: GameStateManager, templateManager: TemplateManager);
loadScenes(scenes: ParsedScene[]): void;
startScene(sceneName: string, instructionIndex?: number): ScriptResult;
continue(): ScriptResult;
makeChoice(choiceIndex: number): ScriptResult;
private executeCurrentInstruction;
private executeInstruction;
private executeDialogue;
private executeActionInstruction;
private executeConditional;
private executeJump;
private executeActions;
private executeAction;
private renderActionValue;
private executeHelperAction;
private callHelper;
private filterAvailableChoices;
private evaluateCondition;
private renderTemplate;
private createTemplateContext;
private getNestedProperty;
}
export declare interface ScriptInstruction {
type: 'dialogue' | 'action' | 'conditional' | 'jump';
_sourceLocation?: SourceLocation;
}
export declare class ScriptParseError extends VNEngineError {
sourceLocation?: SourceLocation_2 | undefined;
constructor(message: string, sourceLocation?: SourceLocation_2 | undefined);
}
export declare class ScriptParser {
parse(content: string, fileName?: string): ParsedScene_2[];
private parseScene;
private parseInstruction;
}
export declare interface ScriptResult {
type: 'display_dialogue' | 'show_choices' | 'scene_complete' | 'error';
content?: string;
speaker?: string;
choices?: ChoiceOption[];
canContinue?: boolean;
error?: string;
}
export declare interface ScriptUpgradeOptions {
mode?: 'additive' | 'replace';
namespace?: string;
allowOverwrite?: string[];
validateState?: boolean;
dryRun?: boolean;
}
export declare interface SerializableGameState {
currentScene: string;
currentInstruction: number;
variables: [string, any][];
storyFlags: string[];
choiceHistory: ChoiceRecord[];
schemaVersion: string;
saveDate: string;
}
export declare function setNestedValue(obj: any, path: string, value: any): void;
export declare class SimpleTemplateEngine {
private static readonly VARIABLE_REGEX;
private static readonly CONDITION_REGEX;
private static readonly CONDITION_ELSE_REGEX;
render(template: string, context: RenderableState): string;
private processConditionals;
private processVariables;
private evaluateCondition;
private evaluateExpression;
private parseValue;
private compareValues;
private isTruthy;
private formatValue;
getSupportedFeatures(): {
variables: boolean;
conditionals: boolean;
helpers: boolean;
loops: boolean;
partials: boolean;
};
getEngineType(): string;
}
export declare interface SourceLocation {
file: string;
line: number;
scene: string;
}
export declare interface StringHelpers {
uppercase(str: string): string;
lowercase(str: string): string;
capitalize(str: string): string;
capitalizeFirst(str: string): string;
titleCase(str: string): string;
trim(str: string): string;
truncate(str: string, length: number, suffix?: string): string;
ellipsis(str: string, length: number): string;
replace(str: string, search: string, replacement: string): string;
remove(str: string, target: string): string;
reverse(str: string): string;
repeat(str: string, count: number): string;
padStart(str: string, length: number, padString?: string): string;
padEnd(str: string, length: number, padString?: string): string;
center(str: string, length: number): string;
startsWith(str: string, searchString: string): boolean;
endsWith(str: string, searchString: string): boolean;
includes(str: string, searchString: string): boolean;
substring(str: string, start: number, end?: number): string;
words(str: string, count?: number): string[];
wordCount(str: string): number;
slugify(str: string): string;
stripTags(str: string): string;
typewriter(str: string, speed?: number): string;
nameTag(name: string): string;
dialogueFormat(speaker: string, text: string): string;
parseMarkdown(str: string): string;
sanitizeInput(str: string): string;
colorText(str: string, color: string): string;
}
export { TemplateEngineInfo }
export declare class TemplateManager {
private handlebars;
private simpleEngine;
private isHandlebarsAvailable;
private helpersRegistered;
private isTestMode;
private gameStateManager;
constructor();
setGameStateManager(gameStateManager: GameStateManager): void;
initialize(): Promise<void>;
private detectHandlebars;
private setupHelpers;
render(template: string, context: RenderableState): string;
renderStrict(template: string, context: RenderableState): string;
private renderWithHandlebars;
getEngineInfo(): {
type: 'handlebars' | 'simple';
isHandlebarsAvailable: boolean;
helpersRegistered: boolean;
supportedFeatures: {
variables: boolean;
conditionals: boolean;
helpers: boolean;
loops: boolean;
partials: boolean;
};
};
registerHelper(name: string, helper: any): boolean;
getHandlebarsInstance(): any | null;
validateTemplate(template: string): {
valid: boolean;
error?: string;
engine: 'handlebars' | 'simple';
supportedFeatures: string[];
};
supportsFeature(feature: 'variables' | 'conditionals' | 'helpers' | 'loops' | 'partials'): boolean;
isReady(): boolean;
}
export declare class TemplateRenderError extends VNEngineError {
template: string;
originalError?: Error | undefined;
constructor(message: string, template: string, originalError?: Error | undefined);
}
export declare interface UpgradeError {
code: 'SCENE_CONFLICT' | 'INVALID_REFERENCE' | 'STATE_INVALID' | 'PARSE_ERROR' | 'UNAUTHORIZED_OVERWRITE';
message: string;
details: {
conflictingScenes?: string[];
invalidReferences?: string[];
affectedState?: string[];
unauthorizedOverwrites?: string[];
parseErrors?: string[];
};
}
export declare interface UpgradeResult {
success: boolean;
error?: UpgradeError;
addedScenes: string[];
replacedScenes: string[];
totalScenes: number;
warnings: string[];
}
export declare interface UserAction {
type: string;
[key: string]: any;
}
export declare interface ValidationResult {
valid: boolean;
errors: UpgradeError[];
warnings: string[];
wouldAddScenes: string[];
wouldReplaceScenes: string[];
}
export { VNEngine }
export declare class VNEngineError extends Error {
code: string;
context?: any | undefined;
constructor(message: string, code: string, context?: any | undefined);
}
export { VNEngineEvents }
export declare interface VNEngineHelpers {
array: ArrayHelpers;
comparison: ComparisonHelpers;
math: MathHelpers;
string: StringHelpers;
vn: VNHelpers;
asset: AssetHelpers;
}
export declare interface VNHelpers {
hasFlag(flagName: string, context: RenderableState): boolean;
addFlag(flagName: string, context: RenderableState): void;
removeFlag(flagName: string, context: RenderableState): void;
toggleFlag(flagName: string, context: RenderableState): boolean;
getVar(key: string, defaultValue?: any, context?: RenderableState): any;
setVar(key: string, value: any, context: RenderableState): void;
hasVar(key: string, context: RenderableState): boolean;
incrementVar(key: string, amount: number, context: RenderableState): void;
playerChose(choiceText: string, inScene?: string, context?: RenderableState): boolean;
getLastChoice(context: RenderableState): ChoiceRecord | undefined;
choiceCount(context: RenderableState): number;
formatTime(minutes: number): string;
randomBool(probability?: number): boolean;
exportFlags(context: RenderableState): string[];
exportVariables(context: RenderableState): Record<string, any>;
}
export { }