@casual-simulation/aux-runtime
Version:
Runtime for AUX projects
657 lines • 23.3 kB
TypeScript
import type { Bot, BotTags, RuntimeBot } from '@casual-simulation/aux-common/bots';
import type { RuntimeBotFactory, RuntimeBotsState, RuntimeBatcher, RuntimeInterpreterGeneratorProcessor } from './RuntimeBot';
import type { AuxVersion } from './AuxVersion';
import type { AuxDevice } from './AuxDevice';
import type { ScriptError } from './AuxResults';
import { RanOutOfEnergyError } from './AuxResults';
import './PerformanceNowPolyfill';
import type { SubscriptionLike } from 'rxjs';
import { ReplaySubject } from 'rxjs';
import type { InterpreterContinuation, InterpreterStop } from '@casual-simulation/js-interpreter';
import type { RuntimeActions } from './RuntimeEvents';
import type seedrandom from 'seedrandom';
/**
* The interval between animation frames in miliseconds when using setInterval().
*/
export declare const SET_INTERVAL_ANIMATION_FRAME_TIME: number;
/**
* A symbol that can be specified on objects to influence how they are stringified
* when printed for debug/mock/error purposes.
*/
export declare const DEBUG_STRING: unique symbol;
/**
* Holds global values that need to be accessible from the runtime.
*/
export interface AuxGlobalContext {
/**
* The ordered list of script bots.
*/
bots: RuntimeBot[];
/**
* The state that the runtime bots occupy.
*/
state: RuntimeBotsState;
/**
* The list of actions that are currently queued in this context.
*/
actions: RuntimeActions[];
/**
* The list of errors that are currently queued in this context.
*/
errors: ScriptError[];
/**
* The version.
*/
version: AuxVersion;
/**
* The device.
*/
device: AuxDevice;
/**
* The player bot.
*/
playerBot: RuntimeBot;
/**
* The current energy that the context has.
*/
energy: number;
/**
* The number of miliseconds since the session has started.
*/
localTime: number;
/**
* The unix time that the session started at.
*/
startTime: number;
/**
* Whether async API actions should be mocked.
*/
mockAsyncActions: boolean;
/**
* The global values that the context is using.
*/
global: any;
/**
* The pseudo-random number generator that should be used by the context.
*/
pseudoRandomNumberGenerator: seedrandom.PRNG;
/**
* Gets or sets the calculated latency between this client and the inst server in miliseconds.
*/
instLatency: number;
/**
* Gets or sets the calculated time offset between this client and the inst server in miliseconds.
*/
instTimeOffset: number;
/**
* Gets or sets the difference between time offsets that are included in the calculated inst time offset.
* Values are in miliseconds.
* Can be a useful indicator of closely the local clock has been synced to the server clock.
*/
instTimeOffsetSpread: number;
/**
* Whether to force the context to produce async tasks that always have unguessable IDs.
* Defaults to false.
*/
forceUnguessableTaskIds: boolean;
/**
* Enqueues the given action.
* @param action The action to enqueue.
*/
enqueueAction(action: RuntimeActions): void;
/**
* Gets the list of actions that have been queued and resets the action queue.
*/
dequeueActions(): RuntimeActions[];
/**
* Records the given error.
* @param error The error to record.
*/
enqueueError(error: ScriptError | RanOutOfEnergyError): void;
/**
* Gets the list of errors that have been queued and resets the error queue.
*/
dequeueErrors(): ScriptError[];
/**
* Converts the given bot into a non-script enabled version.
* @param bot The bot.
*/
unwrapBot(bot: Bot | BotTags): Bot | BotTags;
/**
* Adds the given bot to the state and creates a new script bot to represent it.
* @param bot The bot that should be created.
*/
createBot(bot: Bot): RuntimeBot;
/**
* Destroys the given bot.
* @param bot The bot to destroy.
*/
destroyBot(bot: RuntimeBot): void;
/**
* Gets the list of bot IDs that have a listener for the given tag.
* @param tag The tag.
*/
getBotIdsWithListener(tag: string): string[];
/**
* Records whether the given ID has a listener for the given tag.
* @param id The ID of the bot.
* @param tag The tag that the bot has a listener for.
* @param hasListener Whether the bot has a listener for the given tag.
*/
recordListenerPresense(id: string, tag: string, hasListener: boolean): void;
/**
* Records the given bot timer for the bot.
* @param id The ID of the bot.
* @param info The timer info.
*/
recordBotTimer(id: string, info: BotTimer): void;
/**
* Removes the given bot timer from the bot.
* Note that this does not cancel the timer, it only removes it from the timer record.
* @param id The ID of the bot.
* @param type The type of the timer.
* @param timer The timer to remove.
*/
removeBotTimer(id: string, type: BotTimer['type'], timerId: number): void;
/**
* Processes the given bot timer resulit.
* For native runtimes this does nothing, but for interpreted runtimes this ensures that the generator breakpoints are correctly processed by the runtime.
* @param result The result that should be processed.
*/
processBotTimerResult(result: void | Generator<InterpreterStop, any, InterpreterContinuation>): void;
/**
* Gets the list of bot timers for the given bot.
* @param id The ID of the bot.
*/
getBotTimers(id: string): BotTimer[];
/**
* Gets the list of bot timers that were setup to watch the given bot ID.
* @param id The ID of the bot that the timers are watching.
*/
getWatchersForBot(id: string): WatchBotTimer[];
/**
* Gets the list of portal timers that were setup to watch the given portal ID.
* @param id The ID of the portal that the timers are watching.
*/
getWatchersForPortal(id: string): WatchPortalTimer[];
/**
* Gets the list of portal IDs that are being watched.
*/
getWatchedPortals(): Set<string>;
/**
* Cancels the timer with the given timer ID and bot ID.
* @param id The ID of the bot.
* @param timerId The ID of the timer.
*/
cancelAndRemoveBotTimer(id: string, type: BotTimer['type'], timerId: number): void;
/**
* Cancels the list of timers for the given bot ID.
* @param id The ID of the bot.
*/
cancelBotTimers(id: string): void;
/**
* Cancels all the timers that bots have created.
*/
cancelAllBotTimers(): void;
/**
* Cancels and removes the timers with the given timer ID.
* @param timerId The ID of the timer.
* @param type The type of the timers to cancel. If null, timers of all types are canceled.
*/
cancelAndRemoveTimers(timerId: number, type?: string): void;
/**
* Gets the number of timers.
*/
getNumberOfActiveTimers(): number;
/**
* Creates a new task.
* @param unguessableId Whether to use an unguessable task ID. Defaults to false.
* @param allowRemoteResolution Whether the task is allowed to be resolved via a remote action result. Defaults to false.
*/
createTask(unguessableId?: boolean, allowRemoteResolution?: boolean): AsyncTask;
/**
* Creates a new iterable task.
* @param unguessableId Whether to use an unguessable task ID. Defaults to false.
* @param allowRemoteResolution Whether the task is allowed to be resolved via a remote action result. Defaults to false.
*/
createIterable(unguessableId?: boolean, allowRemoteResolution?: boolean): AsyncIterableTask;
/**
* Completes the task with the given task ID with the given result.
* Returns whether the task was handled by this context.
* @param taskId The ID of the task.
* @param result The result.
* @param remote Whether this call is being triggered from a remote device.
* This should be true if resolveTask() is being called in response to a remote or device action.
*/
resolveTask(taskId: number | string, result: any, remote: boolean): boolean;
/**
* Completes the task with the given task ID with the given error.
* * Returns whether the task was handled by this context.
* @param taskId The ID of the task.
* @param error The error.
* @param remote Whether this call is being triggered from a remote device.
* This should be true if resolveTask() is being called in response to a remote or device action.
*/
rejectTask(taskId: number | string, error: any, remote: boolean): boolean;
/**
* Provides the next value for the given iterable task.
* @param taskId The ID of the task.
* @param value The value to provide.
* @param remote Whether this call is being triggered from a remote device.
* This should be true if resolveTask() is being called in response to a remote or device action.
*/
iterableNext(taskId: number | string, value: any, remote: boolean): boolean;
/**
* Completes the iterable task.
* @param taskId The ID of the task.
* @param remote Whether this call is being triggered from a remote device.
* This should be true if resolveTask() is being called in response to a remote or device action.
*/
iterableComplete(taskId: number | string, remote: boolean): boolean;
/**
* Instructs the iterable task to throw the given error.
* @param taskId The ID of the task.
* @param value The value to provide.
* @param remote Whether this call is being triggered from a remote device.
* This should be true if resolveTask() is being called in response to a remote or device action.
*/
iterableThrow(taskId: number | string, value: any, remote: boolean): boolean;
/**
* Gets a list of timers that contains the amount of time a tag has run for in miliseconds.
*/
getShoutTimers(): {
tag: string;
timeMs: number;
}[];
/**
* Adds the given number of miliseconds to the timer for the given shout.
* @param shout The name of the shout.
* @param ms The number of miliseconds to add.
*/
addShoutTime(shout: string, ms: number): void;
/**
* Gets information on how long it took different aspects of the instance to load.
*/
getLoadTimes(): {
[key: string]: number;
};
/**
* Records the given time to the load times object.
* @param key The key that indicates what the time represents.
* @param ms The number of miliseconds.
*/
setLoadTime(key: string, ms: number): void;
/**
* Starts the animation loop for the context.
*/
startAnimationLoop(): SubscriptionLike;
/**
* Creates a UUID.
*/
uuid(): string;
/**
* Sets the data that should be used to mock the given function.
* @param func The function that the return values should be set for.
* @param returnValues The list of return values that should be used for the mock.
*/
setMockReturns(func: any, returnValues: any[]): void;
/**
* Sets the data that should be used to mock the given function for the given arguments.
* @param func The function.
* @param args The arguments that should be matched against.
* @param returnValue The return value that should be used for the mock.
*/
setMockReturn(func: any, args: any[], returnValue: any): void;
/**
* Gets the data that should be used as the function's return value.
* @param func The function.
*/
getNextMockReturn(func: any, functionName: string, args: any[]): any;
}
/**
* Defines an interface for an asynchronous task.
*/
export interface AsyncTask {
/**
* The ID of the task.
*/
taskId: number | string;
/**
* Whether the task is allowed to be resolved via a remote action result.
*/
allowRemoteResolution: boolean;
/**
* The promise that the task contains.
*/
promise: Promise<any>;
/**
* The function that is used to resolve the task with a result.
*/
resolve: (val: any) => void;
/**
* The function that is used to reject the task with an error.
*/
reject: (err: any) => void;
}
export type AsyncIterableTaskPromiseResult = {
iterable: AsyncIterable<any>;
result: any;
};
/**
* Defines an interface for an asynchronous iterable task.
* The task can be used in one of two ways:
*
* 1. The task can be used to provide an async iterable that can be used to stream values to the caller.
* In this case, the caller will be provided with the iterable directly and values can be sent to it via the next(), complete(), and throw() functions.
* 2. The task can be used to provide a promise that resolves with an async iterable that can be used to stream values to the caller.
* In this case, the caller will be provided with the promise and it will be resolved with the iterable either when the resolve() function is called or when the next() function is called.
*/
export interface AsyncIterableTask extends AsyncTask {
/**
* The promise that the task contains.
*/
promise: Promise<AsyncIterableTaskPromiseResult>;
/**
* The iterable that the task contains.
*/
iterable: AsyncIterable<any>;
/**
* The subject that the iterable uses to provide values.
*/
subject: ReplaySubject<any>;
/**
* Resolves the promise of the task.
* @param value The value to resolve with.
*/
resolve: (value: any) => void;
/**
* The next value to provide to the iterablwe.
* @param val The value to provide.
*/
next: (val: any) => void;
/**
* Completes the iterable.
*/
complete: () => void;
/**
* Throws the given error.
* @param err The error to throw.
*/
throw: (err: any) => void;
}
/**
* Defines an interface for a timer that was created by a bot (e.g. setTimeout() or setInterval()).
*/
export type BotTimer = TimeoutOrIntervalTimer | AnimationTimer | WatchPortalTimer | WatchBotTimer;
/**
* Defines an interface for a setTimeout() or setInterval() timer that was created by a bot.
*/
export interface TimeoutOrIntervalTimer {
/**
* The ID of the timer.
*/
timerId: number;
/**
* The type of the timer.
*/
type: 'timeout' | 'interval';
}
/**
* Defines an interface for a animation timer that was created by a bot.
*/
export interface AnimationTimer {
/**
* The ID of the timer.
*/
timerId: number;
/**
* The type of the timer.
*/
type: 'animation';
/**
* The tag that the timer is for.
*/
tag: string;
/**
* The group ID that the timer exists in.
*/
groupId?: string;
/**
* A function used to cancel the timer.
*/
cancel: () => void;
}
/**
* Defines an interface for a subscription to watching a set of bots that was created by a bot.
*/
export interface WatchPortalTimer {
/**
* The ID of the timer.
*/
timerId: number;
/**
* The type of the timer.
*/
type: 'watch_portal';
/**
* The tag that the timer is for.
*/
tag: string;
/**
* The ID of the portal that the timer is for.
*/
portalId: string;
/**
* The function that should be called when the portal changes.
*/
handler: () => void | Generator<InterpreterStop, any, InterpreterContinuation>;
}
/**
* Defines an interface for a subscription to watching a set of bots that was created by a bot.
*/
export interface WatchBotTimer {
/**
* The ID of the timer.
*/
timerId: number;
/**
* The type of the timer.
*/
type: 'watch_bot';
/**
* The tag that the timer was created by.
*/
tag: string;
/**
* The ID of the bot that the timer is for.
*/
botId: string;
/**
* The function that should be called when the bot changes.
*/
handler: () => void | Generator<InterpreterStop, any, InterpreterContinuation>;
}
/**
* Inserts the given bot into the global context.
* @param context The context.
* @param bot The bot.
*/
export declare function addToContext(context: AuxGlobalContext, ...bots: RuntimeBot[]): void;
/**
* Removes the given bots from the given context.
* @param context The context that the bots should be removed from.
* @param bots The bots that should be removed.
*/
export declare function removeFromContext(context: AuxGlobalContext, bots: RuntimeBot[], cancelTimers?: boolean): void;
/**
* Gets whether a bot with the given ID is in the given context.
* @param context The context.
* @param bot The bot.
*/
export declare function isInContext(context: AuxGlobalContext, bot: Bot): boolean;
/**
* Defines a global context that stores all information in memory.
*/
export declare class MemoryGlobalContext implements AuxGlobalContext {
/**
* The ordered list of script bots.
*/
bots: RuntimeBot[];
/**
* The state that the runtime bots occupy.
*/
state: RuntimeBotsState;
/**
* The list of actions that have been queued.
*/
actions: RuntimeActions[];
/**
* The list of errors that have been queued.
*/
errors: ScriptError[];
/**
* The map of task IDs to tasks.
*/
tasks: Map<number | string, AsyncTask>;
/**
* The map of task IDs to iterable tasks.
*/
iterableTasks: Map<number | string, AsyncIterableTask>;
/**
* The version.
*/
version: AuxVersion;
/**
* The device.
*/
device: AuxDevice;
/**
* The player bot.
*/
playerBot: RuntimeBot;
/**
* The current energy that the context has.
*/
energy: number;
/**
* Whether async API actions should be mocked.
*/
mockAsyncActions: boolean;
pseudoRandomNumberGenerator: seedrandom.PRNG;
global: any;
uuid: (<T extends ArrayLike<number>>(options: import("uuid").V4Options | null | undefined, buffer: T, offset?: number) => T) & ((options?: import("uuid").V4Options) => string);
instLatency: number;
instTimeOffset: number;
instTimeOffsetSpread: number;
forceUnguessableTaskIds: boolean;
get localTime(): number;
get startTime(): number;
private _taskCounter;
private _scriptFactory;
private _batcher;
private _generatorProcessor;
private _shoutTimers;
private _listenerMap;
private _botTimerMap;
private _botWatcherMap;
private _portalWatcherMap;
private _numberOfTimers;
private _startTime;
private _animationLoop;
private _mocks;
private _loadTimes;
/**
* Creates a new global context.
* @param version The version number.
* @param device The device that we're running on.
* @param scriptFactory The factory that should be used to create new script bots.
* @param batcher The batcher that should be used to batch changes.
* @param generatorProcessor The processor that should be used to process generators created from bot timer handlers.
*/
constructor(version: AuxVersion, device: AuxDevice, scriptFactory: RuntimeBotFactory, batcher: RuntimeBatcher, generatorProcessor: RuntimeInterpreterGeneratorProcessor);
getBotIdsWithListener(tag: string): string[];
recordListenerPresense(id: string, tag: string, hasListener: boolean): void;
recordBotTimer(id: string, info: BotTimer): void;
removeBotTimer(id: string, type: BotTimer['type'], timer: number | string): void;
processBotTimerResult(result: void | Generator<InterpreterStop, any, InterpreterContinuation>): void;
getBotTimers(id: string): BotTimer[];
getWatchersForBot(id: string): WatchBotTimer[];
getWatchersForPortal(id: string): WatchPortalTimer[];
getWatchedPortals(): Set<string>;
cancelAndRemoveBotTimer(id: string, type: BotTimer['type'], timerId: number): void;
cancelBotTimers(id: string): void;
cancelAllBotTimers(): void;
cancelAndRemoveTimers(timerId: number, type?: string): void;
getNumberOfActiveTimers(): number;
private _clearTimers;
private _clearTimer;
/**
* Enqueues the given action.
* @param action The action to enqueue.
*/
enqueueAction(action: RuntimeActions): void;
dequeueActions(): RuntimeActions[];
enqueueError(error: ScriptError | RanOutOfEnergyError): void;
dequeueErrors(): ScriptError[];
/**
* Converts the given bot into a non-script enabled version.
* @param bot The bot.
*/
unwrapBot(bot: Bot | BotTags): Bot | BotTags;
createBot(bot: Bot): RuntimeBot;
/**
* Destroys the given bot.
* @param bot The bot to destroy.
*/
destroyBot(bot: RuntimeBot): void;
createTask(unguessableId: boolean, allowRemoteResolution: boolean): AsyncTask;
createIterable(unguessableId?: boolean, allowRemoteResolution?: boolean): AsyncIterableTask;
iterableNext(taskId: string | number, value: any, remote: boolean): boolean;
iterableComplete(taskId: string | number, remote: boolean): boolean;
iterableThrow(taskId: string | number, value: any, remote: boolean): boolean;
resolveTask(taskId: number | string, result: any, remote: boolean): boolean;
rejectTask(taskId: number | string, error: any, remote: boolean): boolean;
getShoutTimers(): {
tag: string;
timeMs: number;
}[];
addShoutTime(shout: string, ms: number): void;
getLoadTimes(): {
[key: string]: number;
};
setLoadTime(key: string, ms: number): void;
startAnimationLoop(): SubscriptionLike;
/**
* Sets the data that should be used to mock the given function.
* @param func The function that the return values should be set for.
* @param returnValues The list of return values that should be used for the mock.
*/
setMockReturns(func: any, returnValues: any[]): void;
/**
* Sets the data that should be used to mock the given function for the given arguments.
* @param func The function.
* @param args The arguments that should be matched against.
* @param returnValue The return value that should be used for the mock.
*/
setMockReturn(func: any, args: any[], returnValue: any): void;
/**
* Gets the data that should be used as the function's return value.
* @param func The function.
*/
getNextMockReturn(func: any, functionName: string, args: any[]): any;
private _updateAnimationLoop;
}
/**
* Creates a debug string that is useful for visualizing a function call.
* @param functionName The name of the function.
* @param args The arguments that were passed to the function.
* @returns
*/
export declare function debugStringifyFunction(functionName: string, args: any[]): string;
/**
* Creates a debug string from the given value.
* @param value
* @returns
*/
export declare function debugStringify(value: any): string;
//# sourceMappingURL=AuxGlobalContext.d.ts.map